Error Handling
How to handle errors from the Presscart API, including error format, status codes, and best practices.
The Presscart API returns errors as JSON with a consistent format. This guide covers the error structure, common status codes, and best practices for handling errors in your integration.
Error format
All errors are returned as JSON objects with name and message fields:
{
"name": "ForbiddenError",
"message": "Insufficient permissions"
}Validation failures may also include an issues array with field-level details from Zod:
{
"name": "ValidationError",
"message": "Invalid request payload",
"issues": [
{
"path": ["profile_id"],
"message": "Required"
}
]
}Status codes
| Status | Meaning | Common causes |
|---|---|---|
400 | Bad Request | Invalid request payload or query parameters |
401 | Unauthorized | Missing token, invalid token, expired token, or malformed API token format |
403 | Forbidden | Valid token but wrong scope or wrong team/resource access |
404 | Not Found | Resource does not exist or belongs to another team |
429 | Too Many Requests | Rate limited -- slow down and retry with backoff |
Best practices
Always check the status code
Do not assume every response is successful. Check the HTTP status code before parsing the response body.
const response = await fetch("https://api.presscart.com/orders", {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
const error = await response.json();
console.error(`API error ${response.status}: ${error.message}`);
// Handle specific error types
if (response.status === 401) {
// Token is invalid or expired -- re-authenticate
} else if (response.status === 403) {
// Token lacks required scope
} else if (response.status === 429) {
// Rate limited -- implement exponential backoff
}
return;
}
const data = await response.json();Handle rate limiting with exponential backoff
When you receive a 429 status, wait before retrying. Use exponential backoff to avoid further rate limiting:
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
return response;
}
throw new Error("Max retries exceeded");
}Validate before sending
Validate your request payloads before sending them to avoid 400 errors. For example, ensure all required fields are present in checkout requests:
profile_idmust be a valid UUIDline_itemsmust be a non-empty array- Each line item must include
product_id,quantity,is_add_on, andlinked_order_line_item_id
Handle scope errors
If you receive a 403 error, verify that your token has the required scope for the endpoint you are calling. See the Authentication page for the full scope map.
Log errors for debugging
Log the full error response (including name, message, and issues if present) to help diagnose problems:
import requests
import logging
response = requests.get(
"https://api.presscart.com/campaigns",
headers={"Authorization": f"Bearer {token}"},
)
if not response.ok:
error = response.json()
logging.error(
"API error %d: %s - %s",
response.status_code,
error.get("name"),
error.get("message"),
)
if "issues" in error:
for issue in error["issues"]:
logging.error(" Field %s: %s", issue.get("path"), issue.get("message"))