Skip to content

Errors

Open .md

A request failed when either of these is true:

  • The HTTP status is 4xx or 5xx.
  • The JSON body has "success": false.

Check both. A few operations refuse with status 200 and "success": false, and some refuse a change with 500. They’re listed under Known exceptions.

Send Accept: application/json on every request. Matched paths always answer JSON, but a path that doesn’t exist (404) or a method it doesn’t take (405) answers an HTML page without that header. A missing second /v2/ is the usual cause. There’s no request id header to quote: when you ask for help, send the method, path, time and answer instead.

A failed request with Accept: application/json answers JSON in one of two shapes. Your code must handle both.

1. The standard error body. Most errors look like this:

{
"status": 422,
"success": false,
"error": {
"code": "validation_failed",
"message": null,
"fields": {
"customer.name": ["The customer.name field is required."]
}
}
}
Field Meaning
status Usually the HTTP status, repeated. On the 200 refusals listed under Known exceptions, it says 500 while the HTTP status is 200. Branch on the HTTP status and success, not on this field.
success false on an error.
error.code A short machine-readable reason, such as validation_failed or user_is_not_authorized. Can be null.
error.message A human-readable explanation. Often null.
error.fields On a validation error, the problems for each field, keyed by the field’s path in your body.
error.field_reasons Sometimes, with fields: a machine-readable reason for each field.

2. A bare message. A few errors have only message, with no status, success or error:

{ "message": "Insufficient Permission" }

You get this shape from:

  • A 403 when your role lacks a permission checked before the operation runs, such as Manage Settings: "Insufficient Permission".
  • A 422 when the team’s plan doesn’t include a feature: "This feature is not available to your team's plan."
  • A 500 from an unexpected failure: "Server Error".
  • A few operation-specific refusals, which their reference pages show, such as a product that isn’t found when you add a line.

Without Accept: application/json, a path that doesn’t exist (404) or a method it doesn’t take (405) answers an HTML page instead. A request over 100 MB is refused with 413 before YoPrint reads it, so that answer isn’t JSON either.

So read error.code when error is an object, and fall back to message:

const code = typeof body?.error === 'object' && body.error !== null ? body.error.code : null;
const message = body?.error?.message ?? body?.message ?? null;

Handle errors in this order:

  1. HTTP status and successDid it fail?
  2. error.codeWhy, when it isn’t null
  3. error.fieldsWhich input to fix
  4. error.message or messageTo log or show a person
Don't parse the message: its wording can change.
Status What it means What to do
400 A value YoPrint checks before anything else isn’t one it knows, such as the event name in Show a sample event. Fix the value. The operation’s reference page lists the ones it takes.
401 The API key is missing or wrong, or it was regenerated. error.code is unauthenticated. Send Authorization: Bearer YOUR_API_KEY with the current key. See Authentication.
402 A payment for your YoPrint subscription failed. Follow next_action: use_different_card, update_card_then_retry, or refresh_billing when the subscription ended during a retry.
403 Your team’s plan doesn’t include API access (api_access_not_in_plan), your role doesn’t allow this operation, or the call manages the key itself (self_credential). For api_access_not_in_plan, use a team on the Pro plan or higher. Otherwise check your role. See Roles and permissions.
404 The team slug is wrong, you’re not on that team, or the record doesn’t exist on this team. error.code is page_not_found or null. Check the slug and the id. Ids are the id field, not document numbers. See IDs.
405 The path exists, but not with this method. Check the method on the operation’s reference page.
409 Not saved: the record changed since you read it, or the id is an older, replaced version of it (some addresses and locations). Read it again and retry. When there’s a newer version, the answer points at it, such as current_address.
410 Gone for good: a file or an attempt that expired, such as an import’s error file. Start again.
413 The request is over 100 MB. The web server refuses it before YoPrint reads it, so the body isn’t JSON. Send a smaller file.
422 The request was understood but refused: a field is missing or invalid, or a business rule stops it. Read error.fields or error.message, fix the request, and send it again.
429 Your team already has the most data exports running at once. Wait for one to finish, then start yours. See Limits.
500 Something failed inside YoPrint, or one of the business refusals listed below. Check the list below. Otherwise read the record back before you retry. See Retries and duplicates.
503 YoPrint is briefly unavailable, or exports are paused (export_creation_paused, with Retry-After). Wait and retry, reading back first if it was a change.

validation_failed: a field is wrong. error.fields names each field with its problems, and error.message is null.

validation_error, or another code: a business rule refuses the change. The fields are fine, but the record’s state doesn’t allow it. error.message says why. For example, recording a payment on a draft order answers:

{
"status": 422,
"success": false,
"error": {
"code": "validation_error",
"message": "Payment Action Not Allowed - due to order internal state"
}
}

Fix the state first (here, publish the order), then retry.

These are the codes you can get on most operations. Operation-specific codes, such as payment_below_minimum or stale_address, are on each operation’s reference page under Errors.

Code Status What it means What to do
unauthenticated 401 The key is missing or wrong, or it was regenerated. Send Authorization: Bearer YOUR_API_KEY with your current key.
api_access_not_in_plan 403 The key works, but the team’s plan doesn’t include API access. Every request to this team answers this. Use a team on Pro or higher, or upgrade this one. See Authentication.
self_credential 403 The call reads, creates or resets the key itself. A key can’t manage itself. Manage the key in Profile.
user_is_not_authorized 403 Your role doesn’t allow this action on this record. Ask the team owner to change your role, or use a key whose role allows it.
unauthorized 403 A role or ownership check refused it. message is null. As above.
No code: { "message": "Insufficient Permission" } 403 Your role lacks a permission, such as Manage Settings. As above.
page_not_found 404 The team slug is wrong, you’re not a member of the team, or an id in the path isn’t one of this team’s. Check the slug against Team ID in Profile, and the id.
null, with a message starting “No query results for” 404 No record with that id on this team. Check the id. Ids are the id field, not document numbers.
validation_failed 422 A field is missing or invalid. error.fields names each one. Fix the fields and send the request again.
validation_error 422 A business rule refused the change. error.message says why. Fix the record’s state, then retry.
bulk_validation_payload_failed 422 One item of a bulk request is invalid. error.bid names it. Nothing was saved. Fix that item and send the whole request again.
amount_out_of_range 422 The save would answer with an amount the older number format can’t carry exactly. Nothing was saved. Send X-Yoprint-Decimal-Format: exact-v1 and retry.
upload_not_allowed 422 The file is a web page, a script or a program. Send another file type, or zip it.
mockup_type_not_allowed, image_not_allowed 422 A mockup isn’t an image YoPrint can preview, or an image is over a size limit. Upload it as a production file, or send a smaller image.
duplicate_report 422 An export of the same kind is already running. Wait for it to finish.
connect_timeout 422 Another service YoPrint called, such as Shippo, Shopify or QuickBooks, didn’t answer in time. The change may have happened there. Read the record back before you retry.
No code: { "message": "This feature is not available to your team's plan." } 422 The team’s plan doesn’t include this feature. Upgrade the plan, or leave the feature out.
validation_error, “You are sending too many emails…” 422 The team went over an email limit. All of the team’s email is now blocked. Stop sending, and contact YoPrint support to lift the block. See Limits.
email_feature_not_enabled_in_trial 422 The team is on a trial, and YoPrint hasn’t turned email on for it. Nothing was sent. Contact YoPrint support, or send once the subscription is paid.
export_capacity 429 The team already has 3 exports running. Wait for one to finish, then start yours.
action_not_allowed 200 or 500 The record’s state doesn’t allow the action. See Known exceptions. Don’t retry without fixing the state.
delete_fail 500 or 422 The record can’t be deleted: it’s a default, made by YoPrint, a primary contact, or a customer with an open quote or order. Change the default or the primary first, or close the open orders.
export_creation_paused 503 Exports are paused for a few minutes while YoPrint updates. Retry-After says how long. Wait that many seconds, then send it again.
No code: { "message": "Server Error" } 500 Something failed inside YoPrint. Read the record back before you retry. See Retries and duplicates.

error.code is sometimes not a short code but a sentence or a number, such as "Insufficient Order Balance" on some payment refusals. Branch on the HTTP status and success first, and treat any code you don’t know as a refusal.

A 404 for a record means YoPrint found nothing with that id on this team. The usual causes:

  • The id is a document number such as SO1001, or a value from another team.
  • The record was deleted.
  • The slug is wrong, so no record on any path will be found.

The message of a record 404 can name an internal class. Ignore it: it isn’t part of the API.

These operations don’t follow the rule that a refusal is a 4xx. Your code must check success, and must not retry the 500s below without fixing the cause: they fail the same way every time.

These answer HTTP 200 with a body like this. They change nothing, except Delete a job, which deletes the job anyway. “Neither a draft nor published” only happens on some older orders, made before YoPrint’s current order system. Orders made today are always one or the other.

{ "status": 500, "success": false, "error": { "code": "action_not_allowed", "message": null } }
Operation When
Publish a sales order or quote It’s already published.
Restore a sales order or quote It isn’t deleted.
Create a job, or add one from a job preset The order is neither a draft nor published.
Reorder an order’s jobs The order is neither a draft nor published.
Update a job The order is neither a draft nor published.
Change a job’s status The order isn’t published (a draft).
Delete a job The order is neither a draft nor published. The job is deleted anyway, then this refusal comes back. Don’t retry: read the order’s jobs, and the job is gone.
Add or list a job’s tasks (work pipeline) The order is neither a draft nor published.
Integration data for Square with type create_device_code (a terminal pairing code) Square refuses. Here error.code is a number, 422.

Refused with 200 and "success": true, but nothing done

Section titled “Refused with 200 and "success": true, but nothing done”

Publishing a sales order or quote answers 200 with "valid": false when the order isn’t ready. Check data.valid after you publish:

{
"status": 200,
"success": true,
"data": {
"id": "V4keXwwxMQyXw7",
"valid": false,
"validation": {
"has_customer": true,
"has_order_items": false,
"has_sellable_items": true,
"unsellable_items": []
}
}
}
Operation When
Delete a customer’s or vendor’s contact It’s the primary contact (delete_fail).
Delete a currency, payment method, payment term, shipping box, shipping method, tax preset or fee preset It’s the team’s default, or made by YoPrint (delete_fail).
Create, delete or sync statuses The status type isn’t allowed, such as pre_production, or a start or pre_production status is deleted.
Delete a sales order approval The approval is completed.
Delete a system message template Always (delete_fail).
Filter shipments You filtered on ship_due_date, order_external_type or shipment_source.
Buy a GoShippo label Shippo failed or timed out during the purchase. A label may have been bought. Don’t retry. See Ship an order.
Get rates, carriers or estimates from GoShippo, or track a package Shippo refused the request or couldn’t be reached.

Each operation’s reference page lists its own errors, including these.