Menu

Errors

Every failed call answers with JSON in the same shape, whatever your Accept header says. Branch on its code.

The error body

A failure carries a human-readable message and a stable code:

{
    "code": "missing_ability",
    "message": "Invalid ability provided."
}

A validation failure adds errors: per field, the messages saying what is wrong with it.

{
    "code": "validation_failed",
    "message": "The lines field is required.",
    "errors": {
        "lines": ["The lines field is required."]
    }
}

The message is meant for people and can change. The code is part of the contract: codes are only ever added, never renamed or removed. If your integration meets a code it doesn't know, go by the HTTP status.

Every code

Code Status What happened What to do
validation_failed 422 The request body or query has a field Picked can't accept. errors says which. Fix the request. Sending it again unchanged fails again.
bad_request 400 The request is malformed, for example a Picked-Dry-Run header that isn't true or false. Also used for any other 4xx status this table doesn't list. Fix the request.
unauthenticated 401 The token is missing, mistyped or revoked, or the member who issued it was removed from the workspace. Stop, and check the token your integration sends.
missing_ability 403 The token is valid but lacks the ability this endpoint needs. Stop, and issue a token with the right ability. See Authentication & abilities.
forbidden 403 The token may not act here, for example because you called another workspace's address with it. Stop, and check the address and the token.
not_found 404 The address doesn't exist, or the thing you asked for isn't in your workspace: an unknown SKU, an unknown receipt id. Fix the request. Don't retry.
method_not_allowed 405 The address exists, but not for this HTTP method. Fix the request.
conflict 409 An Idempotency-Key was already used for a different request, or a request with it is still being handled. Send a new key; for a request still being handled, retry shortly.
gone 410 The thing you called back on no longer waits for you: a step's callback after it timed out or ended another way. Stop: the work has gone its own way. Don't retry.
rate_limited 429 Your workspace made too many calls this minute. Wait the number of seconds in Retry-After, then retry. See Rate limits.
temporarily_unavailable 503 The call ran into a concurrent one, or the work you called back on can't carry on yet. Wait the number of seconds in Retry-After, then retry.
server_error 500 Something went wrong on Picked's side. Retry a few times with a growing pause. If it keeps failing, contact us.

Retrying safely

Only rate_limited, temporarily_unavailable and server_error are worth retrying, always with a pause in between. Every other code means the same request will fail the same way, with two exceptions that Idempotency explains: a receipt whose reference arrived twice at the same moment, and a process event that Picked accepted but couldn't act on yet.

Retry a write only when Picked can recognise the repeat; the same page says which writes it recognises.

Find a failed call

The API tokens page lists each token's recent calls under Requests. It shows only the failed ones until you switch off Errors only. For a failure it keeps the response Picked gave; for a 5xx, only its code. That is the quickest way to see which call went wrong and why.