Authentication
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl "https://www.happyscribe.com/api/v1/transcriptions" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/transcriptions', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
Make sure to replace
**your_api_key_here**with your API key.
You can get your HappyScribe API key by logging in and going to your "Account" page.
HappyScribe expects the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer **your_api_key_here**"
Uploads
When creating a transcription, a media file URL (accessible to our servers) must be provided.
This can be a publicly accessible URL hosted by you or a third party. We also support public links from services like YouTube and Vimeo. Alternatively, you can upload files directly to our storage system (AWS S3 bucket) and create the transcription using the returned URL.
To upload files to our AWS S3 bucket, you must first request a signed URL using the endpoints below.
1. Get a Signed Url
curl "https://www.happyscribe.com/api/v1/uploads/new?filename=my_media.mp3" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/uploads/new?filename=my_media.mp3', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"signedUrl": "https://happy-scribe-domain.s3.eu-west-1.amazonaws.com/xxxxxx?x-amx-signature=xxxxx..."
}
This endpoint returns a signed URL which can be used to make PUT requests to our S3 bucket. More information here: docs.aws.amazon.com
Once the file is uploaded, this same URL should be used as the tmp_url when creating the associated transcription.
HTTP Request
GET https://www.happyscribe.com/api/v1/uploads/new
Parameters
| Parameter | Description |
|---|---|
| filename | (required) The filename and extension of the media file (e.g. my_media.mp3) |
2. Upload your file with the Signed Url
curl -X PUT -T my_media.mp3 -L https://signed-url...
fetch('https://signed-url...', {
method: 'PUT',
body: my_media_data, // This should be a Blob or File object representing my_media.mp3
});
Simple upload to an AWS S3 Bucket
Once you have a signed URL, you have to upload the file there, and you do it as you would with any AWS S3 bucket.
To upload a file to the signed URL you may use cURL like the example on the right.
Here you have more information about how to deal with AWS S3 signed URLs docs.aws.amazon.com.
Transcriptions
List All Transcriptions
curl "https://www.happyscribe.com/api/v1/transcriptions" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/transcriptions', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"results": [
{
"id": "e458099e7f8da14f9625854ba7b6a026917ad306",
"name": "interview1.mov",
"folder": { "id": 521, "name": "Marketing interviews" },
"createdAt": "2024-10-29T14:31:29.799+00:00",
"updatedAt": "2024-10-29T14:31:38.495+00:00",
"state": "automatic_done",
"sharingEnabled": false,
"language": "en-GB",
"audioLengthInSeconds": 42,
"costInCents": 100,
"refunded": false,
"_links": {
"self": {
"editorUrl": "https://www.happyscribe.com/api/v1/transcriptions/e458099e7f8da14f9625854ba7b6a026917ad306"
}
},
"tags": ["To do", "req_1234"],
},
{
"id": "9jossdjdf09j309omsldknslkjndfjknsdfs",
"name": "interview2.mov",
"folder": { "id": 522, "name": "Customer calls" },
"createdAt": "2024-10-29T14:31:29.799+00:00",
"updatedAt": "2024-10-29T14:31:38.495+00:00",
"state": "automatic_done",
"sharingEnabled": false,
"language": "en-GB",
"audioLengthInSeconds": 42,
"costInCents": 100,
"refunded": false,
"_links": {
"self": {
"editorUrl": "https://www.happyscribe.com/api/v1/transcriptions/9jossdjdf09j309omsldknslkjndfjknsdfs"
}
},
"tags": [],
},
...
],
"_links": {
"next": {
"url": "https://www.happyscribe.com/api/v1/transcriptions?page=2"
}
}
}
Returns a list of transcriptions you’ve previously created. The transcriptions are returned in sorted order, with the most recent charges appearing first. The information returned is metadata about each transcription, not the actual transcript. To retrieve a specific transcript you have to use the export endpoint.
HTTP Request
GET https://www.happyscribe.com/api/v1/transcriptions
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| organization_id | - | (required) Id of the organization to get the transcriptions from |
| folder_id | All folders | When set, filters the list to transcriptions that are inside the specified folder or its subfolders. To get the folder id, navigate to the given folder in the web application and copy the id from the URL. |
| page | 0 | Request a specific page |
| per_page | 5 | Number of transcriptions to return per page. Maximum 100. |
| tags | - | List of tags to filter by. |
Create a Transcription
curl -X POST "https://www.happyscribe.com/api/v1/transcriptions" \
-H "Authorization: Bearer **your_api_key_here**" \
-H "Content-Type: application/json" \
-d '{
"transcription": {
"name": "My Interview",
"language": "en-GB",
"tmp_url": "https://example.com/my_media.mp3",
"is_subtitle": false,
"organization_id": "413",
"folder_id": "521",
"tags": ["To do", "req_1234"],
}
}'
fetch('https://www.happyscribe.com/api/v1/transcriptions', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({
transcription: {
name: 'My Interview',
language: 'en-GB',
tmp_url: 'https://example.com/my_media.mp3',
is_subtitle: false,
organization_id: '413',
tags: ['To do', 'req_1234'],
},
}),
});
The above command returns JSON structured like this:
{
"id": "9josdjdfo09j309omsldknslkjndfjknsdfs",
"name": "My Interview",
"folder": { "id": 521, "name": "My folder" },
"createdAt": "2024-10-29T14:31:29.799+00:00",
"updatedAt": "2024-10-29T14:31:38.495+00:00",
"sharingEnabled": false,
"state": "ingesting",
"language": "en-GB",
"tags": ["To do", "req_1234"],
"_links": {
"self": {
"editorUrl": "https://www.happyscribe.com/api/v1/transcriptions/f6511f81s5611daede28dc85f25a796ae7996d11"
}
}
}
This endpoint creates a new transcription. After a transcription is created, the system will proceed to automatically transcribe it. You can watch if the transcription process has finished by retrieving a transcription.
You can order as many transcriptions as needed (within the established rate limit). The transcriptions will be processed in parallel.
HTTP Request
POST https://www.happyscribe.com/api/v1/transcriptions
Parameters
| Parameter | Type | Description |
|---|---|---|
| name | String | (required) Name of the transcription |
| language | String | (required) BCP-47 language code. Full list here |
| tmp_url | String | (required) A url where the media file is located and can be retrieved by our server. |
| is_subtitle | Boolean | (default: false) If set to true, we will treat this transcription as subtitles. |
| service | String | auto(default) : Machine generated transcription/subtitles. pro : transcription/subtitles hand-crafted by human professionals. alignment: Align the text provided in document_url with the media from tmp_url Note: check the supported languages. |
| organization_id | String | (required) Id of the organization to save the transcription in. |
| folder | String | (optional) Path of the folder to save the transcription in. Example: path/to/my folder. |
| folder_id | String | (optional) Id of the folder to save the transcription in. |
| document_url | String | (only for alignment ) An accessible url to a plain text document that needs to be aligned with the media provided in tmp_url. |
| sharing_enabled | Boolean | (default: false) If set to true, everyone with the editor url will be able to access it. |
| tags | Array | (optional) List of tags to add to the transcription. |
Retrieve a Transcription
curl "https://www.happyscribe.com/api/v1/transcriptions/<ID>" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/transcriptions/<ID>', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"id": "9josdjdfo09j309omsldknslkjndfjknsdfs",
"name": "interview2.mov",
"folder": { "id": 522, "name": "Customer calls" },
"createdAt": "2024-10-29T14:31:29.799+00:00",
"updatedAt": "2024-10-29T14:31:38.495+00:00",
"failureReason": null,
"sharingEnabled": false,
"state": "automatic_done",
"language": "en-GB",
"audioLengthInSeconds": 42,
"costInCents": 100,
"refunded": false,
"tags": ["To do", "req_1234"],
"soundwaveUrl": "https://hs-soundwaves-prod.s3-eu-west-1.amazonaws.com/e4c8e370a92aafb8b03da708c5016bb6-10.dat",
"_links": {
"self": {
"downloadUrl": "** download URL for JSON format transcription content**",
"editorUrl": "https://www.happyscribe.com/api/v1/transcriptions/f6511f81156114aede28dc85325a796ae7996d11"
}
}
}
This endpoint retrieves information about a specific transcription. To retrieve the transcript you have to use the export endpoint.
HTTP Request
GET https://www.happyscribe.com/api/v1/transcriptions/<ID>
Soundwave
The soundwaveUrl is returned for any transcription with associated media. The file is in BBC audiowaveform binary format. It is not available until the state is automatic_done.
Additional transcription properties
| Value | Description |
|---|---|
deliveryEstimatedAt |
Estimated time for the transcription to be delivered. It can change over time. |
failureReason |
Error code for the failure. |
failureMessage |
User friendly message explaining the failure root cause. |
Transcription State Descriptions
| Value | Description |
|---|---|
initial |
Transcription is waiting to be processed |
ingesting |
Media file is being ingested |
automatic_transcribing |
Audio is being transcribed to text |
automatic_done |
Transcription is finished and ready to export! |
aligning |
Text is being realigned with the audio |
locked |
Transcription is locked due to insufficient credits |
failed |
File failed to process |
demo |
The initial demo file |
Delete a Transcription
curl -X DELETE "https://www.happyscribe.com/api/v1/transcriptions/<ID>" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/transcriptions/<ID>', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
This endpoint deletes a transcription.
HTTP Request
DELETE https://www.happyscribe.com/api/v1/transcriptions/<ID>
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| permanent | false | When set to "true" the action is irreversible. Otherwise, the transcription can be found in the Trash. |
Exports
Create an Export
curl -X POST "https://www.happyscribe.com/api/v1/exports" \
-H "Authorization: Bearer **your_api_key_here**" \
-H 'Content-Type: application/json' \
-d '{
"export": {
"format": "txt",
"transcription_ids": [
"**transcription_id_1**"
]
}
}'
fetch('https://www.happyscribe.com/api/v1/exports', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({
export: {
format: 'txt',
transcription_ids: ['**transcription_id_1**'],
},
}),
});
The above command returns JSON structured like this:
{
"id": "**export_id**",
"state": "pending",
"format": "txt",
"show_timestamps": false,
"show_speakers": false,
"show_comments": false,
"show_highlights": false,
"transcription_ids": ["**transcription_id_1**"]
}
This endpoint creates a new export. After an export is created, the system will proceed to generate it. You can watch if the exporting process has finished by retrieving an export.
The exporting process is generally very fast. Each file takes ~10s to complete. You can submit more than one file at the same time.
For the mp3 and mp4 formats, no conversion is performed — the export points at the existing source media. The response from POST /api/v1/exports returns state: "ready" and the download_link immediately, with no need to poll.
HTTP Request
POST https://www.happyscribe.com/api/v1/exports
JSON Parameters
| Parameter | Default | Description |
|---|---|---|
| format | none | (required) Specify the export format (see chart below) |
| show_timestamps | false | Include timestamps (only formats: txt, docx, pdf ) |
| timestamps_frequency | nil | Include inline timecodes at a given frequency (valid values: 5s, 10s, 15s, 20s, 30s, 60s) |
| show_speakers | false | Include speaker labels (only formats: txt, docx, pdf ) |
| show_comments | false | Include comments (only formats: txt, docx, pdf ) |
| show_highlights | false | Include highlights (only formats: docx, pdf ) |
| show_highlights_only | false | Include only highlights (only formats: docx, pdf ) |
Export formats
| Value | Description |
|---|---|
| txt | Text Document (.txt) |
| docx | Word Document (.docx) |
| PDF Document (.pdf) | |
| srt | Subtitles (SubRip .srt) |
| vtt | Subtitles (WebVTT .vtt) |
| stl | Subtitles (EBU-STL .stl) |
| avid | Avid Markers (.txt) |
| html | Interactive Transcript (.html) |
| premiere | Premiere Pro (Beta) (.xml) |
| maxqda | Maxqda (.txt) |
| json | JSON (.json) |
| fcp | Final Cut Pro (.fcp) |
| mp3 | Source audio (.mp3) |
| mp4 | Source video (.mp4) |
Retrieve an Export
curl "https://www.happyscribe.com/api/v1/exports/<ID>" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/exports/<ID>', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"id": "**export_id**",
"state": "ready",
"format": "txt",
"show_timestamps": false,
"show_speakers": false,
"show_comments": false,
"show_highlights": false,
"transcription_ids": ["**transcription_id_1**"],
"download_link": "**download_link**"
}
This endpoint retrieves information about a specific export. To download it you can use the returned download_link.
HTTP Request
GET https://www.happyscribe.com/api/v1/exports/<ID>
Export State Descriptions
| Value | Description |
|---|---|
pending |
Waiting to be processed. |
processing |
The export is being generated. |
ready |
The export is ready to download. |
expired |
No longer available. |
failed |
A problem occurred. |
Translations
Create a Translation Task
curl -X POST "https://www.happyscribe.com/api/v1/task/transcription_translation" \
-H "Authorization: Bearer **your_api_key_here**" \
-H 'Content-Type: application/json' \
-d '{
"source_transcription_id": "**source_transcription_id**",
"target_language": "es"
}'
fetch('https://www.happyscribe.com/api/v1/task/transcription_translation', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({
source_transcription_id: '**source_transcription_id**',
target_language: 'es',
}),
});
The above command returns JSON structured like this:
{
"id": "054fe9f3aa0b446baea730fba688f96c",
"state": "working",
"failureReason": null,
"progressPercent": null,
"targetLanguage": "es"
}
Creates a new translation task given a source transcription and a target language code.
After a translation task is created, the system will proceed to generate a new transcription
with the translated content. You can watch the task status and get the result
by retrieving a translation task using the response
id property.
The translation task typically takes ~10s to complete but can take up to two minutes if the source transcription is large.
HTTP Request
POST https://www.happyscribe.com/api/v1/task/transcription_translation
JSON Parameters
| Parameter | Default | Description |
|---|---|---|
| source_transcription_id | none | (required) Specify the id of the transcription you want to translate from. It must be in one of the supported source translation languages. |
| target_language | none | (required) The language code of the language you want to translate to. Full list here. |
Target translation languages
| Code | Language |
|---|---|
| af | Afrikaans |
| sq | Albanian |
| am | Amharic |
| ar | Arabic |
| hy | Armenian |
| az | Azerbaijani |
| eu | Basque |
| bn | Bengali |
| bs | Bosnian |
| bg | Bulgarian |
| ca | Catalan |
| zh | Chinese |
| hr | Croatian |
| cs | Czech |
| da | Danish |
| nl | Dutch |
| en | English |
| et | Estonian |
| fil | Filipino |
| fi | Finnish |
| fr | French |
| gl | Galician |
| ka | Georgian |
| de | German |
| el | Greek |
| gu | Gujarati |
| he | Hebrew |
| hi | Hindi |
| hu | Hungarian |
| is | Icelandic |
| id | Indonesian |
| it | Italian |
| ja | Japanese |
| jv | Javanese |
| kn | Kannada |
| km | Khmer |
| ko | Korean |
| lo | Lao |
| lv | Latvian |
| lt | Lithuanian |
| mk | Macedonian |
| ms | Malay |
| ml | Malayalam |
| mr | Marathi |
| mn | Mongolian |
| my | Burmese |
| ne | Nepali |
| no | Norwegian |
| fa | Persian |
| pl | Polish |
| pt-PT | Portuguese (Portugal) |
| pt-BR | Portuguese (Brazil) |
| pa | Punjabi |
| ro | Romanian |
| ru | Russian |
| sr | Serbian |
| si | Sinhala |
| sk | Slovak |
| sl | Slovenian |
| es | Spanish |
| su | Sundanese |
| sw | Swahili |
| sv | Swedish |
| ta | Tamil |
| te | Telugu |
| th | Thai |
| tr | Turkish |
| uk | Ukrainian |
| ur | Urdu |
| uz | Uzbek |
| vi | Vietnamese |
| zu | Zulu |
Supported source translation languages
| Language Code | Language Name |
|---|---|
| af | Afrikaans |
| sq | Albanian |
| am | Amharic |
| ar | Arabic |
| hy | Armenian |
| az | Azerbaijani |
| eu | Basque |
| bn | Bengali |
| bs | Bosnian |
| bg | Bulgarian |
| ca | Catalan |
| cmn-Hans-CN | Chinese, Mandarin (Simplified, China) |
| cmn-Hans-HK | Chinese, Mandarin (Simplified, Hong Kong) |
| cmn-Hant-TW | Chinese, Mandarin (Traditional, Taiwan) |
| hr | Croatian |
| cs | Czech |
| da | Danish |
| nl | Dutch |
| en | English |
| et | Estonian |
| fil | Filipino |
| fi | Finnish |
| fr | French |
| gl | Galician |
| ka | Georgian |
| de | German |
| el | Greek |
| gu | Gujarati |
| he | Hebrew |
| hi | Hindi |
| hu | Hungarian |
| is | Icelandic |
| id | Indonesian |
| it | Italian |
| ja | Japanese |
| jv | Javanese |
| kn | Kannada |
| km | Khmer |
| ko | Korean |
| lo | Lao |
| lv | Latvian |
| lt | Lithuanian |
| mk | Macedonian |
| ms | Malay |
| ml | Malayalam |
| mr | Marathi |
| mn | Mongolian |
| my | Burmese |
| ne | Nepali |
| no | Norwegian |
| fa | Persian |
| pl | Polish |
| pt | Portuguese |
| pa | Punjabi |
| ro | Romanian |
| ru | Russian |
| sr | Serbian |
| si | Sinhala |
| sk | Slovak |
| sl | Slovenian |
| es | Spanish |
| su | Sundanese |
| sw | Swahili |
| sv | Swedish |
| ta | Tamil |
| te | Telugu |
| th | Thai |
| tr | Turkish |
| uk | Ukrainian |
| ur | Urdu |
| uz | Uzbek |
| vi | Vietnamese |
| zu | Zulu |
Retrieve a Translation Task
curl "https://www.happyscribe.com/api/v1/task/transcription_translation/<ID>" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/task/transcription_translation/<ID>', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns a JSON structured like the following:
{
"id": "054fe9f3aa0b446baea730fba688f96c",
"state": "done",
"failureReason": null,
"progressPercent": 100.0,
"targetLanguage": "es",
"translatedTranscriptionId": "372e9530d8f24ba68ccbcce11de43f9d"
}
This endpoint returns information about a translation task. To get the translated
transcription when the task has finished you can use the translatedTranscriptionId property in
the response. Remember that you can use the transcription endpoint
or the export endpoint to retrieve the information and content of the transcription given the transcription id.
HTTP Request
GET https://www.happyscribe.com/api/v1/task/transcription_translation/<id>
Translation task state descriptions
| Value | Description |
|---|---|
| initial | The task is waiting to be processed |
| working | The translation is being generated |
| failed | A problem occured. See the failureReason attribute. |
| done | The translated transcription is ready. The translatedTranscriptionId attribute can be used to retrieve the translated transcription. |
Orders
This new section of the API replaces the deprecated Translations and some of the Transcriptions endpoints. For listing and retrieving transcriptions you can still refer to the Transcriptions endpoints.
Create a Transcription or Subtitling Order
curl -X POST "https://www.happyscribe.com/api/v1/orders" \
-H "Authorization: Bearer **your_api_key_here**" \
-H 'Content-Type: application/json' \
-d '{
"order": {
"url": "**url**",
"language": "es",
"service": "pro",
"confirm": true,
"organization_id": 123,
"folder": "my_project",
"name": "My transcription",
"tags": ["To do", "req_1234"],
"boost": true,
"is_subtitle": false,
"webhook_url": "**webhook_url**",
"glossary_ids": [1, 2],
"style_guide_id": 5
}
}'
fetch('https://www.happyscribe.com/api/v1/orders', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({
order: {
url: '**url**',
language: 'es',
service: 'pro',
confirm: true,
folder: 'my_project',
organization_id: 123,
name: 'My transcription',
tags: ['To do', 'req_1234'],
boost: true,
is_subtitle: false,
webhook_url: '**webhook_url**',
glossary_ids: [1, 2],
style_guide_id: 5,
},
}),
});
Creates a new transcription or subtitling order from the provided URL.
The location of the resulting file can be specified with either:
folder_id: The ID of the folder where to create the file.folder: A path to a folder in the given organization.
If none is given, it defaults to the workspace folder of the given organization.
If a webhook_url is provided, a webhook will be sent to the URL every time the order changes state (you can find more information about the order states in the Retrieve an Order section). The webhook payload is a JSON object containing the order id, its current state and, when state is failed, a failure_reason indicating which kind of failure happened:
{ "id": "10b1edd9381d4a00a3d0db1ca1b3d0cf", "state": "fulfilled" }
{
"id": "10b1edd9381d4a00a3d0db1ca1b3d0cf",
"state": "failed",
"failure_reason": "ingestion_failed"
}
Retrieve the order to get the full failure details (see the Retrieve an Order section).
After an order is created, the system will generate a new transcription or subtitle. You can monitor the order status and access the results by retrieving the order using the response id property and calling the Retrieve order endpoint to check its status. You can find more information about the meaning of each status in the linked section.
You may choose to submit the order immediately or later. If the confirm parameter is provided with true then the order will be submitted automatically if there are no errors. Otherwise it needs to be submitted manually by calling the confirm order endpoint
The transcription processing time depends on the service type:
- For "auto" service: Typically completed within a few seconds or minutes.
- For "pro" service: It depends on the language and whether the order is boosted or not. It may be from a few hours to multiple days.
You can order as many files as needed (within the established rate limit). The files will be processed in parallel.
HTTP Request
POST https://www.happyscribe.com/api/v1/orders
JSON Parameters
| Parameter | Default | Description |
|---|---|---|
| url | none | (required) The URL of the media file you want to transcribe. |
| language | none | (required) The language code of the language you want to transcribe to. See the full list here. |
| organization_id | none | (required) The ID of the workspace where to create the file. |
| service | auto | Specify "pro" for human transcription or "auto" for automatic transcription. |
| confirm | false | When set to true, the order will be submitted automatically. When false, the order remains in "incomplete" state until confirmed (using the confirm endpoint). |
| folder_id | none | The ID of the folder you want to create the order in. |
| folder | none | Path of the folder to save the transcription in. Example: path/to/my folder. |
| name | none | The name of the resulting transcription. If not provided, the name will be derived from the source file. |
| boost | false | When set to true, the order will be boosted. |
| is_subtitle | false | If set to true, we will treat this transcription as subtitles. |
| tags | none | List of tags to add to the transcription. |
| webhook_url | none | The URL to send a webhook to when the order is completed. |
| glossary_ids | none | Array of glossary IDs to apply to the order. Use the List Glossaries endpoint to find available glossary IDs. All IDs must belong to the specified organization. |
| style_guide_id | none | ID of a style guide to apply to the order. Use the List Style Guides endpoint to find available style guide IDs. Must belong to the specified organization. For pro service orders, addons like verbatim and SDH will be automatically applied based on the style guide settings. |
Response
The response follows the Order object structure as described in the "Retrieve an Order" section.
Create a Translation Order
curl -X POST "https://www.happyscribe.com/api/v1/orders/translation" \
-H "Authorization: Bearer **your_api_key_here**" \
-H 'Content-Type: application/json' \
-d '{
"order": {
"source_transcription_id": "**source_transcription_id**",
"target_languages": ["es"],
"service": "pro",
"confirm": true,
"webhook_url": "**webhook_url**"
}
}'
fetch('https://www.happyscribe.com/api/v1/orders/translation', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({
order: {
source_transcription_id: '**source_transcription_id**',
target_languages: ['es'],
service: 'pro',
confirm: false,
webhook_url: '**webhook_url**',
},
}),
});
The above command returns JSON structured like this:
{
"id": "7cb8b631b14342da900f49fbc02faf14",
"folder_id": 1,
"state": "submitted",
"operations": [
{
"name": "subtitles",
"type": "pro",
"language": "en-US",
"use_vocab": true,
"glossary_ids": []
},
{
"name": "transcription_translation",
"type": "pro",
"language": "en-US",
"glossary_ids": [],
"target_language": "es"
}
],
"details": {
"items": [
{
"input_id": 256,
"filename": "TED+Talk [SUB]",
"pricing_unit_name": "minutes",
"pricing_unit_count": 0.12,
"service": {
"name": "subtitles",
"type": "pro",
"language": "en-US",
"use_vocab": true,
"glossary_ids": []
},
"addon_id": null,
"addon_name": null,
"turnaround_minutes": 1440,
"cents_per_unit": 214,
"cents": 100,
"credits": null
},
{
"input_id": 256,
"filename": "TED+Talk [SUB]",
"pricing_unit_name": "minutes",
"pricing_unit_count": 0.12,
"service": {
"name": "transcription_translation",
"type": "pro",
"language": "en-US",
"glossary_ids": [],
"target_language": "es"
},
"addon_id": null,
"addon_name": null,
"turnaround_minutes": 4320,
"cents_per_unit": 475,
"cents": 57,
"credits": null
}
],
"pricing_unit_name": "minutes",
"pricing_unit_total_count": 0.12,
"total_cents": 157,
"total_credits": null,
"currency": "usd",
"currency_symbol": "$",
"addons_total_cents": {
"rush": 12,
"verbatim": 12,
"light_human": 0,
"sdh": 18
},
"minimum_charge": 50
},
"addons": [],
"inputs": [
{
"transcription_id": "aec40bff9aa6409da41658cb20c1b89f"
}
],
"outputsIds": ["e5fb537cecc9436b93c04be2a9219001"],
"canBeSubmitted": false
}
Creates a new translation order based on a source transcription and one or more target languages.
After a translation order is created, the system will generate new transcriptions
with the translated content for each target language specified. You can monitor the order status and access the results
by retrieving the order using the response id property.
The translation processing time depends on the service type:
- For "auto" service: Typically completed within a few seconds
- For "pro" service: Approximately 3 days for human translation
HTTP Request
POST https://www.happyscribe.com/api/v1/orders/translation
JSON Parameters
| Parameter | Default | Description |
|---|---|---|
| source_transcription_id | none | (required) The ID of the transcription you want to translate from. |
| target_languages | none | (required) An array of language codes you want to translate to. See the full list here. |
| service | auto | Specify "pro" for human translation or "auto" for automatic translation. |
| confirm | false | When set to true, the order will be submitted automatically. When false, the order remains in "incomplete" state until confirmed. |
| boost | false | When set to true, the order will be boosted. |
| webhook_url | none | The URL to send a webhook to when the order is completed. |
| tags | none | List of tags to add to the order. |
Response
The response follows the Order object structure as described in the "Retrieve an Order" section.
Key fields in the response include:
id: Use this identifier to check the order status later.state: Initially "submitted" (when confirm=true) or "incomplete" (when confirm=false).operations: Details of the translation operations being performed.inputs: Contains the source transcription ID.
Retrieve an Order
curl "https://www.happyscribe.com/api/v1/orders/<ID>" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/orders/<ID>', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns a JSON structured like the following:
{
"id": "10b1edd9381d4a00a3d0db1ca1b3d0cf",
"folder_id": 1,
"state": "incomplete",
"operations": [
{
"name": "transcription_translation",
"type": "auto",
"language": "en-US",
"target_language": "es",
"glossary_ids": []
}
],
"details": {
"items": [
{
"input_id": 258,
"filename": "TED+Talk",
"pricing_unit_name": "minutes",
"pricing_unit_count": 0.12,
"service": {
"name": "transcription_translation",
"type": "auto",
"language": "en-US",
"target_language": "es",
"glossary_ids": []
},
"addon_id": null,
"addon_name": null,
"turnaround_minutes": 1,
"cents_per_unit": 20,
"cents": 3,
"credits": 0.12
}
],
"pricing_unit_name": "minutes",
"pricing_unit_total_count": 0.12,
"total_cents": 3,
"total_credits": 0.12,
"currency": "usd",
"currency_symbol": "$",
"addons_total_cents": {},
"minimum_charge": 50
},
"addons": [
{
"name": "rush"
}
],
"inputs": [
{
"transcription_id": "e5fb537cecc9436b93c04be2a9219001"
}
],
"canBeSubmitted": true,
"outputsIds": ["e5fb537cecc9436b93c04be2a9219001"],
"transcriptions": [
{
"id": 123,
"uuid": "20481bf70b514a2f866f6977db97ac84",
"name": "**file_name**",
"state": "automatic_transcribing",
"language": "en",
"estimated_at": "2025-11-25T14:40:00+01:00"
}
],
"ingestions": [
{
"id": 41,
"name": "**url**",
"state": "transferring"
}
]
}
For a failed order, the response includes a top-level
failure_reasonand, for each failed ingestion, afailure_reasonand human-readablefailure_message:
{
"id": "10b1edd9381d4a00a3d0db1ca1b3d0cf",
"state": "failed",
"failure_reason": "ingestion_failed",
"ingestions": [
{
"id": 41,
"name": "**url**",
"state": "failed",
"failure_reason": "failed_import",
"failure_message": "Unable to access the file. The URL may have expired or require authentication."
}
]
}
This endpoint retrieves information about a specific order by its ID. Use this endpoint to check the status of an order, view its details, and access the results when the order is complete.
HTTP Request
GET https://www.happyscribe.com/api/v1/orders/<ID>
URL Parameters
| Parameter | Description |
|---|---|
| ID | The unique identifier of the order to retrieve |
Order Description
| Field | Description |
|---|---|
| id | Unique identifier for the order (UUID format) |
| folder_id | ID of the folder containing the order |
| state | Current state of the order (see "Order States" below) |
| operations | Array of operations being performed as part of this order |
| details | Contains pricing information, items being processed, and other order details |
| inputs | Source materials for the order, including transcription_id |
| canBeSubmitted | Whether the order can be submitted |
| addons | Array of additional services applied to the order |
| outputsIds | The IDs (UUIDs) of the generated transcriptions or translations from this order (only present if order is fulfilled) |
| transcriptions | Generated transcriptions or subtitles from this order, together with their state and estimated delivery time |
| ingestions | File ingestions for this order (see "Ingestion Object" below) |
| failure_reason | Present when state is failed. A high-level category of the failure: ingestion_failed, transcription_failed or unknown. See "Failure Reasons" below. |
Order States
| State | Description |
|---|---|
| incomplete | The order has been created but not yet submitted for processing |
| waiting_for_payment | The order is waiting for payment to be processed |
| submitted | The order has been submitted for processing but the service has not been completed yet (for example, the transcription is in progress) |
| locked | There were not sufficient credits or balance in the account to pay for the order. It needs to be unlocked from the UI after upgrading or topping up |
| fulfilled | The order has been completed successfully. The transcription, subtitles or translation is ready |
| failed | The order processing has failed |
| canceled | The order has been canceled |
| expired | An old failed or incomplete order that has been cleaned up |
| free_trial_submitted | Legacy state for free trial orders that have been submitted |
| free_trial_fulfilled | Legacy state for free trial orders that have been fulfilled |
Ingestion Object
Each entry in the ingestions array represents a file being downloaded from the URL provided when the order was created.
| Field | Description |
|---|---|
| id | The ingestion ID |
| name | The name of the file being ingested |
| state | Current state of the ingestion (idle, transferring, transferred, analyzing, done, failed, expired) |
| failure_reason | Only present when state is failed. One of failed_import, invalid_file, failed_analysis, unknown. |
| failure_message | Only present when state is failed. A human-readable description of the failure suitable for displaying to an end user. |
Failure Reasons
When an order is in the failed state, failure_reason categorises the failure so you know where to look for details:
| Value | Meaning |
|---|---|
| ingestion_failed | One or more files could not be imported. Inspect each ingestions[] entry for the specific reason and message. |
| transcription_failed | The file was imported but the transcription/subtitling step failed. Inspect transcriptions[] for details. |
| unknown | The order is marked as failed without an identifiable underlying cause. If you see this, please contact support. |
For ingestion failures, the per-ingestion failure_reason narrows it down further:
| Value | Meaning |
|---|---|
| failed_import | We could not download the file from the provided URL (e.g. the URL returned an error, is private, or expired). |
| invalid_file | The file was downloaded but its format is not supported. |
| failed_analysis | We could not extract media metadata (duration, codec, etc.) from the file. |
| unknown | Something else went wrong. If you see this, please contact support. |
Operations Object
The operations array contains details about each operation being performed as part of the order:
| Field | Description |
|---|---|
| name | The type of operation (e.g., "transcription_translation", "subtitles") |
| type | The service level ("auto" or "pro") |
| language | The source language code |
| target_language | The target language code for translation operations |
| glossary_ids | Array of glossary IDs applied to the operation |
| style_guide_id | ID of the style guide applied to the operation |
| use_vocab | Whether to use vocabulary optimization (for subtitle operations) |
Confirm an Order
curl -X POST "https://www.happyscribe.com/api/v1/orders/<ID>/confirm" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/orders/<ID>/confirm', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
This endpoint confirms an order that was previously created with confirm=false. Once confirmed, the order will begin processing according to the service type selected.
HTTP Request
POST https://www.happyscribe.com/api/v1/orders/<ID>/confirm
URL Parameters
| Parameter | Description |
|---|---|
| ID | The unique identifier of the order to confirm |
Response Codes
| Status | Meaning |
|---|---|
| 200 | Order was confirmed and submitted for processing. |
| 400 | The order cannot be submitted in its current form (for example, it was already submitted, its language isn't available, or a localization target is missing). The response body contains an error message describing the specific reason. |
| 409 | The order's media is still being ingested and cannot be confirmed yet. Retry after a short delay — the response includes a Retry-After header with the suggested wait in seconds. You can avoid this entirely by creating the order with confirm: true so the order auto-submits once it's ready. |
Glossaries
List Glossaries
curl "https://www.happyscribe.com/api/v1/glossaries?organization_id=123" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/glossaries?organization_id=123', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"glossaries": [
{
"id": 1,
"name": "Medical Terms",
"source_language": "en",
"target_languages": ["es", "fr"],
"organization_default": false,
"imported": true,
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-02-01T14:20:00.000Z"
},
{
"id": 2,
"name": "Legal Terms",
"source_language": "en",
"target_languages": ["de"],
"organization_default": true,
"imported": false,
"created_at": "2024-01-10T09:00:00.000Z",
"updated_at": "2024-01-20T11:30:00.000Z"
}
]
}
Returns a list of glossaries available in the specified organization. Glossary IDs from this endpoint can be used when creating orders to apply specific terminology during transcription or translation.
HTTP Request
GET https://www.happyscribe.com/api/v1/glossaries
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| organization_id | none | (required) The ID of the organization to list glossaries for. |
Response
| Field | Description |
|---|---|
| id | Unique identifier for the glossary |
| name | Name of the glossary |
| source_language | Source language code of the glossary |
| target_languages | Array of target language codes the glossary supports |
| organization_default | Whether this glossary is the default for the organization |
| imported | Whether the glossary was imported from an external source |
| created_at | Timestamp when the glossary was created |
| updated_at | Timestamp when the glossary was last updated |
Style Guides
List Style Guides
curl "https://www.happyscribe.com/api/v1/style_guides?organization_id=123" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/style_guides?organization_id=123', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"style_guides": [
{
"id": 1,
"name": "Corporate Standard",
"operation": "transcription",
"organization_default": true,
"verbatim": false,
"fix_grammar": true,
"sdh": false,
"speaker_id": "full_name",
"notation_tags": "standard",
"created_at": "2024-01-10T09:00:00.000Z",
"updated_at": "2024-01-20T11:30:00.000Z"
},
{
"id": 2,
"name": "Subtitle Guidelines",
"operation": "subtitles",
"organization_default": false,
"verbatim": false,
"fix_grammar": false,
"sdh": true,
"speaker_id": "default",
"notation_tags": "no",
"created_at": "2024-02-01T14:00:00.000Z",
"updated_at": "2024-02-05T16:45:00.000Z"
}
]
}
Returns a list of style guides available in the specified organization. Style guide IDs from this endpoint can be used when creating orders to apply specific formatting and transcription preferences.
HTTP Request
GET https://www.happyscribe.com/api/v1/style_guides
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| organization_id | none | (required) The ID of the organization to list style guides for. |
Response
| Field | Description |
|---|---|
| id | Unique identifier for the style guide |
| name | Name of the style guide |
| operation | The type of operation this style guide applies to: transcription or subtitles |
| organization_default | Whether this style guide is the default for its operation type in the organization |
| verbatim | Whether verbatim transcription is enabled (every word and filler is transcribed exactly as spoken). Only supported for pro service in English, Spanish, French, and German |
| fix_grammar | Whether grammar correction is enabled |
| sdh | Whether SDH (Subtitles for the Deaf and Hard of Hearing) is enabled. Only supported for pro service in English, Spanish, and French |
| speaker_id | How speakers should be identified: default, full_name, gender, or description |
| notation_tags | Notation tag preference: no (none), standard, or custom |
| created_at | Timestamp when the style guide was created |
| updated_at | Timestamp when the style guide was last updated |
Organizations
List Organizations
curl "https://www.happyscribe.com/api/v1/organizations" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/organizations', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"organizations": [
{
"id": 123,
"name": "Acme Corp",
"role": "owner",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-02-01T14:20:00.000Z",
"ownerEmail": "owner@acme.com",
"membersCount": 12,
"isHumanTranscriptionAllowed": true,
"isHumanTranslationAllowed": true,
"emailDomains": ["acme.com"],
"idpCompanyNames": ["Okta", "Azure AD"],
"currency": "usd"
},
{
"id": 456,
"name": "Personal workspace",
"role": "member",
"createdAt": "2023-08-01T09:00:00.000Z",
"updatedAt": "2024-03-10T16:45:00.000Z"
}
]
}
Returns the organizations the authenticated user belongs to.
HTTP Request
GET https://www.happyscribe.com/api/v1/organizations
Response
| Field | Description |
|---|---|
| id | Unique identifier for the organization |
| name | Display name of the organization |
| role | The authenticated user's role in this organization (owner, admin, member, or guest) |
| createdAt | Timestamp when the organization was created |
| updatedAt | Timestamp when the organization was last updated |
| ownerEmail | Email address of the organization owner (staff only) |
| membersCount | Number of members in the organization, excluding guests and deleted users (staff only) |
| isHumanTranscriptionAllowed | Whether the organization is allowed to order human transcription (staff only) |
| isHumanTranslationAllowed | Whether the organization is allowed to order human translation (staff only) |
| emailDomains | Domains that auto-join the workspace at sign-up (staff only) |
| idpCompanyNames | IdP company names configured for SSO; empty array when SSO is not configured (staff only) |
| currency | Billing currency code, e.g. usd, eur, gbp (staff only) |
Organization Memberships
Manage memberships (users ↔ organizations). All endpoints authenticate with an API key. An owner or admin role is required for every action except listing, which is also available to regular members (they see only their own row).
List Memberships
curl "https://www.happyscribe.com/api/v1/organization_memberships?organization_id=123" \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/organization_memberships?organization_id=123', {
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
The above command returns JSON structured like this:
{
"members": [
{
"id": 9001,
"organizationId": 123,
"organizationName": "Acme Corp",
"email": "alice@acme.com",
"name": "Alice Smith",
"role": "admin",
"createdAt": "2024-02-01T10:00:00.000Z",
"updatedAt": "2024-05-12T11:30:00.000Z"
},
{
"id": 9000,
"organizationId": 123,
"organizationName": "Acme Corp",
"email": "owner@acme.com",
"name": "Bob Owner",
"role": "owner",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
],
"_links": {
"next": {
"url": "https://www.happyscribe.com/api/v1/organization_memberships?organization_id=123&page=2"
}
}
}
Returns memberships across all organizations the caller belongs to. The response is paginated and it return 25 results per page. Supports the filters defined below.
HTTP Request
GET https://www.happyscribe.com/api/v1/organization_memberships
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| organization_id | none | Restrict the result to a single organization |
| role | none | Filter by exact role (owner, admin, member, guest) |
| none | Case-insensitive partial match on the user's email | |
| name | none | Case-insensitive partial match on the user's full name |
| page | 1 | Page number to fetch |
Response
| Field | Description |
|---|---|
| id | Unique identifier for the membership |
| organizationId | ID of the organization the membership belongs to |
| organizationName | Name of the organization the membership belongs to |
| Email address of the member | |
| name | Full name of the member |
| role | Role of the member (owner, admin, member, or guest) |
| createdAt | Timestamp when the membership was created |
| updatedAt | Timestamp when the membership was last updated |
| _links.next.url | URL of the next page (absent on the last page) |
Add a Membership
curl "https://www.happyscribe.com/api/v1/organization_memberships" \
-X POST \
-H "Authorization: Bearer **your_api_key_here**" \
-H "Content-Type: application/json" \
-d '{"organization_id": 123, "email": "new-hire@acme.com", "role": "member"}'
fetch('https://www.happyscribe.com/api/v1/organization_memberships', {
method: 'POST',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({
organization_id: 123,
email: 'new-hire@acme.com',
role: 'member',
}),
});
If the email belongs to an existing HappyScribe user, the membership is created immediately and the response is
201 Created:
{
"member": {
"id": 9002,
"organizationId": 123,
"organizationName": "Acme Corp",
"email": "new-hire@acme.com",
"name": "New Hire",
"role": "member",
"createdAt": "2024-06-01T12:00:00.000Z",
"updatedAt": "2024-06-01T12:00:00.000Z"
}
}
If the email is new to HappyScribe, an invitation is emailed instead and the response is
202 Accepted:
{
"invite": {
"email": "new-hire@acme.com",
"role": "member"
}
}
Adds a user to the organization. If the email belongs to an existing HappyScribe user they become a member instantly; otherwise an invitation email is sent.
Only the admin and member roles can be assigned through this endpoint.
HTTP Request
POST https://www.happyscribe.com/api/v1/organization_memberships
Body Parameters
| Parameter | Description |
|---|---|
| organization_id | (required) ID of the organization |
| (required) Email address of the user to add | |
| role | (required) admin or member |
Errors
| Status | Condition |
|---|---|
| 400 | organization_id missing, or role is not one of admin, member |
| 401 | Caller is not an owner or admin of the organization |
| 404 | Organization does not exist, is archived, or the caller is not a member |
| 422 | Email is invalid, already a member, already invited, plan does not allow the requested role, or plan seat limit is reached |
Update a Membership's Role
curl "https://www.happyscribe.com/api/v1/organization_memberships/9002" \
-X PATCH \
-H "Authorization: Bearer **your_api_key_here**" \
-H "Content-Type: application/json" \
-d '{"role": "admin"}'
fetch('https://www.happyscribe.com/api/v1/organization_memberships/9002', {
method: 'PATCH',
headers: {
authorization: 'Bearer **your_api_key_here**',
'content-type': 'application/json',
},
body: JSON.stringify({ role: 'admin' }),
});
On success the response is
200 OK:
{
"member": {
"id": 9002,
"organizationId": 123,
"organizationName": "Acme Corp",
"email": "new-hire@acme.com",
"name": "New Hire",
"role": "admin",
"createdAt": "2024-06-01T12:00:00.000Z",
"updatedAt": "2024-06-10T15:30:00.000Z"
}
}
Changes a member's role. The new role must be admin or member; the owner's role cannot be changed through this endpoint.
HTTP Request
PATCH https://www.happyscribe.com/api/v1/organization_memberships/:id
URL Parameters
| Parameter | Description |
|---|---|
| id | (required) ID of the membership |
Body Parameters
| Parameter | Description |
|---|---|
| role | (required) admin or member |
Errors
| Status | Condition |
|---|---|
| 400 | role is not one of admin, member |
| 401 | Caller is not an owner or admin, the target is the organization owner, or the plan does not allow the requested role |
| 404 | Membership does not exist or belongs to an archived organization |
Remove a Membership
curl "https://www.happyscribe.com/api/v1/organization_memberships/9002" \
-X DELETE \
-H "Authorization: Bearer **your_api_key_here**"
fetch('https://www.happyscribe.com/api/v1/organization_memberships/9002', {
method: 'DELETE',
headers: {
authorization: 'Bearer **your_api_key_here**',
},
});
A successful call returns
204 No Content.
Removes a member from the organization. The owner cannot be removed through this endpoint. Staff members may remove themselves.
HTTP Request
DELETE https://www.happyscribe.com/api/v1/organization_memberships/:id
URL Parameters
| Parameter | Description |
|---|---|
| id | (required) ID of the membership |
Errors
| Status | Condition |
|---|---|
| 401 | Caller is not an owner or admin, or the target membership belongs to the organization owner |
| 404 | Membership does not exist or belongs to an archived organization |