NutraSoft food manufacturing ERP software
Esc
  • GuideGetting startedThree steps to your first call and your first order, then the two shapes every response takes.
  • GuideAuthentication and keysBearer keys, test and live environments, rotation without an outage, and what each scope grants.
  • GuideTest modeA second NutraSoft account of your own, seeded with realistic data, that you can safely break.
  • PageErrorsEvery error code the API returns, what it means, what to do about it and whether to retry.
  • PageConventionsThe rules every operation follows: money, time, paging, sorting, nulls, PATCH and identifiers.
Menu

Errors

Every error code the API returns, what it means, what to do about it and whether to retry.

Every error has one shape, whatever went wrong. Branch on code, never on message: codes are added over time but never renamed or repurposed, and messages are written for people and may change.

  • details lists the offending fields when a request fails validation, each with its field, a message and a machine-readable type. It is null otherwise.
  • request_id is also in the X-Request-Id header of every response. Quote it in any support request.
  • The status code groups the codes: 400 for a malformed request or an unknown referenced id, 401 for a missing or rejected key, 403 for plan, scope or read-only refusals, 404 for a path id that is not in your account, 409 for duplicates, state conflicts and records still in use.
json
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "One or more parameters are invalid.",
    "details": [
      { "field": "body.lines", "message": "List should have at most 200 items after validation, not 201", "type": "too_long" }
    ],
    "request_id": "req_4f1c8a90b7e24d3f9c0a5b6e7d8f9012"
  }
}
INVALID_REQUEST400

The request is malformed: a missing or invalid parameter, an unknown field in the body, an id in the body that is not in your account, a sort field the operation does not accept, a line list outside its limits, or search combined with a filter it would override.

Read details, fix the request and send it again.

Retry:After fixing
UNAUTHENTICATED401

No credentials: the Authorization header is missing or is not Bearer <key>.

Send the key as a bearer token.

Retry:After fixing
INVALID_API_KEY401

A key was sent and rejected: it is wrong, revoked, past its rotation grace period, or its nsk_live_ or nsk_test_ prefix does not match its account.

Check which key is deployed and its prefix. The message is deliberately the same for every cause.

Retry:After fixing
NOT_ENTITLED403

The account's plan does not include the API: it is not a paid Enterprise plan, or the plan has lapsed. Test keys follow the plan of the account that owns them.

The account owner needs an active paid Enterprise plan. On a plan without the API, keys can still be listed and revoked meanwhile.

Retry:No
INSUFFICIENT_SCOPE403

The key does not carry the scope the operation needs. Each operation in the reference shows its scope.

Add the scope to the key in Settings, Developer, or use a key that has it.

Retry:After fixing
READ_ONLY403

The request tries to change a shared reference row, one marked is_global, which every account can read but none can change.

Create your own row and use it instead.

Retry:No
NOT_FOUND404

The id in the path is not in your account. The API does not distinguish a record that does not exist from one that belongs to someone else.

Check the id, and that the key is for the account you expect.

Retry:No
CONFLICT409

The request conflicts with the current state: a duplicate code, a status change the document's state does not allow, a record still in use elsewhere, or an Idempotency-Key reused with a different body.

Read the message, fetch the current state and decide what to do. Sending the same request again will fail the same way.

Retry:No
UNPROCESSABLE422

The request was understood but cannot be applied. Rare in v1: most such refusals are INVALID_REQUEST or CONFLICT.

Read the message and change the request.

Retry:No
RATE_LIMITED429

The account went over its 300 requests per minute, or one IP address sent too many requests that failed authentication.

Wait the number of seconds in Retry-After, then retry.

Retry:Yes
INTERNAL_ERROR500

Something went wrong on our side, including a request whose database work ran past the time limit. The failure is recorded against its request_id.

Retry reads with backoff. Before retrying a write, check whether it landed. If it persists, contact support with the request_id.

Retry:Reads only
SERVICE_UNAVAILABLE503

We were briefly out of capacity to serve the request.

Wait the number of seconds in Retry-After, then retry with exponential backoff and jitter.

Retry:Yes