---
title: "Speak AI dashboards and share link settings"
description: "Create and update Speak AI analytics dashboards, and choose what their share link shows: custom fields, feedback, labels, comments and reviewers."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.speakai.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Speak AI dashboards and share link settings


import EndpointIndex from "@/components/api/EndpointIndex.astro";

The Speak AI API exposes 3 dashboards endpoints under the base URL `https://api.speakai.co/v1`. Every request needs the `x-speakai-key` and `x-access-token` headers described in [Authentication](/api/authentication/).

Create and update analytics dashboards, including the viewer settings that decide what a dashboard's share link shows: custom fields, the Feedback button, labels, comments, and, through the feedback submitter names, who a viewer may write as.

## Labels and comments on a share link

| Setting | Shape | Rule |
| --- | --- | --- |
| `labels` | `{ isEnabled, mode: "view" \| "apply", labelGroupIds }` | `labelGroupIds` (at most 100) must be active label groups of your company (400 on save). Empty means every active label. |
| `comments` | `{ isEnabled, mode: "view" \| "reply" }` | |

Each section replaces itself when sent and keeps its stored value when left out. Everything is off and read-only until you turn it on. Viewers use the [shared link](/api/shared-links/) routes.

## What can you do with the dashboards endpoints?

Speak AI groups these 3 endpoints under the dashboards resource. Each entry below links to the full reference for that endpoint further down this page.

| Method | Path | What it does |
| --- | --- | --- |
| `POST` | [`/dashboards`](#post-dashboards) | Create a dashboard |
| `PUT` | [`/dashboards/{dashboardId}`](#put-dashboards-dashboard-id) | Update a dashboard |
| `POST` | [`/dashboards/{dashboardId}/profile-image`](#post-dashboards-dashboard-id-profile-image) | Upload a profile image |

<h2 id="post-dashboards">Create a dashboard</h2>

Create an analytics dashboard. Only `spec` is required. Creating a dashboard does not share it; the share link is made from the app.

#### Viewer settings

`settings` controls what viewers of the dashboard's share link see on each media page. Each section (`fields`, `feedback`, `labels`, `comments`) is saved on its own: the section you send replaces the stored one in full, and a section you leave out keeps its stored value. Read the dashboard first and resend every key of the section you change.

Labels and comments are off until you turn them on. With `labels.mode` set to `apply` or `comments.mode` set to `reply`, a viewer picks one of the dashboard's feedback submitter names (`feedback.submitters`, even while feedback itself is off), or types another name when `feedback.allowOtherSubmitter` is on, and writes under that name. With no names and other names off, nobody can write. The link has no sign-in, so these writes are not authenticated: the link holder chooses the name and Speak AI records the entry under it without checking who sent it, the same as feedback. Only the dashboard's feedback names are accepted, plus any other name when `feedback.allowOtherSubmitter` is on. Speak AI accepts this risk by design and limits it: every entry written through the link is shown as made via the dashboard, a name can change or delete only the entries written under it from that dashboard, a name that is not allowed is refused on every write, and revoking the link stops every write at once. List only the names you are happy for link holders to write as.

#### Errors

- `400` when a field fails validation, the spec is invalid, the payload is too large, or a label group is not an active group of your company ("Choose active label groups from this workspace."). Nothing is saved.

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `spec` | object, **required** | The dashboard itself: `title` (1 to 60 characters), `description` (up to 280), `source` (`{"type": "workspace"}`, `{"type": "team"}` or `{"type": "folders", "folderIds": [...]}`), `dateRange` (`{"preset": "last30days"}`), `sections` and `widgets`. It is checked against the dashboard spec schema, and unknown keys return 400. |
| `icon` | string | Icon identifier. Optional. An empty string is allowed. |
| `assignTo` | string[] | User ids, or group ids written as `<groupId> (G)`, that can view the dashboard. Optional. |
| `filters` | object | Saved filters for the dashboard. Optional. Up to 100 keys; `filterList` holds up to 20 filters. |
| `settings` | object | What viewers of the dashboard's share link see on each media page. Optional. Every section is saved on its own: a section you send replaces that whole section, and a section you leave out keeps its stored value. Unknown keys return 400. |
| `settings.fields` | object | Which custom fields the media page shows, and how its Fields tab groups them. |
| `settings.feedback` | object | The Feedback button on the media page. |
| `settings.labels` | object | Labels on the shared media pages. Off unless you turn it on. |
| `settings.comments` | object | Comments on the shared media pages. Off unless you turn it on. |
| `settings.profiles` | object[] | Profiles: an image, a description and a link for values of a custom field, such as speakers, events or sponsors. Up to 5 groups, one per field (a field may appear only once). Sending `profiles` replaces the whole list. On an update it also needs the dashboard's current `revision` at the top level of the body: without it the request returns 400, and a stale one returns 409. Saving only `profiles` does not change which fields media pages show. Names, images, descriptions and links are visible to anyone with the dashboard link. Optional. |
| `isDefault` | boolean | Make this your default dashboard. Setting it clears the flag on your other dashboards. Optional. |

<details>
<summary>`settings.fields` -- 3 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `includeIds` | string[], **required** | Field ids shown, in this order, private fields included. Empty shows the company's public fields. Required in the section. Ids that are not fields of your company are dropped and listed in `droppedFieldIds`. |
| `orderIds` | string[] | Used only when `includeIds` is empty: these fields show first, in this order. Optional. |
| `groups` | object[], **required** | Pills on the Fields tab. Unique by `key`. Required in the section; send an empty array for none. |
| `groups[].key` | string, **required** | Stable key of the group, unique in the list. |
| `groups[].label` | string, **required** | Name shown on the pill. |
| `groups[].fieldIds` | string[], **required** | Field ids in the group, in order. At least one. |

</details>

<details>
<summary>`settings.feedback` -- 9 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `isEnabled` | boolean, **required** | Show the Feedback button. |
| `fieldIds` | string[], **required** | Fields a reviewer scores. Empty means every field the page shows. |
| `submitters` | string[], **required** | Names a reviewer picks from. Empty lets them type their own. |
| `removeReasons` | string[], **required** | Reasons for removing a call from scoring. Empty hides that option. |
| `reviewScope` | string | `dashboard` (the default) or `company`. Optional. One of: `dashboard`, `company` . |
| `allowOtherSubmitter` | boolean | Lets a reviewer type a name that is not in `submitters`. Optional. |
| `groups` | object[] | Pills in the Feedback dialog. Optional. |
| `groups[].key` | string, **required** | Stable key of the group, unique in the list. |
| `groups[].label` | string, **required** | Name shown on the pill. |
| `groups[].fieldIds` | string[], **required** | Field ids in the group, in order. At least one. |
| `fieldRules` | object | Per field id: an optional row `label` and the allowed `min` and `max` score. Optional. |
| `sheetWebhookUrl` | string | Google Apps Script web app URL that receives one row per submission. Never shown to viewers. Optional. |

</details>

<details>
<summary>`settings.labels` -- 3 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `isEnabled` | boolean, **required** | Show labels on media pages opened from the share link. |
| `mode` | string, **required** | `view` shows labels read-only. `apply` also lets a viewer add and remove labels under one of the reviewer names. One of: `view`, `apply` . |
| `labelGroupIds` | string[], **required** | Label groups the link shows and offers. Up to 100 group ids, no repeats. Empty means every active label. Each must be an active label group of your company, or the whole save returns 400 "Choose active label groups from this workspace." Groups are refused rather than dropped, because dropping them all would widen the link to every label. If every chosen group is archived later, the link shows no labels. |

</details>

<details>
<summary>`settings.comments` -- 2 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `isEnabled` | boolean, **required** | Show comments on media pages opened from the share link. |
| `mode` | string, **required** | `view` shows comments read-only. `reply` also lets a viewer comment and reply under one of the reviewer names. One of: `view`, `reply` . |

</details>

<details>
<summary>`settings.profiles` -- 4 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `fieldId` | string, **required** | Id of the custom field the profiles are for. Required. |
| `label` | string, **required** | Name of the group, such as `Speakers`. 1 to 40 characters. Required. |
| `imageShape` | string | How images are cropped. Optional; round when left out. One of: `round`, `square` . |
| `entries` | object[], **required** | Up to 60 profiles. Required; send an empty array for none. |
| `entries[].id` | string | Stable id of the entry: lowercase letters, digits and hyphens, up to 64 characters. Optional. |
| `entries[].name` | string, **required** | The field value this profile is for, up to 80 characters. It matches the value ignoring case and extra spaces, and a name may appear only once in a group. Required. |
| `entries[].imageKey` | string | The `imageKey` returned by `POST /dashboards/{dashboardId}/profile-image`, or one read back from the dashboard unchanged. Optional. |
| `entries[].description` | string | Plain text shown with the profile, up to 600 characters. Optional. |
| `entries[].link` | string | An `http` or `https` link, up to 2048 characters. Optional. |

</details>

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/dashboards' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "spec": {
"title": "Sales calls",
"source": {
  "type": "workspace"
},
"dateRange": {
  "preset": "last30days"
},
"sections": [],
"widgets": []
  },
  "settings": {
"feedback": {
  "isEnabled": true,
  "fieldIds": [],
  "submitters": [
    "Reviewer A",
    "Reviewer B"
  ],
  "removeReasons": []
},
"labels": {
  "isEnabled": true,
  "mode": "apply",
  "labelGroupIds": [
    "Gr7kQ2pLm9xZ"
  ]
},
"comments": {
  "isEnabled": true,
  "mode": "reply"
}
  }
}'
```

</CodePanel>

<ResponsePanel id="post-dashboards" statuses={[{"code":"200","description":"Success"},{"code":"400","description":"Validation failed"}]}>

<div slot="status-200">

**`200` Success**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `success` on every 2xx response. One of: `success` . |
| `data` | object |  |
| `data.dashboardId` | string | Id of the new dashboard. |
| `data.droppedFieldIds` | string[] | Field ids removed from `settings` because they are not fields of your company. Present only when some were removed. |
| `data.message` | string | Confirmation text. |

</div>

<div slot="status-400">

**`400` Validation failed**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

</ResponsePanel>

</div>

<h2 id="put-dashboards-dashboard-id">Update a dashboard</h2>

Update a dashboard. Send only the keys you want to change. To change the dashboard itself, send the full `spec` with the `revision` you read: the write is accepted only while it still matches, and returns 409 otherwise. Settings, icon, sharing, filters and the default flag can be changed without a `spec`.

#### Viewer settings

`settings` controls what viewers of the dashboard's share link see on each media page. Each section (`fields`, `feedback`, `labels`, `comments`, `profiles`) is saved on its own: the section you send replaces the stored one in full, and a section you leave out keeps its stored value. Read the dashboard first and resend every key of the section you change.

Labels and comments are off until you turn them on. With `labels.mode` set to `apply` or `comments.mode` set to `reply`, a viewer picks one of the dashboard's feedback submitter names (`feedback.submitters`, even while feedback itself is off), or types another name when `feedback.allowOtherSubmitter` is on, and writes under that name. With no names and other names off, nobody can write. The link has no sign-in, so these writes are not authenticated: the link holder chooses the name and Speak AI records the entry under it without checking who sent it, the same as feedback. Only the dashboard's feedback names are accepted, plus any other name when `feedback.allowOtherSubmitter` is on. Speak AI accepts this risk by design and limits it: every entry written through the link is shown as made via the dashboard, a name can change or delete only the entries written under it from that dashboard, a name that is not allowed is refused on every write, and revoking the link stops every write at once. List only the names you are happy for link holders to write as.

#### Errors

- `400` when a field fails validation, the spec is invalid, the payload is too large, or a label group is not an active group of your company ("Choose active label groups from this workspace."). Nothing is saved.
- `404` when the dashboard does not exist or you cannot edit it.
- `409` when the spec `revision` is stale: "Dashboard was modified by another update. Reload and try again."

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `dashboardId` | path | string | Yes | Id of the dashboard, as returned when it was created. |

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `spec` | object | The dashboard itself: `title` (1 to 60 characters), `description` (up to 280), `source` (`{"type": "workspace"}`, `{"type": "team"}` or `{"type": "folders", "folderIds": [...]}`), `dateRange` (`{"preset": "last30days"}`), `sections` and `widgets`. It is checked against the dashboard spec schema, and unknown keys return 400. When sent it must be the full spec, with `revision`. |
| `revision` | number | The dashboard's current revision, a whole number. Required when you send `settings.profiles` without a `spec`; a stale one returns 409. |
| `icon` | string | Icon identifier. Optional. An empty string is allowed. |
| `assignTo` | string[] | User ids, or group ids written as `<groupId> (G)`, that can view the dashboard. Optional. |
| `filters` | object | Saved filters for the dashboard. Optional. Up to 100 keys; `filterList` holds up to 20 filters. |
| `settings` | object | What viewers of the dashboard's share link see on each media page. Optional. Every section is saved on its own: a section you send replaces that whole section, and a section you leave out keeps its stored value. Unknown keys return 400. |
| `settings.fields` | object | Which custom fields the media page shows, and how its Fields tab groups them. |
| `settings.feedback` | object | The Feedback button on the media page. |
| `settings.labels` | object | Labels on the shared media pages. Off unless you turn it on. |
| `settings.comments` | object | Comments on the shared media pages. Off unless you turn it on. |
| `settings.profiles` | object[] | Profiles: an image, a description and a link for values of a custom field, such as speakers, events or sponsors. Up to 5 groups, one per field (a field may appear only once). Sending `profiles` replaces the whole list. On an update it also needs the dashboard's current `revision` at the top level of the body: without it the request returns 400, and a stale one returns 409. Saving only `profiles` does not change which fields media pages show. Names, images, descriptions and links are visible to anyone with the dashboard link. Optional. |
| `isDefault` | boolean | Make this your default dashboard. Setting it clears the flag on your other dashboards. Optional. |

<details>
<summary>`settings.fields` -- 3 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `includeIds` | string[], **required** | Field ids shown, in this order, private fields included. Empty shows the company's public fields. Required in the section. Ids that are not fields of your company are dropped and listed in `droppedFieldIds`. |
| `orderIds` | string[] | Used only when `includeIds` is empty: these fields show first, in this order. Optional. |
| `groups` | object[], **required** | Pills on the Fields tab. Unique by `key`. Required in the section; send an empty array for none. |
| `groups[].key` | string, **required** | Stable key of the group, unique in the list. |
| `groups[].label` | string, **required** | Name shown on the pill. |
| `groups[].fieldIds` | string[], **required** | Field ids in the group, in order. At least one. |

</details>

<details>
<summary>`settings.feedback` -- 9 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `isEnabled` | boolean, **required** | Show the Feedback button. |
| `fieldIds` | string[], **required** | Fields a reviewer scores. Empty means every field the page shows. |
| `submitters` | string[], **required** | Names a reviewer picks from. Empty lets them type their own. |
| `removeReasons` | string[], **required** | Reasons for removing a call from scoring. Empty hides that option. |
| `reviewScope` | string | `dashboard` (the default) or `company`. Optional. One of: `dashboard`, `company` . |
| `allowOtherSubmitter` | boolean | Lets a reviewer type a name that is not in `submitters`. Optional. |
| `groups` | object[] | Pills in the Feedback dialog. Optional. |
| `groups[].key` | string, **required** | Stable key of the group, unique in the list. |
| `groups[].label` | string, **required** | Name shown on the pill. |
| `groups[].fieldIds` | string[], **required** | Field ids in the group, in order. At least one. |
| `fieldRules` | object | Per field id: an optional row `label` and the allowed `min` and `max` score. Optional. |
| `sheetWebhookUrl` | string | Google Apps Script web app URL that receives one row per submission. Never shown to viewers. Optional. |

</details>

<details>
<summary>`settings.labels` -- 3 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `isEnabled` | boolean, **required** | Show labels on media pages opened from the share link. |
| `mode` | string, **required** | `view` shows labels read-only. `apply` also lets a viewer add and remove labels under one of the reviewer names. One of: `view`, `apply` . |
| `labelGroupIds` | string[], **required** | Label groups the link shows and offers. Up to 100 group ids, no repeats. Empty means every active label. Each must be an active label group of your company, or the whole save returns 400 "Choose active label groups from this workspace." Groups are refused rather than dropped, because dropping them all would widen the link to every label. If every chosen group is archived later, the link shows no labels. |

</details>

<details>
<summary>`settings.comments` -- 2 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `isEnabled` | boolean, **required** | Show comments on media pages opened from the share link. |
| `mode` | string, **required** | `view` shows comments read-only. `reply` also lets a viewer comment and reply under one of the reviewer names. One of: `view`, `reply` . |

</details>

<details>
<summary>`settings.profiles` -- 4 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `fieldId` | string, **required** | Id of the custom field the profiles are for. Required. |
| `label` | string, **required** | Name of the group, such as `Speakers`. 1 to 40 characters. Required. |
| `imageShape` | string | How images are cropped. Optional; round when left out. One of: `round`, `square` . |
| `entries` | object[], **required** | Up to 60 profiles. Required; send an empty array for none. |
| `entries[].id` | string | Stable id of the entry: lowercase letters, digits and hyphens, up to 64 characters. Optional. |
| `entries[].name` | string, **required** | The field value this profile is for, up to 80 characters. It matches the value ignoring case and extra spaces, and a name may appear only once in a group. Required. |
| `entries[].imageKey` | string | The `imageKey` returned by `POST /dashboards/{dashboardId}/profile-image`, or one read back from the dashboard unchanged. Optional. |
| `entries[].description` | string | Plain text shown with the profile, up to 600 characters. Optional. |
| `entries[].link` | string | An `http` or `https` link, up to 2048 characters. Optional. |

</details>

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X PUT 'https://api.speakai.co/v1/dashboards/Db4kX9mQ2pLr' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "settings": {
"labels": {
  "isEnabled": true,
  "mode": "apply",
  "labelGroupIds": [
    "Gr7kQ2pLm9xZ"
  ]
},
"comments": {
  "isEnabled": true,
  "mode": "reply"
}
  }
}'
```

</CodePanel>

<ResponsePanel id="put-dashboards-dashboard-id" statuses={[{"code":"200","description":"Success"},{"code":"400","description":"Validation failed"},{"code":"404","description":"The dashboard does not exist or you cannot edit it"},{"code":"409","description":"The spec revision is stale"}]}>

<div slot="status-200">

**`200` Success**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `success` on every 2xx response. One of: `success` . |
| `data` | object |  |
| `data.dashboardId` | string | Id of the dashboard. |
| `data.revision` | integer | The dashboard's revision after the update. |
| `data.droppedFieldIds` | string[] | Field ids removed from `settings` because they are not fields of your company. Present only when some were removed. |
| `data.message` | string | Confirmation text. |

</div>

<div slot="status-400">

**`400` Validation failed**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

<div slot="status-404">

**`404` The dashboard does not exist or you cannot edit it**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

<div slot="status-409">

**`409` The spec revision is stale**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

</ResponsePanel>

</div>

<h2 id="post-dashboards-dashboard-id-profile-image">Upload a profile image</h2>

Upload one image for a dashboard profile, then put the returned `imageKey` on the profile entry in `settings.profiles` and save the dashboard with `PUT /dashboards/{dashboardId}`. Uploading alone does not change the dashboard.

Send the file as multipart form data, for example `-F 'image=@speaker.png'`. Send exactly one JPEG, PNG, WebP or GIF image of up to 2 MB. The server checks the file's content, not its name or declared type.

Only people who can edit the dashboard can upload. Each user can upload up to 30 images in 10 minutes.

#### Errors

- `400` when there is not exactly one file, or the file is not a JPEG, PNG, WebP or GIF of up to 2 MB: "Upload one JPEG, PNG, WEBP, or GIF image of up to 2 MB."
- `404` when the dashboard does not exist or you cannot edit it.
- `429` after 30 uploads in 10 minutes.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `dashboardId` | path | string | Yes | Id of the dashboard, as returned when it was created. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/dashboards/Db4kX9mQ2pLr/profile-image' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -F 'image='
```

</CodePanel>

<ResponsePanel id="post-dashboards-dashboard-id-profile-image" statuses={[{"code":"200","description":"Success"},{"code":"400","description":"Not exactly one JPEG, PNG, WebP or GIF image of up to 2 MB"},{"code":"404","description":"The dashboard does not exist or you cannot edit it"},{"code":"429","description":"More than 30 uploads in 10 minutes"}]}>

<div slot="status-200">

**`200` Success**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `success` on every 2xx response. One of: `success` . |
| `data` | object |  |
| `data.imageKey` | string | Where the image is stored. Put it on a profile entry as `imageKey` and save the dashboard. |
| `data.imageUrl` | string | A signed link to preview the image. It expires, so do not store it. |

</div>

<div slot="status-400">

**`400` Not exactly one JPEG, PNG, WebP or GIF image of up to 2 MB**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

<div slot="status-404">

**`404` The dashboard does not exist or you cannot edit it**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

<div slot="status-429">

**`429` More than 30 uploads in 10 minutes**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `failed`. One of: `failed` . |
| `requestId` | string | Id of this request, for support. |
| `code` | integer | The HTTP status code again. |
| `message` | string | What went wrong, in words you can show to a person. |
| `hints` | string[] | Generic hints for this kind of error. |

</div>

</ResponsePanel>

</div>

## Related pages

- [API reference](/api/) for the base URL, authentication, and the error format.
- [Authenticate with the Speak AI API using access tokens](/api/authentication/)
- [Upload audio and video to Speak AI and read insights](/api/media/)
- [Create and update live transcription sessions](/api/live-transcription/)
- [Analyze text notes with the Speak AI text endpoints](/api/text/)

Get an API key on the [Speak AI developer page](https://app.speakai.co/developers?utm_source=docs&utm_medium=referral&utm_campaign=api-reference&utm_content=api-dashboards).

Source: https://docs.speakai.co/api/dashboards/index.mdx
