Skip to main content
Every error Surfer handles is JSON in one envelope, whatever the endpoint returns on success: the status gives the class of failure and error.reason names the cause. Find the status and reason in the table below, then read error.details for the exact field or lookup that failed. An unhandled 500 falls outside the envelope: a JSON request gets {"errors": {"detail": "Internal Server Error"}}, and a request that asked for HTML gets an HTML error page.

The error envelope

Match errors by HTTP status and error.reason; treat error.message as optional context. A PATCH to a Content Editor’s SEO Guidelines terms that would raise the custom terms above 500 answers 400 with this body:

Reasons and what to do

Find the response’s status and reason below to choose the next action. Four messages carry their own remedy:
  • 409 with Content editor must be in completed state: wait until the editor is completed (Content Editor states). The capitalization of this message varies between endpoints, so match on the status and reason, not on the text.
  • 409 with A request with this idempotency key is currently being processed: wait for the first request to finish (Idempotent creates).
  • 422 with This idempotency key was already used with a different request: send a new key (Idempotent creates).
  • 422 with The AI writing system is overloaded, please retry shortly: wait, then send the request again (Create AI Article).

Validation details

Each item in the details of a validation_error names one problem with field and reason; fix all of them before you resend. field names what failed:
  • A body key or query parameter by name, for example keywords or page_size.
  • A nested key as parent.child.
  • A list position as parent.0.child in schema errors, and as parent[0].child in content-template and custom-voice body errors.
  • filter[state] for a rejected filter value.
  • body when the request body is missing or too large.
  • base when the problem concerns the request as a whole.
The common reason values: Schema errors name the failed check in reason and carry no message of their own; the envelope’s message describes every failure in one string. Other details carry a message when the check has more to say than the reason, as Maximum 500 custom terms allowed does above. A rejected sort or order value adds value, allowed, and default to the detail, so the response tells you what to send instead. An unknown order produces this detail:
A rejected filter value repeats the offending value in value, and a body that is not valid JSON answers with the message Malformed request body and empty details. Requests and responses has the list and body conventions themselves.

Not-found details

details says which lookup failed, so you can tell a wrong workspace from a wrong path.

v1 errors

v1 answers most failures with plain text, not the envelope. Humanizer and AI Detector answer 422 with a JSON {"error": "..."} body, and invalid parameters come back as 422 with a JSON:API errors array whose items carry title, detail, and source.pointer. Migrating from v1 covers the other differences.