Understand API error responses, status codes, error codes, and retry strategies.
Error Handling
The Sayify.pro API uses standard HTTP status codes and structured JSON error bodies to tell you exactly what went wrong.
Error Response Format
Most errors return a JSON object with error and code fields:
{
"error": "name is required",
"code": "NAME_REQUIRED"
}
Validation errors may include more descriptive messages:
{
"error": "Slug \"my-form\" is already in use",
"code": "SLUG_CONFLICT"
}
Some DRF-standard errors return a detail field instead:
{
"detail": "Authentication credentials were not provided."
}
For field-level validation, the response includes per-field messages:
{
"name": ["This field is required."],
"slug": ["A link with this slug already exists in your workspace."]
}
Status Codes
Success Codes
| Code | Meaning |
|---|---|
200 OK |
Request succeeded. |
201 Created |
Resource successfully created. |
200 OK |
Resource successfully deleted (returns confirmation message). |
Client Error Codes
| Code | Meaning | Common Cause |
|---|---|---|
400 Bad Request |
Invalid request body. | Missing required fields, invalid data types, slug conflict. |
401 Unauthorized |
Authentication failed. | Missing or invalid API key. |
403 Forbidden |
Insufficient permissions. | Key missing required scope, plan limit reached. |
404 Not Found |
Resource doesn't exist. | Invalid UUID, wrong endpoint, missing trailing slash. |
405 Method Not Allowed |
Wrong HTTP method. | Using GET on a POST-only endpoint. |
429 Too Many Requests |
Rate limit exceeded. | Slow down and retry with backoff. |
Server Error Codes
| Code | Meaning |
|---|---|
500 Internal Server Error |
Something went wrong on our end. Contact support if persistent. |
503 Service Unavailable |
Temporary maintenance or overload. Retry after a short wait. |
Error Codes
Named error codes help you programmatically handle specific failure scenarios:
| Error Code | HTTP Status | Description |
|---|---|---|
NAME_REQUIRED |
400 |
The name field is missing from the request body. |
SLUG_CONFLICT |
400 |
The provided slug already exists in this workspace. Omit it to auto-generate. |
CREATE_FAILED |
400 |
Unexpected error during resource creation — check request body. |
LINK_LIMIT_REACHED |
403 |
Workspace has hit its plan's link quota — upgrade to create more. |
INSUFFICIENT_SCOPE |
403 |
API key lacks the required scope (e.g. links:read, links:write). |
Retry Strategy
For 429 and 5xx errors, use exponential backoff:
Python
import time
import requests
def api_request(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
if response.status_code in (429, 500, 503):
wait_time = (2 ** attempt) # 1s, 2s, 4s
time.sleep(wait_time)
continue
# Client error — don't retry
response.raise_for_status()
raise Exception("Max retries exceeded")
JavaScript
async function apiRequest(url, headers, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, { headers });
if (response.ok) return response.json();
if ([429, 500, 503].includes(response.status)) {
const waitMs = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
await new Promise(r => setTimeout(r, waitMs));
continue;
}
throw new Error(`API Error: ${response.status} ${response.statusText}`);
}
throw new Error("Max retries exceeded");
}
[!TIP]
When rate-limited (429), the response includes aRetry-Afterheader indicating how many seconds to wait before retrying.
Tips
- Always check the
codefield — it's more reliable than parsing error messages. - Don't retry
400or401errors — these indicate a problem with your request, not a transient failure. - Log delivery IDs — for webhook errors, log
X-Sayify-Delivery-Idfor debugging. - Contact support — if you consistently get
500errors, create a support ticket.
What's Next?
- Authentication — API key creation and security.
- Endpoints — Full endpoint reference with payloads.
- API Overview — Base URL, request format, pagination.
Was this page helpful?
Report an issue
→