Getting started
Errors
When a request fails, the API returns a 4xx or 5xx status with a JSON error that has a code, a message and often a hint about what to do next.
The error object
Every error has the same shape:
{ "error": { "code": "session_invalid", "message": "Source src_01a1446f8e8f7b23a4c06d1c3e5f7a90 is 10.0 milliseconds shorter than source src_01a1446f235c7448abbe096c9b9adf6c", "hint": "Trim the files to the same length, within 2.7 milliseconds, before uploading", "details": { "source_id": "src_01a1446f8e8f7b23a4c06d1c3e5f7a90" } }}- codestring
The kind of error, such as
validation_errorornot_found. - messagestring
What went wrong.
- hintstring
What to do about it. The field is omitted when there's no hint.
- detailsobject
More about the error, such as
fieldsfor a validation error or thesource_id,job_idorrequired_scopesinvolved. The field is omitted when it would be empty.
Your code should branch on the status and the code. The message and hint are written for people, so log them or show them to your user.
Error codes
| Code | Status | When |
|---|---|---|
validation_error | 400 | A field is missing or invalid, or the request breaks a rule, such as asking for ADM files and tracks in one job. |
unauthorized | 401 | The API key is missing, not valid, revoked or expired. |
forbidden | 403 | The API key does not have the scope the route needs. |
not_found | 404 | The ID doesn't exist, was deleted or isn't your organization's. You also get it for an unknown path, an expired upload and the outputs of a job that isn't done yet. |
method_not_allowed | 405 | The path exists but doesn't take this method. |
conflict | 409 | The upload is already complete, the source is in a session, or the session has a job that is running or may still finish. |
upload_incomplete | 409 | Some parts are missing, or they don't match the parts you listed. |
idempotency_conflict | 409 | The Idempotency-Key was already used with a different body. |
job_not_cancellable | 409 | Processing has already started, or the job has ended. |
payload_too_large | 413 | The request body is larger than 1 MiB. |
source_rejected | 422 | The uploaded file can't be used, for example because it isn't WAV or FLAC or is shorter than one second. |
session_invalid | 422 | The session breaks a session rule, such as more than four microphones or sources of different lengths. |
internal | 500 | Something went wrong on our side. |
Details
Some errors add details, with values your code can act on:
| Field | Error | Value |
|---|---|---|
fields | validation_error | The fields that are invalid, each with a message. |
source_id | session_invalid | The source you need to fix. |
job_id | conflict | The job that stops the session from being deleted. |
required_scopes | forbidden | The scopes the route needs. |
Validation errors
A request that doesn't validate gets a 400 that lists each wrong field in details.fields:
{ "error": { "code": "validation_error", "message": "The request is not valid", "details": { "fields": [ {"field": "body.products", "message": "Field required"}, {"field": "body.outputs", "message": "Field required"} ] } }}Each field is a dotted path, starting with body, query or header, to the value that failed, such as body.sources.0.label, query.limit or header.idempotency-key. List positions count from 0, and in a job's outputs the output's type follows its position, as in body.outputs.0.mix.format.
POST /v1/sessions and POST /v1/jobs reject fields they don't know, while the upload routes ignore them. An empty body, invalid JSON, or a body sent without Content-Type: application/json is a 400 validation_error as well.
When a request is valid but breaks one of the API's rules, such as the combination rules for jobs, it gets a 400 validation_error without details, and the message names the rule:
{ "error": { "code": "validation_error", "message": "An ADM output cannot be made in the same job as tracks, a mix or an analysis", "hint": "Create a separate job on the same session for the tracks, mix or analysis" }}In a session, an unknown role or array is a 422 session_invalid instead, with the source in details.source_id.
Other statuses
Calling a path with a method it doesn't take returns a 405 method_not_allowed, and the Allow header lists the methods it does take:
HTTP/1.1 405 Method Not Allowedallow: GET, POSTcontent-type: application/json{"error": {"code": "method_not_allowed", "message": "Method Not Allowed"}}A 500 internal comes without a hint or details. To retry POST /v1/jobs after one without creating a second job, send an Idempotency-Key.
Handling errors
The request below leaves out the job's products and outputs, so it fails validation:
curl -sS -i https://platform-api.nomono.co/v1/jobs \ -H "Authorization: Bearer $NOMONO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"session_id": "ses_01a14471a03b7c56a1e28d9f4b6c7d8e"}'The Python version prints:
400 validation_error The request is not validbody.products: Field requiredbody.outputs: Field requiredFailed jobs
A job that fails during processing isn't an HTTP error. Its status becomes failed, and its error has the code processing_failed and a message that tells you what to do. See Jobs.