API errors HTTP status codes, error codes, and recommended client behaviour.
All SimplyFill API errors are JSON. Every error body shares the same minimum shape:
{
"error" : "machine_readable_code" ,
"message" : "Human-readable explanation."
}
Some endpoints add per-error fields (a limit for quota errors, retry_after for rate-limit errors, etc.). Those are documented on the endpoint that emits them; what follows is the cross-cutting summary.
Status Meaning Common causes 400 Bad RequestValidation failed Missing required field, wrong type, unknown alias in data 401 UnauthorizedAuthentication failed Missing or invalid Bearer token 402 Payment RequiredQuota exceeded (FREE tier) Monthly PDF or AI quota at 100% on FREE 403 ForbiddenPermission denied or scope insufficient Not the resource owner; key lacks required scope; tier feature limit 404 Not FoundResource does not exist Wrong ID, or you don't have access 409 ConflictState conflict Promoting an already-published version; invalid plan transition 410 GoneResource expired Download URL older than 24 hours 422 Unprocessable EntitySchema understood but semantically invalid Mapping references a deleted template version 429 Too Many RequestsRate limit exceeded Hourly cap reached; honor Retry-After 500 Internal Server ErrorServer-side fault Rare; auto-reported to on-call. Retry with exponential backoff 503 Service UnavailableMaintenance / dependency outage Status page will reflect; retry once Retry-After elapses
Stable identifiers in the error field. Match on these in client code; the message is for humans and may change wording without notice.
Code Status When missing_authorization401 No Authorization header invalid_api_key401 Key revoked, malformed, or unknown scope_required403 Key lacks the scope the endpoint requires
Code Status When template_not_found404 Template ID unknown or inaccessible mapping_not_found404 Mapping ID unknown or inaccessible task_not_found404 Async task ID unknown file_not_found404 Download file ID unknown file_expired410 Download URL older than 24 hours envelope_not_found404 Envelope ID unknown
Code Status When validation_error400 Body failed Pydantic validation. Fields listed under details. invalid_file_type400 Upload not a .pdf file_too_large400 Upload above 25 MB invalid_csv400 Bulk envelope CSV missing header or has mismatched columns
Code Status When quota_exceeded402 Monthly PDF quota at 100% on FREE ai_quota_exceeded402 Monthly AI quota at 100% on FREE or PRO feature_limit_reached403 Per-tier template or API-key cap rate_limit_exceeded429 Hourly cap exceeded; Retry-After set
Code Status When template_not_deployed403 Resolved version not published to the request's environment invalid_plan_transition409 Cannot downgrade mid-period for current plan
HTTP / 1.1 400 Bad Request
Content-Type : application/json
{
"error" : "validation_error" ,
"message" : "Request body failed validation." ,
"details" : [
{ "field" : "data.amount" , "issue" : "field required" }
]
}
HTTP / 1.1 429 Too Many Requests
Retry-After : 247
Content-Type : application/json
{
"error" : "rate_limit_exceeded" ,
"message" : "Hourly rate limit reached. Try again in 247 seconds." ,
"retry_after" : 247
}
HTTP / 1.1 402 Payment Required
Content-Type : application/json
{
"error" : "quota_exceeded" ,
"message" : "Monthly PDF quota exceeded for FREE tier." ,
"tier" : "FREE" ,
"limit" : 100 ,
"used" : 100 ,
"upgrade_url" : "https://simplyfill.app/billing" ,
"resets_at" : "2026-06-01T00:00:00Z"
}
A reasonable retry policy for production code:
Status Action 4xx (except 429)Do not retry. Fix the request. 429Wait Retry-After seconds, then retry. 5xxExponential backoff with jitter, capped at ~5 attempts. 402 / 403 (tier)Surface upgrade prompt to the user. Do not retry until plan changes.
Implement this retry policy in whichever HTTP client you use against the API.