Errors
What an error response looks like, what the common errors mean, and how to report one.
This page explains the errors the Tepez API returns: the shape of an error response, the two kinds of validation error, the common status codes and messages, and the request id that lets us find your request. Use it to handle errors in your code and to fix a failing request.
The error shape
Every error answers with a 4xx or 5xx status and a JSON body with three properties:
{
"statusCode": 404,
"error": "Not Found",
"message": "Could not find an entry with ID <entryId>."
}statusCoderepeats the HTTP status.erroris the status's name.messagesays what went wrong, in words a person can read. Some errors add more properties, described below.
Base your code on the HTTP status and on the added properties, not on the text of message. The
text depends on the language you ask for (see Message language) and may be
reworded.
A few errors don't come from the API itself but from the network in front of it, and their body
is HTML, not JSON: a request over plain HTTP, and a gateway error such as 504. Don't assume every
error body parses as JSON.
This reads an entry and handles an error, keeping the request id for a support request (see The request id):
curl -i https://api.tepez.co.il/v1.0/entry/<entryId> \
-H "x-api-key: $TEPEZ_API_KEY"The response to an entry id that doesn't exist, with the headers trimmed:
HTTP/1.1 404 Not Found
x-tepez-request-id: 1790800000000:<host>:1:k2x9q7ab:10452{
"statusCode": 404,
"error": "Not Found",
"message": "Could not find an entry with ID <entryId>."
}Status codes
| Status | Meaning | What to do |
|---|---|---|
400 | The request is invalid: a parameter or a body property is missing or wrong, or the entry's data breaks the form's rules. | Fix the request. See Validation errors. |
401 | No valid credential. | Send a valid key in the x-api-key header. See Troubleshooting. |
403 | The action isn't allowed: the object belongs to another account, or its state doesn't allow the action. Also returned, with an HTML body, for a request over plain HTTP. | Read message. See Troubleshooting. |
404 | The id or the path doesn't exist. | Check the id and the path, including /v1.0. |
413 | The request body is too large. | Send less data in one request. See Limits. |
500 | The server failed to handle the request, for example because a file value points at a file that isn't in storage. | Check the request's file values. Retry later. If it keeps failing, contact support with the request id. |
502, 503, 504 | The API was unavailable or took too long to answer. The body may be HTML. | Retry reads after a pause. Before retrying a write, check whether it happened. See Timeouts and gateway errors. |
Validation errors
A 400 usually comes in one of two shapes, depending on what failed: the request itself, or the
entry data it carries. A few 400 errors have only the three basic properties, such as
Query must contain a form from an export.
An invalid request: validation
When a query parameter, a path parameter or a body property is missing or has the wrong type or
value, the error adds a validation object. This request asks for more entries per page than the
API allows:
curl -G https://api.tepez.co.il/v1.0/entry \
-H "x-api-key: $TEPEZ_API_KEY" \
--data-urlencode 'query={"form":"<formId>"}' \
--data-urlencode 'limit=5000'{
"statusCode": 400,
"error": "Bad Request",
"message": "\"limit\" must be less than or equal to 2000",
"validation": { "source": "query", "keys": ["limit"] }
}validation.sourcesays where the problem is:queryfor the query string,payloadfor the request body,paramsfor the path.validation.keyslists the parameters or properties that failed, as dotted paths.messagedescribes the first problem found. These messages are always in English.
The same shape comes back for a missing body property, such as a submit with no form:
{
"statusCode": 400,
"error": "Bad Request",
"message": "\"form\" is required",
"validation": { "source": "payload", "keys": ["form"] }
}and for an id that isn't 24 hexadecimal characters:
{
"statusCode": 400,
"error": "Bad Request",
"message": "\"entryId\" with value \"123\" fails to match the required pattern: /^[0-9a-fA-F]{24}$/",
"validation": { "source": "params", "keys": ["entryId"] }
}The API reference lists each endpoint's parameters and body properties.
Invalid entry data: entry_failed_validation
When the request is valid but the entry's data breaks the form's rules, the error has
"id": "entry_failed_validation" and a messages array with one item per problem. Saves, submits,
edits and templates can all return it. This submit leaves out a required field and sends an
invalid email address:
curl -X POST https://api.tepez.co.il/v1.0/entry/submit \
-H "x-api-key: $TEPEZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{"form": "<formId>", "data": {"email": "not-an-email"}}'{
"statusCode": 400,
"error": "Bad Request",
"message": "The entry failed validation on the server. Sorry, this is probably a BUG on our side. If the issue persists please contact us at support@tepez.co.il",
"id": "entry_failed_validation",
"messages": [
{ "modelPath": "model['fullName']", "message": "You can't leave this empty.", "type": "error", "value": null },
{ "modelPath": "model['email']", "message": "Must be a valid email address.", "type": "error", "value": "not-an-email" }
]
}Each item of messages has:
modelPath: the field, as a path into the entry's data.message: what is wrong, in the form's language, as a person filling the form would see it, whatever language the request asks for.type:error.value: the value you sent, ornullwhen the field is empty.
Nothing is stored when this error comes back. Despite the wording of the top-level message, it
almost always means the data broke a rule of the form, not a fault on our side. Fix the fields
named in messages and send the request again. Submit entries from your server
shows how to handle it, and Form data schema shows the value each field takes.
Check the HTTP status, not the presence of id: a successful save or submit has no top-level
id, and the id of this error is its code.
Message language
The locale query parameter sets the language of message. It works on every endpoint:
locale | Language |
|---|---|
en | English. The default. |
he | Hebrew. |
en_GB, en_IL | English. |
This asks for the same missing entry in Hebrew:
curl "https://api.tepez.co.il/v1.0/entry/<entryId>?locale=he" \
-H "x-api-key: $TEPEZ_API_KEY"{
"statusCode": 404,
"error": "Not Found",
"message": "רשומה עם מזהה <entryId> לא נמצא."
}fallbackLocaleslists more locales to try, in order, for a message that has no translation inlocale. Send it once per locale (fallbackLocales=he) or repeated. When no listed locale has the message, it comes back in English.localechanges onlymessage. Theerrorname stays in English, and so do the messages of401errors and of invalid requests.- In an
entry_failed_validationerror, the top-levelmessagefollowslocale, but the items ofmessagesare always in the form's language. - Any other value fails with
400"locale" must be one of [en, en_GB, he, en_IL].
The request id
Every response from the API, successful or not, carries an x-tepez-request-id header:
x-tepez-request-id: 1790800000000:<host>:1:k2x9q7ab:10452It identifies the request in our logs. Log it with every failed request, and quote it when you contact support, together with the time of the request. With it we can find exactly what the API received and why it answered as it did.
Successful responses with no content
A successful request always answers 200, never 204, even when there is nothing to return.
Don't expect every 200 to have a JSON body:
DELETE /entry/{entryId}answers{"message": "The entry has been deleted successfully."}.- The other
DELETEendpoints, such asDELETE /optionsSet/{setId}andDELETE /api-keys/{apiKey}, answer with an empty body. - Deleting many at once, such as
POST /entry/delete, answers{}.
Timeouts and gateway errors
A 502, 503 or 504, or a request that times out on your side, means the answer didn't reach
you. It doesn't mean the request failed:
- Reads (
GET) are safe to retry. Wait a few seconds, and wait longer after each retry. - Writes may have happened. A submit that timed out may still have stored the entry. Check before you retry, as Submit entries from your server describes, or a retry can store it twice.
Troubleshooting
| Response | Cause and fix |
|---|---|
401 Missing authentication | No credential reached the API. Send the key in the x-api-key header, not as a query string parameter. |
401 Invalid API key | The key is mistyped, cut short, or was revoked. See Authentication. |
401 Invalid token or Expired token | A login token in Authorization is wrong, or older than 3 days. Sign in again, or use an API key. |
401 Wrong username/ password | The email or password sent to POST /auth/login is wrong, or the user signs in with Google only. |
403 You have insufficient permissions to perform the action. | The object belongs to an account other than the key's. Check the id, and that the key is from the right account. |
403 You cannot save this form entry because it was already submitted. | Saves work only on drafts. To change a submitted entry, edit it. |
403 You cannot submit this form entry because it was already submitted. | The entry was submitted earlier. Nothing more to do, or edit it. |
403 You cannot delete this form entry because it was already deleted. | The entry was deleted earlier. Nothing more to do. |
403 This form entry was already deleted and cannot be edited. | The entry was deleted. Deleted entries can't change. |
403 Can't change the status of the entry to this status. | The edit asked for a status change that isn't allowed, such as a template to submitted. See Entries. |
403 with a message the form's owner wrote | GET /form/{formId}/start or a template's clone link, on a form that is closed to new entries (access.isDisabled). Ask the form's owner to reopen it. |
403 with an HTML body | The request went over plain HTTP. Use https://. |
404 Could not find an entry with ID … | The id is wrong, or is the id of another kind of object, such as a form id. |
404 Could not find a form with ID … | The form id is wrong. Copy it from the form's link or from GET /form. |
404 Not Found | The path is wrong. Check the spelling, and that it starts with /v1.0. |
413 Payload content length greater than maximum allowed: … | The body is larger than the endpoint allows. The number is the limit in bytes. See Limits. Files never go in the body: upload them to storage. |
Every response carries an x-tepez-request-id header. Quote it when you contact us.
Question about this page? Email support@tepez.co.il