Reference
Errors, retries and pagination
Every error code, how Idempotency-Key makes retries safe, and how to page through lists.
Error format
json
{
"error": {
"code": "card_required",
"message": "Add a card to start sending. Your free documents are used up and this business has no card in Kiewa. Test envelopes (test: true) are still free.",
"add_card_url": "https://bms.kiewa.com.au/..."
}
}code is stable: branch on it. message says what went wrong and how to fix it, written so an AI agent can act on it. Some errors carry extra fields, shown below.
Idempotency
Every write (POST, PATCH, DELETE) accepts an Idempotency-Key header, up to 255 characters. The first answer is stored for 24 hours; repeating the request with the same key returns that answer with Idempotent-Replayed: true, and does nothing again. Use something tied to your own record, like quote-1042-send, and send it on every attempt.
Pagination
Lists return has_more and next_cursor. Pass cursor to get the next page; limit is 1 to 100 (default 20).
bash
curl "https://squiggli.billy-965.workers.dev/v1/envelopes?status=sent,viewed&limit=50&cursor=env_..." -H "Authorization: Bearer $SQUIGGLI_API_KEY"Error codes
| Status | Code | Means |
|---|---|---|
| 400 | invalid_request | The body or query failed validation. field names the first bad one. |
| 400 | invalid_json | The body is not valid JSON. |
| 400 | invalid_month | month must be YYYY-MM. |
| 400 | invalid_idempotency_key | Idempotency-Key is longer than 255 characters. |
| 401 | unauthorized | No key, or the key is wrong or revoked. |
| 401 | access_code_required | This signer needs to enter their access code. |
| 402 | card_required | Free documents are used up and there is no card. add_card_url is where the business adds one. Test envelopes still work. |
| 403 | squiggli_not_enabled | The business doesn't have squiggli in Kiewa. |
| 403 | forbidden | This credential can't do that (for example, an embed token outside its scope). |
| 403 | wrong_access_code | The access code is wrong. |
| 403 | cross_site | A cookie-authenticated write came from another site. |
| 404 | not_found | No such envelope, template, webhook or key in this account. |
| 404 | invalid_link | The signing link isn't valid, or the envelope hasn't been sent. |
| 404 | not_linked | The business's billing isn't through Kiewa. |
| 409 | already_sent | It's not a draft any more. |
| 409 | not_open | It's signed, declined, voided or expired, so it can't change. |
| 409 | is_draft | Drafts are deleted, not voided. |
| 409 | not_draft | Only drafts can be deleted. |
| 409 | not_your_turn | A sequential signer tried to sign before their turn. |
| 409 | not_viewed | The signer must open the document before signing. |
| 409 | already_signed | This signer has signed. |
| 409 | already_declined | This signer declined. |
| 409 | document_changed | A document no longer matches its hash from sending, so it can't be signed. |
| 409 | not_signed | The signed PDF exists once everyone has signed. |
| 409 | idempotency_in_progress | A request with this Idempotency-Key is still running. Retry shortly. |
| 409 | own_key | You can't revoke the key the request is using. |
| 410 | voided | The sender cancelled it. |
| 410 | declined | Someone declined it. |
| 410 | expired | The deadline passed. |
| 410 | link_expired | The download link is over 7 days old. Get a new one from the envelope. |
| 413 | file_too_large | PDFs can be up to 10 MB. |
| 413 | signature_too_large | Signature images can be up to 500 KB. |
| 413 | logo_too_large | Logos can be up to 500 KB. |
| 422 | missing_documents | Add documents or template_id. |
| 422 | missing_email | An email-delivery signer has no email. |
| 422 | duplicate_signer | Two signers have the same email. |
| 422 | unknown_signer | A field's signer isn't an index, role or email in signers. |
| 422 | unknown_document | A field's document index doesn't exist. |
| 422 | invalid_field | A field is on a page the document does not have. |
| 422 | field_off_page | A field runs off the page. The message gives the page size. |
| 422 | missing_fields | A signer has nothing to fill. |
| 422 | missing_variables | A template variable has no value. missing lists them. |
| 422 | unfilled_role | A template role has no signer. roles lists them. |
| 422 | invalid_template | Send blocks or a PDF, not both; fields go with a PDF. |
| 422 | invalid_pdf | The file isn't a readable PDF. |
| 422 | encrypted_pdf | The PDF is password-protected. |
| 422 | too_many_pages | PDFs can have at most 200 pages. |
| 422 | invalid_base64 | file_base64 isn't valid base64. |
| 422 | missing_file | Send file_base64 or file_url. |
| 422 | file_unreachable | file_url couldn't be downloaded. |
| 422 | invalid_url | URLs must be public https. |
| 422 | invalid_deadline | The deadline is in the past. |
| 422 | invalid_metadata | metadata has more than 20 keys. |
| 422 | invalid_logo | The logo must be a PNG. |
| 422 | missing_value | A required field is empty. field_id says which. |
| 422 | missing_signature | The signer has signature fields but sent no signature. |
| 422 | invalid_signature | The signature must be a PNG data URL. |
| 422 | idempotency_key_reused | This Idempotency-Key was used for a different request. |
| 422 | missing_envelope_id | An envelope embed token needs envelope_id. |
| 429 | test_limit_reached | This business sent 100 test envelopes today. |
| 429 | access_code_locked | Too many wrong access codes. Wait 15 minutes. |
| 500 | internal_error | Something unexpected. Retrying with the same Idempotency-Key is safe. |