API error codes and what they mean
The SignWith API uses conventional HTTP status codes, and every error response has the same small envelope with a stable code your program can branch on.
The error envelope
Every 4xx and 5xx response looks like this:
JSON
{
"error": {
"code": "invalid_signer",
"message": "Signer 2 needs an email or phone"
}
}
codeis stable. Branch on it in your code.messageis for people. It may change, so don't parse it; show it or log it.
All error codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_json | The request body is not valid JSON. |
| 401 | unauthenticated | The API key is missing, malformed or revoked, or its account has been archived. |
| 401 | api_key_expired | The API key has passed its expiry date. Create a new one. |
| 402 | insufficient_credits | Your account doesn't have enough credits to send this document. See Buying credits. |
| 403 | read_only_api_key | A read-only key was used for a write request. |
| 403 | insufficient_scope | MCP only: the AI app was connected with View only access and tried to change something. |
| 403 | not_available | MCP only: the tool isn't offered to this app (credit purchase tools in ChatGPT). |
| 403 | forbidden | The key's user doesn't have access to this resource. |
| 404 | not_found | The resource doesn't exist or belongs to another account, or no endpoint matches the method and path. |
| 409 | idempotency_key_in_use | Another request with the same Idempotency-Key is still running. |
| 422 | idempotency_key_reused | The Idempotency-Key was already used with a different request body. |
| 422 | missing_parameter | A required parameter is missing. |
| 422 | invalid_parameter | A parameter has an unsupported value (e.g. status, signing_order, expires_at not an ISO 8601 time in the future, prefill/metadata not an object, invalid signer email on update). |
| 422 | invalid_request | The request is well-formed but can't be processed (e.g. invalid prefill value). |
| 422 | missing_documents | A template was created without any documents. |
| 422 | too_many_documents | More than 10 documents were sent for one template. |
| 422 | document_too_large | A document is larger than 25 MB. |
| 422 | invalid_document | A document is empty, could not be downloaded, or is not valid base64 / PDF. |
| 422 | invalid_file_type | A document is not a PDF or an image. |
| 422 | invalid_field | A template field in fields is invalid (unknown type, missing options or areas, page or coordinates out of range, too many roles). |
| 422 | template_has_no_fields | The template has no fields to fill in or sign yet. Add fields with PATCH /templates/{id} or in the editor. |
| 422 | template_archived | The template is archived and can't be sent. Duplicate it or pick another one. |
| 422 | pdf_encrypted | The PDF is password protected and no password was sent. |
| 422 | missing_signers | A signature request has no usable signers. |
| 422 | invalid_signer | signers isn't a list of objects, a signer has no email or phone or an invalid email, has an unknown role, a role is given twice, or there are more signers than roles. |
| 422 | already_completed | The signature request is already fully signed. |
| 422 | not_open | The signature request was canceled, declined or has expired, so it can't be reminded and its signers can't be changed. |
| 422 | nothing_to_remind | No signer is currently waiting to sign. |
| 422 | signer_finished | The signer has already signed or declined. |
| 422 | invalid_discount_code | The discount code is invalid, used up, expired or not valid for this credit pack. |
| 422 | already_purchased | The user already has the lifetime deal. |
| 422 | billing_details_required | The user must add a billing country in SignWith before buying credits. |
| 429 | rate_limited | Too many requests (or more than 20 feedback messages in an hour). Wait for Retry-After seconds when present. |
| 429 | remind_too_soon | Signers of this request were reminded less than an hour ago, or (resend: true) this signer was emailed less than 10 minutes ago. |
| 500 | internal_error | Something went wrong on SignWith's side. Retry (with the same Idempotency-Key for POSTs); contact support if it persists. |
| 502 | payment_provider_error | The payment provider couldn't start the checkout. Try again later. |
Handling errors in practice
402 insufficient_creditsis the one most integrations should handle in the product: tell the user, or buy credits from the API and retry. See credits and billing.422codes mean the request itself needs fixing. The message names the parameter, signer or field, for exampleSigner 2 has role "Buyer", but the template's roles are: Tenant, Landlord.429,409and5xxare temporary. Retry them safely with the sameIdempotency-Key.401and403are about the key. See authentication.
Each endpoint in the API reference lists the statuses it can return.
Start building
The API and MCP server come with every account. 3 free documents a month, then pay per document.