---
title: "Collect async voice and video with Speak AI recorders"
description: "Create and clone Speak AI recorders, set their questions and settings, generate share URLs, and read the recordings that respondents submit."
---

> 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.

# Collect async voice and video with Speak AI recorders


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

The Speak AI API exposes 11 recorders and surveys 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/).

Suvery endpoints serve the purpose of operating an surveys: listing the files, getting info, creating\\updating\\deleting a recorder, generating embeddable URL for it.

Embeddable supports checking it's status,uploading of the recordings directly and verification of password to access the recorder as a user.

## What can you do with the recorders and surveys endpoints?

Speak AI groups these 11 endpoints under the recorders and surveys resource. Each entry below links to the full reference for that endpoint further down this page.

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/recorder`](#get-recorder) | Recorder List |
| `GET` | [`/recorder/{recorderId}`](#get-recorder-recorder-id) | Recorder info |
| `DELETE` | [`/recorder/{recorderId}`](#delete-recorder-recorder-id) | Delete Recorder |
| `POST` | [`/recorder/clone`](#post-recorder-clone) | Clone Recorder |
| `POST` | [`/recorder/create`](#post-recorder-create) | Create Recorder |
| `POST` | [`/recorder/questions/{recorderId}`](#post-recorder-questions-recorder-id) | Update Recorder Questions |
| `GET` | [`/recorder/recordings/{recorderId}`](#get-recorder-recordings-recorder-id) | Recording Details |
| `PUT` | [`/recorder/settings/{recorderId}`](#put-recorder-settings-recorder-id) | Update Recorder Settings |
| `GET` | [`/recorder/status/{token}`](#get-recorder-status-token) | Check Recorder Status |
| `GET` | [`/recorder/url/{recorderId}`](#get-recorder-url-recorder-id) | Generate Recorder URL |
| `POST` | [`/recorder/verify`](#post-recorder-verify) | Verify Password |

<h2 id="get-recorder">Recorder List</h2>

#### API Endpoint: Retrieve Recorders

This endpoint retrieves a list of recorders with pagination and sorting options. It allows users to fetch details about available recorders based on specified parameters.

##### Request

**Method:** GET
**URL:** `https://api.speakai.co/v1/recorder`

**Query Parameters:**

- `page` (integer): The page number of the results to retrieve. Default is `0`.

- `pageSize` (integer): The number of records to return per page. Default is `20`.

- `sortBy` (string): The field by which to sort the results, followed by the sorting order. For example, `createdAt:desc` sorts by the creation date in descending order.

##### Response

The response will contain a JSON object with the following structure:

- `status` (string): The status of the request.

- `data` (object): Contains the results of the request.

 - `totalCount` (integer): The total number of recorders available.

 - `page` (integer): The current page number of the results.

 - `recorderList` (array): A list of recorder objects, each containing:

 - `duration` (integer): The duration of the recording.

 - `isAutoAnalyze` (boolean): Indicates if the recorder is set for automatic analysis.

 - `isActive` (boolean): Indicates if the recorder is currently active.

 - `recordings` (array): An array of recordings associated with the recorder.

 - `createdAt` (string): The timestamp when the recorder was created.

 - `updatedAt` (string): The timestamp when the recorder was last updated.

 - `userId` (string): The ID of the user associated with the recorder.

 - `recorderId` (string): The unique ID of the recorder.

 - `token` (string): A token associated with the recorder.

 - `name` (string): The name of the recorder.

 - `meta` (object): Metadata about the recorder, including:

 - `type` (object): Specifies the types of media supported (e.g., video and audio).

 - `client` (object): Information about the client, including name and email.

##### Example Response

``` json
{
 "status": "",
 "data": {
 "totalCount": 0,
 "page": "",
 "recorderList": [
 {
 "duration": 0,
 "isAutoAnalyze": true,
 "isActive": true,
 "recordings": [],
 "createdAt": "",
 "updatedAt": "",
 "userId": "",
 "recorderId": "",
 "token": "",
 "name": "",
 "meta": {
 "type": {
 "video": true,
 "audio": true
 },
 "client": {
 "name": true,
 "email": true
 }
 }
 }
 ]
 }
}

```

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `page` | query | integer | No |  |
| `pageSize` | query | integer | No |  |
| `filterName` | query | string | No |  |
| `sortBy` | query | string | No |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/recorder?page=0&pageSize=20&filterName=recorder&sortBy=createdAt%3Adesc' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-recorder" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.totalCount` | integer |
| `data.page` | string |
| `data.recorderList` | object[] |

Deeper nested fields are not listed. See the example response below for the full shape.

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"totalCount": 1,
"page": "1",
"recorderList": [
  {
    "duration": 120,
    "isAutoAnalyze": false,
    "isActive": true,
    "recordings": [],
    "createdAt": "2020-12-15T14:02:21.615Z",
    "updatedAt": "2020-12-15T14:02:21.616Z",
    "userId": "5d03a9d5d4bca272e9c8cf89",
    "recorderId": "70ea4d569736",
    "token": "recorder-9-4fb7713e267a",
    "name": "recorder-9",
    "meta": {
      "type": {
        "video": false,
        "audio": true
      },
      "client": {
        "name": false,
        "email": false
      }
    }
  }
]
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="get-recorder-recorder-id">Recorder info</h2>

#### API Endpoint: Get Recorder Details

**Method:** GET
**Endpoint:** `https://api.speakai.co/v1/recorder/{recorderId}`

This endpoint retrieves detailed information about a specific recorder identified by the `recorderId`. The response includes various attributes related to the recorder, such as its name, description, user information, recording settings, privacy options, and metadata.

##### Response Structure:

- **status**: Status of the request.

- **data**: Contains the details of the recorder:

- **recorderId**: Unique identifier for the recorder.

- **userId**: Identifier for the user associated with the recorder.

- **name**: Name of the recorder.

- **description**: Description of the recorder.

- **token**: Authentication token for the recorder.

- **recordings**: Array of recordings associated with the recorder.

- **minDuration**: Minimum duration for recordings.

- **maxDuration**: Maximum duration for recordings.

- **privacyMode**: Privacy settings for the recorder.

- **password**: Password for accessing the recorder, if applicable.

- **isAutoAnalyze**: Indicates if automatic analysis is enabled.

- **assignTo**: User or entity to which the recorder is assigned.

- **folderId**: Identifier for the folder containing the recorder.

- **sourceLanguage**: Language settings for the recorder.

- **meta**: Metadata related to the recorder, including:

- **backgroundImg**: Background image URL.

- **logo**: Logo URL.

- **primaryColor**: Primary color used in the recorder interface.

- **type**: Supported types of recordings (audio, video, screen share, etc.).

- **client**: Client-related information including name, email, and questions.

- **callToActionButtons**: Action buttons associated with the recorder.

- **notification**: Notification settings for the recorder.

- **isActive**: Indicates if the recorder is currently active.

- **createdAt**: Timestamp of when the recorder was created.

- **updatedAt**: Timestamp of when the recorder was last updated.

- **domain**: Domain associated with the recorder.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recorderId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/recorder/RECORDER_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-recorder-recorder-id" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.recorderId` | string |
| `data.userId` | string |
| `data.name` | string |
| `data.description` | string |
| `data.token` | string |
| `data.recordings` | string[] |
| `data.minDuration` | integer |
| `data.maxDuration` | integer |
| `data.privacyMode` | string |
| `data.password` | string |
| `data.isAutoAnalyze` | boolean |
| `data.assignTo` | string |
| `data.folderId` | string |
| `data.sourceLanguage` | string |
| `data.meta` | object |
| `data.notification` | object |
| `data.isActive` | boolean |
| `data.createdAt` | string (date-time) |
| `data.updatedAt` | string (date-time) |
| `data.domain` | string |

Deeper nested fields are not listed. See the example response below for the full shape.

Example response (Recorder info), `application/json`. Arrays are shortened to one entry and long strings are cut.

```json
{
  "status": "success",
  "data": {
"recorderId": "2f93b3d68937",
"userId": "5d03a9d5d4bca272e9c8cf89",
"name": "Recorder Mon Jun 24 2024",
"description": "",
"token": "recorder-mon-jun-24-2024-a3535823b1a8",
"recordings": [
  "667c643820f2e801e047953c"
],
"minDuration": 15,
"maxDuration": 300,
"privacyMode": "public",
"password": "",
"isAutoAnalyze": true,
"assignTo": "",
"folderId": "f89a9eac1b62",
"sourceLanguage": "en-AU",
"meta": {
  "backgroundImg": "",
  "logo": "",
  "primaryColor": "#c42860",
  "type": {
    "audio": true,
    "video": true,
    "screenShare": false,
    "upload": {
      "file": true,
      "url": true,
      "multiple": false,
      "text": null
    }
  },
  "client": {
    "name": false,
    "email": false,
    "questions": [
      {
        "id": "41db9890bab9",
        "question": "test question",
        "isRequired": true,
        "answerType": "single",
        "options": [],
        "includeOther": false,
        "fieldId": "",
        "_id": "66bd01f4507d676698028770"
      }
    ]
  },
  "callToActionButtons": []
},
"notification": {
  "client": true,
  "upload": true,
  "notifyUsers": []
},
"isActive": true,
"createdAt": "2024-06-24T15:05:41.703Z",
"updatedAt": "2024-06-24T15:05:41.703Z",
"domain": ""
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="delete-recorder-recorder-id">Delete Recorder</h2>

#### DELETE /v1/recorder/\{recorderId\}

This endpoint allows clients to delete a specific recorder resource identified by the `recorderId`.

##### Parameters

- **recorderId** (path parameter): The unique identifier of the recorder that you wish to delete. This parameter is required.

##### Response

Upon successful deletion, the server will respond with a confirmation message indicating the result of the operation. The structure of the response will typically include:

- A status code indicating the success or failure of the operation.

- A message providing additional context about the deletion.

Ensure that the `recorderId` provided corresponds to an existing recorder, as attempting to delete a non-existent recorder may result in an error response.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recorderId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/recorder/RECORDER_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-recorder-recorder-id" statuses={[{"code":"404","description":"Not Found"}]}>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `requestId` | string |
| `code` | integer |
| `message` | string |
| `hints` | string[] |

Example response, `application/json`.

```json
{
  "status": "failed",
  "requestId": "8389bb88-ad28-4210-a72b-b9326e51d9cd",
  "code": 404,
  "message": "Recorder Note not found!",
  "hints": [
"The requested operation failed because a resource associated with the request could not be found."
  ]
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-recorder-clone">Clone Recorder</h2>

**Clone Recorder to copy all the settings from the existing recorders**

**All the required fields are as below:**

`recorderId` - Pass the recorderId from the existing recorder

**Optional:**

`name` - New name for the recorder. If not pass, it will take the existing recorder name and add `(clone)` to the new recorder

`description` - New description for the recorder. If not pass, it will take the existing recorder description as is.

`folderId` - IMPORTANT! We recommend to pass the `folderId` to ensure the recordings save in the specific folder. If not pass, it will take the existing recorder folderId setting.

---

If you need to change any other settings, we recommend to use the `Create Recorder` API call.

### 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 |
| --- | --- | --- |
| `recorderId` | string, **required** | Name the recorder you want to copy. Required. An empty or whitespace-only value is rejected. A recorderId that matches no recorder returns 404 with 'Recorder not found'. |
| `name` | string | Name the copy. Optional, empty string allowed. If you leave it out or send an empty string, the copy is named after the source recorder with ' (Clone)' appended. |
| `description` | string | Describe the copy. Optional, empty string allowed. If you leave it out or send an empty string, the copy inherits the source recorder's description. |
| `folderId` | string | Put the copy in this folder. Optional, empty string allowed. If you leave it out or send an empty string, the copy stays in the source recorder's folder. A folderId that matches no folder returns 404 with 'Folder not found. Please create or select a valid folder Id.' |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/recorder/clone' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "recorderId": "ce8f9465763c",
  "name": "Speak Clone test"
}'
```

</CodePanel>

<ResponsePanel id="post-recorder-clone" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.recorderData` | object |
| `data.recorderId` | string |
| `data.token` | string |

Deeper nested fields are not listed. See the example response below for the full shape.

Example response (Clone Recorder), `application/json`.

```json
{
  "status": "success",
  "data": {
"recorderData": {
  "notification": {
    "upload": true,
    "client": false
  },
  "recordings": [],
  "minDuration": 120,
  "maxDuration": 300,
  "privacyMode": "public",
  "password": "",
  "isAutoAnalyze": true,
  "assignTo": "",
  "folderId": "",
  "sourceLanguage": "en-US",
  "isActive": true,
  "isDisabled": false,
  "isDeleted": false,
  "_id": "640f5c18a33c35424caa86fc",
  "name": "Speak test",
  "description": "Speak recorder description",
  "companyId": "5e21c8dd2d77242c64214816",
  "userId": "5d03a9d5d4bca272e9c8cf89",
  "recorderId": "3a1c8f68f2de",
  "token": "speak-test-5b87d2c2d21e",
  "meta": {
    "backgroundImg": "https://speakai-storage.s3.amazonaws.com/backgroundImg/prod/5d03a9d5d4bca272e9c8cf89/1649768360045-blob",
    "logo": "https://speakai-storage.s3.amazonaws.com/logo/prod/5d03a9d5d4bca272e9c8cf89/1649768327203-Speak---Rectange-Logo---Black---5000px-Wide.png",
    "primaryColor": "#000000",
    "type": {
      "audio": true,
      "video": true,
      "screenShare": true,
      "upload": {
        "file": true,
        "multiple": false,
        "text": true
      }
    },
    "client": {
      "name": true,
      "email": true,
      "questions": []
    }
  },
  "createdAt": "2023-03-13T17:23:36.374Z",
  "updatedAt": "2023-03-13T17:23:36.374Z",
  "__v": 0
},
"recorderId": "3a1c8f68f2de",
"token": "speak-test-5b87d2c2d21e"
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-recorder-create">Create Recorder</h2>

**Create a recorder and integrate with your platform easily.**

**All the required fields are as below:**

`name` - Name of the recorder

All the other fields are optional. Your recorder will be created automatically.

`description` - Assign description of the recorder for internal purpose.

`folderId` - Save all your recordings to the assigned FolderId.

---

**Duration of the recorder:**

- `minDuration` - 15 seconds (min) & 5 min (max)
 - Pass the duration in **seconds**

- `maxDuration` - 10 seconds (min) & 3 hours (max)
 - Pass the duration in seconds

---

**Source Language:**

- You can pass the `sourceLanguage` as a code.

- Other language codes available at the top of the page.

---

**Recorder options:**

- We allow to support creating recorder with the multiple options such as:
 - `audio` - Audio recorder

 - `video` - Video recorder

 - `screeShare` - Allow to screen share on browser (Mobile not supported)

 - `uploadFile` - Allow to upload various file formats
 - `allowMultiple` - Supporting multiple file uploads

---

**Notifications:**

`upload` - Recieve an email notification when anyone uploads a recording on the recorder

`client` - When your user submits a recording (have the email address in a form) - they will receive an submittion email

---

**Client Information Questions:**

`name` - Ask for their name

`email` - Ask for their email address

`questions` - Check an API endpoint to update different types of questions.

### 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 |
| --- | --- | --- |
| `name` | string, **required** | Name the recorder. This is the only field you have to send. Required. An empty or whitespace-only value is rejected because the validator is the schema.trim with no.allow(''). The value is stored exactly as you send it, including any surrounding whitespace. |
| `description` | string | Describe the recorder for your own reference. Optional. An empty string is allowed. |
| `isAutoAnalyze` | boolean | Analyze each recording automatically as soon as it is submitted. Optional. If you leave it out, the recorder is saved with automatic analysis on, which is the default on the Recorder model. |
| `sourceLanguage` | string | Set the spoken language Speak transcribes recordings in. Optional. Must be one of the transcription language codes the server compiles at start up from the static list (137 entries, including auto and multi). An unrecognized code returns 400 with the message 'sourceLanguage must be a valid transcription language code'. GET /v1/media/supportedLanguages returns the list the server is currently serving, which can be refreshed from the database at runtime while the accepted set for this field stays as it was at start up, so the two can drift. If you leave the field out, the recorder is saved with en-US. |
| `folderId` | string | Save every recording from this recorder into the folder you name here. Optional. An empty string is allowed and is the only value that makes Speak pick your first folder. Leaving the field out is not the same: the recorder is saved with an empty folderId instead. A folderId that does not exist in your company returns 400 with 'Folder not found'. |
| `duration` | object | Set how long a recording is allowed to run. Optional. Two optional number keys, both in seconds. minDuration accepts 0 to 300, maxDuration accepts 15 to 10800. The create handler applies 15 and 300 when you leave the object or either key out. |
| `notification` | object | Choose who gets an email when a recording comes in. Optional. Two optional booleans, both treated as true when you leave them out. upload emails the users in notifyUsers when a recording arrives. client emails the respondent a confirmation, and only fires when they gave an email address. |
| `options` | object | Turn the individual capture and upload modes on or off. Optional. Keys are all optional booleans unless noted: audio (true when omitted), video (true), screenShare (true), liveTranscription (false, also accepts null), and upload, a nested object with file (true), text (false), multiple (false) and url (true). The create handler applies those fallbacks. |
| `notifyUsers` | string[] | List the user IDs that get emailed when a recording arrives. Optional. Each item is a non-empty string. Stored under the recorder's notification block and used only when notification.upload is on. |
| `clientInformation` | object | Decide what you ask a respondent for before they record. Optional. Reuses the updateQuestions schema at:33-46. Keys: name (boolean, true when omitted), email (boolean, true when omitted), questions (array, items unconstrained), and consent, a nested object with isEnabled (boolean, false), title (string, empty allowed), description (string, empty allowed), yesButtonLabel (string, 'Yes'), noButtonLabel (string, 'No'), isRequired (boolean, false) and fieldId (string, empty allowed, ''). The whole object is stored as sent. |
| `meta` | object | Customize the recorder page. On create, only the layout fields below take effect. Optional. The create handler reads only customCSS, hideWaveform, hideTitle, hideDescription, hideSubmitButton, submitButtonLabel, countdown and hideImages. customCSS is capped at 50000 characters and is run through a CSS sanitizer before it is stored; when you leave it out or send an empty string, the company's stored customCSS is used. The booleans are false when omitted and submitButtonLabel is 'Upload' when omitted. primaryColor, backgroundImg, logo, fontColor, fontFamily and theme are accepted by the validator but ignored on create: a new recorder always inherits those six from your company branding. Use PUT /recorder/settings/\{recorderId\} to change them. |
| `assignTo` | string | Accepted by the request validator but never used. Optional, empty string allowed. The create handler never reads this field and nothing in the recorder module references it, so sending it has no effect. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/recorder/create' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Speak test 1",
  "description": "Speak recorder description",
  "folderId": "0648e533f72c",
  "sourceLanguage": "en-US",
  "duration": {
"minDuration": 120,
"maxDuration": 300
  },
  "options": {
"audio": true,
"video": true,
"screenShare": true,
"upload": {
  "file": false,
  "text": true,
  "multiple": true,
  "url": false
}
  },
  "notification": {
"upload": true,
"client": false
  },
  "clientInformation": {
"name": true,
"email": true,
"questions": []
  }
}'
```

</CodePanel>

<ResponsePanel id="post-recorder-create" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.recorderData` | object |
| `data.recorderId` | string |
| `data.token` | string |

Deeper nested fields are not listed. See the example response below for the full shape.

Example response (Create Recorder), `application/json`.

```json
{
  "status": "success",
  "data": {
"recorderData": {
  "notification": {
    "upload": true,
    "client": false
  },
  "recordings": [],
  "minDuration": 120,
  "maxDuration": 300,
  "privacyMode": "public",
  "password": "",
  "isAutoAnalyze": true,
  "assignTo": "",
  "folderId": "",
  "sourceLanguage": "en-US",
  "isActive": true,
  "isDisabled": false,
  "isDeleted": false,
  "_id": "640f5c18a33c35424caa86fc",
  "name": "Speak test",
  "description": "Speak recorder description",
  "companyId": "5e21c8dd2d77242c64214816",
  "userId": "5d03a9d5d4bca272e9c8cf89",
  "recorderId": "3a1c8f68f2de",
  "token": "speak-test-5b87d2c2d21e",
  "meta": {
    "backgroundImg": "https://speakai-storage.s3.amazonaws.com/backgroundImg/prod/5d03a9d5d4bca272e9c8cf89/1649768360045-blob",
    "logo": "https://speakai-storage.s3.amazonaws.com/logo/prod/5d03a9d5d4bca272e9c8cf89/1649768327203-Speak---Rectange-Logo---Black---5000px-Wide.png",
    "primaryColor": "#000000",
    "type": {
      "audio": true,
      "video": true,
      "screenShare": true,
      "upload": {
        "file": true,
        "multiple": false,
        "text": true
      }
    },
    "client": {
      "name": true,
      "email": true,
      "questions": []
    }
  },
  "createdAt": "2023-03-13T17:23:36.374Z",
  "updatedAt": "2023-03-13T17:23:36.374Z",
  "__v": 0
},
"recorderId": "3a1c8f68f2de",
"token": "speak-test-5b87d2c2d21e"
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-recorder-questions-recorder-id">Update Recorder Questions</h2>

**Update a recorder questions:**

`questions` - Speak offer different set of questions to create and ask to your clients.

Here're the few examples with value:

1. Single Line - "single"
2. Multi Line - "multiple"
3. Checkbox\* - "checkbox"
4. Radio Button\* - "radiobutton"
5. Dropdown\* - "dropdownlist"
6. Date - "date"
7. Date & Time - "datetime"

Checkbox, Radio Button, Dropdown offers "Include Others" option.

Checkbox Sample:

``` json
{
"question":"My Checkbox question",
"isRequired":true,
"answerType":"checkbox",
"options":["Option A","Option B"],
"includeOther":false
}

```

Dropdown Sample with Include Other:

``` json
{
 "question": "My Dropdown Question with Include Others",
 "isRequired": true,
 "answerType": "dropdownlist",
 "options": [
 "Value 1",
 "Value 2"
 ],
 "includeOther": true
}

```

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recorderId` | path | string | Yes |  |

### 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 |
| --- | --- | --- |
| `id` | string | Send the id of an existing question to edit it. Leave it out to add a new question. Optional. Accepts an empty string and null, both of which are treated as 'add a new question'. If you send an id that no question on the recorder matches, the request still returns 200 but nothing changes and questionData comes back empty. |
| `question` | string, **required** | Write the question text a respondent sees. Required. An empty or whitespace-only value is rejected. |
| `isRequired` | boolean, **required** | Make the respondent answer this question before they can submit. Required. There is no fallback, so you have to send it on every call, including edits. |
| `answerType` | string, **required** | Set the kind of answer control the question uses. Required. An empty or whitespace-only value is rejected. This route puts no.valid constraint on the value, so the server stores whatever string you send. The recorder reads these values from the RecorderAnswerType enum in @speakai/shared: single, multiple, checkbox, radiobutton, dropdownlist, date, time, datetime. The public submission route does enforce that enum with.valid, so a value outside the set is stored here and then rejected when a respondent submits an answer. |
| `options` | string[] | List the choices for a question that offers a fixed set of answers. Optional. Each item is a non-empty string. There is no cap on the number of items. |
| `includeOther` | boolean | Add an 'Other' choice alongside the options you listed. Optional. No fallback, so it is stored as undefined when you leave it out. |
| `fieldId` | string | Map the answers to one of your custom fields. Optional. Accepts an empty string and null. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/recorder/questions/null' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "question": "My First Sample Question",
  "isRequired": true,
  "answerType": "single",
  "options": [],
  "includeOther": false
}'
```

</CodePanel>

<ResponsePanel id="post-recorder-questions-recorder-id" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.message` | string |
| `data.recorderId` | string |

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"message": "recorder-9 updated is successfully updated",
"recorderId": "70ea4d569736"
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="get-recorder-recordings-recorder-id">Recording Details</h2>

Get Recording meta details such as:

* Name
* Email
* Other asked questions

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recorderId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/recorder/recordings/RECORDER_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-recorder-recordings-recorder-id" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.totalCount` | integer |
| `data.recordings` | object[] |

Deeper nested fields are not listed. See the example response below for the full shape.

Example response (Recording Details), `application/json`. Arrays are shortened to one entry and long strings are cut.

```json
{
  "status": "success",
  "data": {
"totalCount": 3,
"recordings": [
  {
    "_id": "66bd022e507d6766980287eb",
    "recorderId": "66798b454a53154b90d40077",
    "mediaId": {
      "_id": "66bd022e507d6766980287e9",
      "folderId": "f89a9eac1b62",
      "name": "Wed Aug 14 2024 15:14:54 GMT-0400 (Eastern Daylight Time)",
      "description": "Client's recording for Recorder Mon Jun 24 2024",
      "tags": [
        "Recorder Mon Jun 24 2024"
      ],
      "state": "processed",
      "duration": {
        "inSecond": 15,
        "end": "00:00:15.504",
        "start": "00:00:00.080"
      },
      "mediaId": "dc49faf822df",
      "createdAt": "2024-08-14T19:14:54.194Z",
      "publishedUrl": "media/5d03a9d5d4bca272e9c8cf89/audio/1723662893381-recorder_mon_jun_24_2024.mp3"
    },
    "client": {
      "name": "",
      "email": "",
      "questions": [
        {
          "id": "41db9890bab9",
          "question": "test question",
          "answer": "test 3",
          "answerType": "single"
        }
      ]
    },
    "isDeleted": false,
    "meta": {
      "isScreenShare": false,
      "microphoneMuted": false,
      "microphoneReadyState": "live",
      "microphoneName": "Default - MacBook Pro Microphone (Built-in)",
      "microphoneNumber": 5,
      "cameraMuted": false,
      "cameraReadyState": "live",
      "cameraName": "",
      "cameraNumber": 1
    },
    "createdAt": "2024-08-14T19:14:54.586Z",
    "updatedAt": "2024-08-14T19:14:54.586Z",
    "__v": 0
  }
]
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="put-recorder-settings-recorder-id">Update Recorder Settings</h2>

**Update a recorder details.**

`name` - Name of the recorder

All the other fields are optional. Your recorder will be updated automatically.

---

**Duration of the recorder:**

- `minDuration` - 15 seconds (min) & 5 min (max)
 - Pass the duration in **seconds**
- `maxDuration` - 10 seconds (min) & 3 hours (max)
 - Pass the duration in seconds

---

**Source Language:**

- You can pass the `sourceLanguage` as a code.
- Other language codes available at the top of the page.

---

**Recorder options:**

- We allow to support creating recorder with the multiple options such as:
 - `audio` - Audio recorder
 - `video` - Video recorder
 - `screeShare` - Allow to screen share on browser (Mobile not supported)
 - `uploadFile` - Allow to upload various file formats
 - `allowMultiple` - Supporting multiple file uploads

---

**Notifications:**

`upload` - Recieve an email notification when anyone uploads a recording on the recorder

`client` - When your user submits a recording (have the email address in a form) - they will receive an submittion email

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recorderId` | path | string | Yes |  |

### 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 |
| --- | --- | --- |
| `name` | string, **required** | Set the recorder name. Required on every call, even when you only mean to change something else. An empty or whitespace-only value is rejected. Sending the current name back is how you make a partial update. |
| `description` | string | Describe the recorder for your own reference. Optional, empty string allowed. The handler writes this only when the value is truthy, so an empty string leaves the stored description as it was. |
| `isAutoAnalyze` | boolean | Analyze each recording automatically as soon as it is submitted. Optional. Leaving it out leaves the stored setting alone. Send false to turn automatic analysis off. |
| `sourceLanguage` | string | Set the spoken language Speak transcribes recordings in. Optional. Leaving it out or sending an empty string leaves the stored language alone. Must be one of the transcription language codes the server compiles at start up from the static list (137 entries, including auto and multi). An unrecognized code returns 400 with 'sourceLanguage must be a valid transcription language code'. |
| `folderId` | string | Move new recordings from this recorder into the folder you name here. Optional, empty string allowed. The handler writes the folder only when the value is truthy, so an empty string leaves the current folder alone. A folderId that does not exist in your company returns 400 with 'Folder not found'. |
| `notifyUsers` | string[] | List the user IDs that get emailed when a recording arrives. Optional. Each item is a non-empty string. The handler persists this list only when you also send a notification object with at least one of upload or client set, so notifyUsers on its own is accepted and then ignored. |
| `duration` | object | Set how long a recording is allowed to run. Optional. Two optional number keys, both in seconds. minDuration accepts 0 to 300, maxDuration accepts 15 to 10800. Each key is written only when it is truthy, so 0 does not overwrite the stored minDuration. |
| `notification` | object | Choose who gets an email when a recording comes in. Optional. Two optional booleans. upload emails the users in notifyUsers when a recording arrives. client emails the respondent a confirmation, and only fires when they gave an email address. Sending this object with at least one key also writes notifyUsers, and any key you leave out is cleared on the stored notification block. |
| `options` | object | Turn the individual capture and upload modes on or off. Optional. Keys are all optional booleans unless noted: audio, video, screenShare, liveTranscription (also accepts null), and upload, a nested object with file, text, multiple and url. When you send this object the handler replaces the whole stored block, so send every mode you want kept or the ones you leave out are cleared. |
| `meta` | object | Brand and customize the recorder page. Optional, and unlike POST /recorder/create every key here takes effect. Strings, each written only when truthy: primaryColor, fontColor, fontFamily, theme, backgroundImg, logo. backgroundImg and logo are normalized from a signed CloudFront URL back to an S3 URI before storage. customCSS is capped at 50000 characters, is run through a CSS sanitizer before it is stored, and is written whenever you send it, so an empty string clears it. Booleans, each written whenever you send it: hideWaveform, hideTitle, hideDescription, hideSubmitButton, countdown, hideImages. submitButtonLabel is a string written only when truthy. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X PUT 'https://api.speakai.co/v1/recorder/settings/null' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "recorder-9",
  "description": "recorder-9 description",
  "folderId": "0648e533f72c",
  "sourceLanguage": "en-US",
  "duration": {
"minDuration": 120,
"maxDuration": 300
  },
  "options": {
"audio": true,
"video": true,
"screenShare": true,
"upload": {
  "file": false,
  "text": true,
  "multiple": true,
  "url": false
}
  },
  "notification": {
"upload": true,
"client": false
  }
}'
```

</CodePanel>

<ResponsePanel id="put-recorder-settings-recorder-id" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.message` | string |
| `data.recorderId` | string |

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"message": "recorder-9 updated is successfully updated",
"recorderId": "70ea4d569736"
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="get-recorder-status-token">Check Recorder Status</h2>

Reveals whether recorder is publically open or password-protected

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `token` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/recorder/status/recorder-9' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-recorder-status-token" statuses={[{"code":"404","description":"Not Found"}]}>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `requestId` | string |
| `code` | integer |
| `message` | string |
| `hints` | string[] |

Example response, `application/json`.

```json
{
  "status": "failed",
  "requestId": "eb3e08b0-3d91-47e1-81bc-8432f76be977",
  "code": 404,
  "message": "Recorder not found!",
  "hints": [
"The requested operation failed because a resource associated with the request could not be found."
  ]
}
```

</div>

</ResponsePanel>

</div>

<h2 id="get-recorder-url-recorder-id">Generate Recorder URL</h2>

#### API Endpoint: Get Recorder URL

**Method:** `GET`
**Endpoint:** `https://api.speakai.co/v1/recorder/url/{recorderId}`

##### Description

This endpoint retrieves the URL associated with a specific recorder identified by `recorderId`. It is used to obtain the necessary information to access the recorder's iframe and page details.

##### Parameters

- **recorderId** (path parameter): The unique identifier for the recorder whose URL is being requested.

##### Response Format

The response will be in JSON format and includes the following fields:

- **status**: A string indicating the status of the request.

- **data**: An object containing:

- **iframe**: A string representing the iframe URL for the recorder.

- **page**: A string representing the page URL for the recorder.

##### Example Response

``` json
{
 "status": "",
 "data": {
 "iframe": "",
 "page": ""
 }
}

```

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `recorderId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/recorder/url/RECORDER_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-recorder-url-recorder-id" statuses={[{"code":"200","description":"OK"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `data` | object |
| `data.iframe` | string |
| `data.page` | string |

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"iframe": "<iframe style=\"height: 800px !important; width: 960px !important;\" src=\"https://recorder.speakai.co/iframe/recorder-9-4fb7713e267a\" frameborder=\"0\" scrolling=\"no\"></iframe>",
"page": "https://recorder.speakai.co/recorder-9-4fb7713e267a"
  }
}
```

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `requestId` | string |
| `code` | integer |
| `message` | string |
| `hints` | string[] |

Example response, `application/json`.

```json
{
  "status": "failed",
  "requestId": "1babfc3a-9f8f-4c22-83c8-0367cb2b7cb1",
  "code": 404,
  "message": "Recorder Id not found!",
  "hints": [
"The requested operation failed because a resource associated with the request could not be found."
  ]
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-recorder-verify">Verify Password</h2>

User to grant\prohobit access to a password-protected recorder

### 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 |
| --- | --- | --- |
| `token` | string, **required** | Pass the recorder's embed token, the same token that appears in the public recorder URL. Required. An empty string is rejected. A token that matches no recorder returns 404 with 'Recorder not found!'. |
| `password` | string, **required** | Pass the password a viewer typed so Speak can check it against the recorder. Required. An empty string is rejected. Unlike most string fields on the recorder endpoints this one is a plain the schema with no.trim, so leading and trailing spaces are compared as typed. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/recorder/verify' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{
  "token": "token",
  "password": "123"
}'
```

</CodePanel>

<ResponsePanel id="post-recorder-verify" statuses={[{"code":"404","description":"Not Found"}]}>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type |
| --- | --- |
| `status` | string |
| `requestId` | string |
| `code` | integer |
| `message` | string |
| `hints` | string[] |

Example response, `application/json`.

```json
{
  "status": "failed",
  "requestId": "32732927-3809-4973-a82b-82663013d36f",
  "code": 404,
  "message": "Recorder not found!",
  "hints": [
"The requested operation failed because a resource associated with the request could not be found."
  ]
}
```

</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 in Speak AI](/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-recorders).

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