Skip to main content

Errors

All One Stack APIs return errors in a consistent JSON format with standard HTTP status codes.

Error Response Format

{
"error": "Human-readable error message",
"code": "MACHINE_READABLE_CODE",
"details": {}
}
FieldTypeDescription
errorstringA human-readable description of what went wrong.
codestringA machine-readable error code for programmatic handling.
detailsobject or nullOptional additional context (e.g., validation errors, conflicting resource IDs).

HTTP Status Codes

400 Bad Request

The request was malformed or failed validation.

{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"fields": {
"title": "Title is required",
"priority": "Must be one of: low, medium, high, critical"
}
}
}

Troubleshooting:

  • Check that all required fields are included in the request body.
  • Verify field values match expected types and allowed values.
  • Ensure the Content-Type header is set to application/json.

401 Unauthorized

Authentication credentials are missing or invalid.

{
"error": "Authentication required",
"code": "UNAUTHORIZED"
}

Troubleshooting:

  • Verify your API key is correct and has not been revoked.
  • Check that the X-Integration-Key header is present and spelled correctly.
  • For session-based auth, ensure the user is logged in and the session has not expired.
  • For portal tokens, ensure the JWT has not expired.

403 Forbidden

The authenticated user or key does not have permission for the requested action.

{
"error": "Access denied to PSA product",
"code": "FORBIDDEN",
"details": {
"requiredProduct": "psa",
"requiredPermission": "tickets.write"
}
}

Troubleshooting:

  • Verify the API key has been granted access to the target product.
  • Check that the key has the required permission level (Read Only vs. Read/Write).
  • For user sessions, verify the user's role includes access to the product and the specific action.
  • Portal tokens can only access portal-designated endpoints.

404 Not Found

The requested resource does not exist, or the URL path is incorrect.

{
"error": "Ticket not found",
"code": "NOT_FOUND",
"details": {
"resourceType": "ticket",
"resourceId": "tkt_nonexistent"
}
}

Troubleshooting:

  • Verify the resource ID is correct.
  • Ensure the resource has not been deleted.
  • Check that the URL path and product base URL are correct.
  • The resource may exist but belong to a different tenant.

409 Conflict

The request conflicts with the current state of a resource.

{
"error": "Ticket has been modified by another user",
"code": "CONFLICT",
"details": {
"currentVersion": "v3",
"submittedVersion": "v1"
}
}

Troubleshooting:

  • Fetch the latest version of the resource and retry with the updated data.
  • For concurrent edits, implement optimistic locking using the _etag field if provided.

429 Too Many Requests

The tenant has exceeded the rate limit.

{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"details": {
"limit": 100,
"window": "1m",
"retryAfter": 23
}
}

Troubleshooting:

  • Wait for the number of seconds specified in the Retry-After header.
  • Implement exponential backoff in your client.
  • Reduce request frequency by using batch operations or webhooks.
  • See Rate Limits for detailed best practices.

500 Internal Server Error

An unexpected error occurred on the server.

{
"error": "An unexpected error occurred",
"code": "INTERNAL_ERROR"
}

Troubleshooting:

  • Retry the request after a short delay. Transient errors often resolve on their own.
  • If the error persists, contact support at [email protected] with the request details and the X-Request-Id response header value.

Error Codes Reference

CodeStatusDescription
VALIDATION_ERROR400Request body or query parameters failed validation
INVALID_JSON400Request body is not valid JSON
UNAUTHORIZED401Missing or invalid authentication
TOKEN_EXPIRED401JWT or session has expired
FORBIDDEN403Insufficient permissions
PRODUCT_ACCESS_DENIED403API key does not have access to this product
NOT_FOUND404Resource does not exist
CONFLICT409Resource version conflict
DUPLICATE_RESOURCE409A resource with the same unique identifier already exists
RATE_LIMIT_EXCEEDED429Too many requests
INTERNAL_ERROR500Unexpected server error

Handling Errors in Code

async function apiRequest(url, options) {
const response = await fetch(url, {
...options,
headers: {
'X-Integration-Key': API_KEY,
'Content-Type': 'application/json',
...options?.headers,
},
});

if (!response.ok) {
const error = await response.json();

switch (error.code) {
case 'RATE_LIMIT_EXCEEDED':
const retryAfter = parseInt(response.headers.get('Retry-After') || '5', 10);
await new Promise(r => setTimeout(r, retryAfter * 1000));
return apiRequest(url, options); // retry once
case 'VALIDATION_ERROR':
console.error('Validation errors:', error.details.fields);
throw new Error(`Validation failed: ${error.error}`);
case 'UNAUTHORIZED':
case 'TOKEN_EXPIRED':
throw new Error('Authentication failed. Check your API key or session.');
default:
throw new Error(`API error (${error.code}): ${error.error}`);
}
}

return response.json();
}