Errors
Every error the public API returns, its status, and what a client should do.
Every failure is an RFC 9457 problem document served as application/problem+json:
{
"type": "https://www.foliaplanner.com/docs/api/errors#unprocessable",
"title": "The request was understood but cannot be applied.",
"status": 422,
"code": "unprocessable",
"detail": "Enter a valid email address",
"errors": { "answers.3f1c…": "Enter a valid email address" }
}Match on code. title and detail are for humans and may be reworded; type links to the matching section on this page. errors, when present, maps a field path to a message the visitor can act on — show it beside the field. On the submission endpoint the path is answers.{questionId}.
validation_failed
400. The path or body did not match the endpoint's schema: answers missing or not an object, pageUrl too long, a malformed token. errors names each field. This is a client bug; do not retry unchanged.
not_found
404. No live form has this token. The form is a draft, has been archived, or the token is wrong. Show the visitor that the form is not available; there is nothing to retry.
payload_too_large
413. The request body is over 256 KB. No form needs anywhere near that; a client sending it has attached something that does not belong in JSON. Do not retry unchanged.
unprocessable
422. Well-formed, but an answer was refused: a required question left blank, an email or date that does not parse, a select answer that is not one of the options, or text past its length cap (2,000 characters for single-line answers, 20,000 for long text). errors maps each answers.{questionId} to a message written for the visitor. Show it next to the question and let them resubmit.
rate_limited
429. Too many submissions to this form from this client in a short window. Nothing was stored. The response carries a Retry-After header in seconds; wait at least that long before resubmitting. A visitor who resubmits a few times — a double-click, a corrected typo — never sees this.
internal
500. Something failed on our side. The response deliberately carries no detail; the server has logged it. Safe to retry a GET; for a submission, retry once after a short delay, then tell the visitor to try again later.
Other codes
unauthorized (401), forbidden (403), and conflict (409) are reserved in the code enum and never returned by these endpoints.