Errors
The error envelope, every error code of the Check API, and what your app should do for each one.
Branch on the HTTP status and on code. Do not parse message. The Check API writes message in English, and the text of a message can change.
Error envelope
Every error response of the Check API has the same JSON shape. A response from the network in front of the Check API can have another body. See Answers outside the envelope.
{
"data": null,
"code": "validation_failed",
"message": "Request is invalid.",
"errorId": "FMS400",
"traceId": "req_01M6JYA33G9NXKXXSG1B7Q1J4J",
"errors": [
{
"code": "text_too_long",
"field": "text",
"inputTokens": 16001,
"maxInputTokens": 16000,
"message": "Text is 16,001 input tokens. The limit is 16,000 input tokens."
}
]
}| Field | Type | Description |
|---|---|---|
data | null | Always null. |
code | string | The error code, such as rate_limited. |
message | string | A sentence for people to read. |
errorId | string | A fixed ID for the error code, such as FMS429. Each code has one errorId. |
traceId | string | The ID of the request. It is equal to the X-Request-Id header. |
errors | array | Present only when code is validation_failed. It has one item, which names the problem in the body. |
errors[].field | string | The part of the request with the problem, text or body. |
errors[].code | string | The field error code. See Field errors. |
errors[].message | string | A sentence for people to read. |
errors[].maxInputTokens | integer | Present only on text_too_long. The limit of input tokens for text. |
errors[].inputTokens | integer | Present only on text_too_long, when the Check API counted the tokens of text. |
Treat traceId and X-Request-Id as opaque strings. Most IDs start with req_, but a 400 or a 503 from the network in front of the Check API carries an ID in another form.
Error codes
Status and code | errorId | When | What your app should do |
|---|---|---|---|
400 validation_failed | FMS400 | The body breaks a rule. errors says which one. | Fix the request. Do not send the same body again. |
401 unauthorized | FMS401 | The key is missing, malformed, unknown, or deleted, or it belongs to another region. | Use a key that exists, with the API URL of its region. Do not retry. |
404 not_found | FMS404 | The path or the method does not exist in this API version. | Send POST to https://api.jp.flowmask.ai/api/v1/check. |
404 api_version_not_supported | FMC01 | The API version in the path does not exist. | Use a version that exists. Today that is v1. See Versioning. |
429 rate_limited | FMS429 | The workspace sent more requests in the current minute than its limit allows. | Wait the number of seconds in Retry-After, then retry. |
429 monthly_quota_exceeded | FMQ01 | The workspace used all of its input tokens for the month. | Stop sending requests until X-Quota-Reset. To raise the quota, email the address in message. |
500 internal_error | FMS500 | The Check API failed while it handled the request. | Retry with backoff. See Retry 500 and 503. |
503 service_unavailable | FMS503 | A part of the Check API failed or did not answer in time. The response has no result for the text. | Retry with backoff. See Retry 500 and 503. |
The Check API handles a request in this order: the path, the key, the body, and the limits. Then it checks the text. A request with a bad key and a bad body gets 401. A 400 or a 401 uses none of the rate limit and none of the monthly quota.
Field errors
A 400 validation_failed response has one item in errors.
errors[].code | errors[].field | When |
|---|---|---|
invalid_json | body | The body is not a JSON object. This includes a body that is not UTF-8, an array, and broken JSON. |
text_empty | text | text is missing, null, an empty string, or only white space. |
text_must_be_string | text | text is a number, a boolean, an object, or an array. |
text_too_long | text | text has more than 16,000 input tokens, or the body has more than 4 MiB. |
When the body has more than 4 MiB, the Check API stops reading it. The text_too_long item then has maxInputTokens but no inputTokens.
{
"data": null,
"code": "validation_failed",
"message": "Request is invalid.",
"errorId": "FMS400",
"traceId": "req_01M6JYA248KMF0WBCMB786A8XD",
"errors": [
{
"code": "text_empty",
"field": "text",
"message": "Text is empty."
}
]
}Answers outside the envelope
Some responses that do not come from the Check API have a body that is not the error envelope.
- The network in front of the Check API can answer
403with a plain body that is not JSON. It does so, for example, when a client sends far too many requests or a request looks malicious. - The load balancer can answer
502,503, or504with an HTML body when the Check API is not available.
These responses have no code, errorId, or traceId, and they can lack the headers in Response headers. Handle them in your app.
- Read the body as JSON only when the
Content-Typeof the response isapplication/json. - Do not retry a
403that is not JSON right away. Send fewer requests and check what you send. If the403keeps coming, contact support with the time of the requests. - Retry a
502,503, or504with an HTML body with backoff, as in Retry 500 and 503.
Retry 500 and 503
A 500 or a 503 has no result for the text. Your app decides whether to block the text or to send it on without a check.
To retry, wait longer before each retry.
- Wait 1, 2, 4, 8, and then 16 seconds before the retries.
- Add a random part of up to 1 second to each wait, so that your servers do not retry at the same moment.
- Stop after 5 retries.
The samples also retry a 502 and a 504, which come from the load balancer. See Answers outside the envelope.
import os
import random
import time
import requests
MAX_RETRIES = 5
def check(text):
for attempt in range(MAX_RETRIES + 1):
response = requests.post(
"https://api.jp.flowmask.ai/api/v1/check",
headers={"Authorization": f"Bearer {os.environ['FLOWMASK_API_KEY']}"},
json={"text": text},
timeout=30,
)
if response.status_code not in (500, 502, 503, 504) or attempt == MAX_RETRIES:
return response
time.sleep(2**attempt + random.random())Keep these facts in mind when you retry.
- A
503can come after the Check API counted the request against the rate limit. Retries then use more requests of the minute. - Only a
200uses input tokens. Every200counts the tokens of its text, even when the same text came in an earlier request. - Do not retry a
429with this loop. Rate limits and quota explains how to handle each429.