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

StatusMeaningCommon causes
400Bad RequestInvalid request payload or query parameters
401UnauthorizedMissing token, invalid token, expired token, or malformed API token format
403ForbiddenValid token but wrong scope or wrong team/resource access
404Not FoundResource does not exist or belongs to another team
429Too Many RequestsRate 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_id must be a valid UUID
  • line_items must be a non-empty array
  • Each line item must include product_id, quantity, is_add_on, and linked_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"))

On this page