Trust Rails
Solutions
About
Log in
Back to Guides

Error Codes

Every error the TrustRails API can return — status codes, error codes, response formats, and patterns for handling them in production.

10 min read

Overview

The TrustRails API uses standard HTTP status codes to indicate request outcomes. Every error response includes a machine-readable code field and a human-readable message to help you diagnose and resolve issues quickly.

Error Response Format

All error responses follow a consistent JSON structure:

JSON
{
"error": "Error Type",
"message": "A human-readable description of what went wrong",
"code": "ERROR_CODE"
}

Validation errors include an additional details array with field-level information:

JSON
{
"error": "Validation Error",
"message": "Invalid request body",
"details": [
{
"code": "invalid_type",
"path": ["participant", "email"],
"message": "Expected string, received number"
}
]
}

Rate limit errors include additional fields to help you implement backoff logic:

JSON
{
"error": "Too Many Requests",
"code": "RATE_LIMIT_EXCEEDED",
"limit": 1000,
"remaining": 0,
"retryAfter": 42
}

HTTP Status Codes

The API uses these HTTP status codes across all endpoints:

CodeStatusWhen It Occurs
200
OKRequest succeeded (reads, updates, deletes)
201
CreatedResource successfully created (POST)
400
Bad RequestMalformed request or invalid parameters
401
UnauthorizedMissing, invalid, or revoked API key
403
ForbiddenIP not allowed, permission denied, or inactive custodian
404
Not FoundResource does not exist or is not accessible
409
ConflictState conflict, duplicate, or reversal already in progress
422
Unprocessable EntityRequest body fails schema validation
429
Too Many RequestsRate limit exceeded for your tier
500
Internal Server ErrorUnexpected server-side error
503
Service UnavailableMaintenance mode or dependent service unavailable

Authentication Errors

These errors occur during API key validation before your request reaches the endpoint.

401 Unauthorized

CodeCauseResolution
MISSING_API_KEYNo Authorization or X-API-Key headerAdd your API key to the request header
INVALID_FORMATAPI key doesn't match expected formatVerify key starts with tr_test_ or tr_live_
NOT_FOUNDAPI key not recognizedCheck for typos or generate a new key
INACTIVEAPI key has been deactivatedContact your account administrator
REVOKEDAPI key was revoked (e.g., after rotation)Use your current active key

403 Forbidden

CodeCauseResolution
IP_NOT_ALLOWEDRequest IP not in your allowlistAdd the server IP to your allowlist in the portal
CUSTODIAN_INACTIVEYour custodian account is inactiveContact TrustRails support
PERMISSION_DENIEDKey lacks required permission for this actionRequest elevated permissions or use a different key
JSON
// Example: Missing API key
// HTTP 401
{
"error": "Unauthorized",
"message": "API key is required. Include it in the Authorization header as 'Bearer <key>' or in the X-API-Key header.",
"code": "MISSING_API_KEY"
}

Rate Limit Errors

Rate limits are applied per API key based on your integration tier. Every response includes rate limit headers so you can track your usage proactively.

Rate Limits by Tier

TierLimitTypical Use
Tier 11,000 req/minFinancial institutions
Tier 2500 req/minHR platforms
Tier 3100 req/minBasic / trial integrations

Rate limit headers are included on every response, not just errors:

Bash
X-RateLimit-Limit: 1000 # Your tier's per-minute limit
X-RateLimit-Remaining: 997 # Requests remaining in current window
X-RateLimit-Reset: 1714300800 # Unix timestamp when the window resets
Retry-After: 42 # Seconds to wait (only on 429 responses)
JSON
// HTTP 429
{
"error": "Too Many Requests",
"code": "RATE_LIMIT_EXCEEDED",
"limit": 1000,
"remaining": 0,
"retryAfter": 42
}

Validation Errors

Request body and query parameter validation errors return a details array with field-level information. These errors use HTTP 400 or 422 depending on the endpoint.

JSON
// HTTP 422 - Invalid request body
{
"error": "Validation Error",
"message": "Invalid request body",
"details": [
{
"code": "invalid_type",
"path": ["participant", "email"],
"message": "Expected string, received number"
},
{
"code": "too_small",
"path": ["participant", "firstName"],
"message": "String must contain at least 1 character(s)"
}
]
}

Resource Errors

These errors occur when looking up specific resources like rollovers, partners, or plans.

404 Not Found

CodeContext
ROLLOVER_NOT_FOUNDRollover ID doesn't exist or belongs to another custodian
CUSTODIAN_NOT_FOUNDCustodian ID not registered in the system
PLAN_NOT_FOUNDNo plan found for the given EIN and plan number

409 Conflict

CodeContext
ALREADY_REVERSEDThis rollover has already been reversed
REVERSAL_IN_PROGRESSA reversal is already pending for this rollover

Rollover Errors

Errors specific to rollover creation, state transitions, and reversals.

Creation Errors (400/503)

CodeCause
CUSTODIAN_NOT_FOUNDSource or destination custodian not registered (returns 400 during creation, 404 on direct lookup)
VAULT_UNAVAILABLEEncryption service unavailable (retry later)
ROLLOVER_CREATE_FAILEDInternal error during rollover creation

Reversal Errors (400/403/409)

CodeCause
ROLLOVER_NOT_COMPLETEDRollover must be in completed state to reverse
IS_REVERSALCannot reverse a rollover that is itself a reversal
OUTSIDE_REVERSAL_WINDOWReversal window (60 days) has passed
NOT_INVOLVEDYour custodian is not the source or destination
IS_INITIATORCannot approve your own reversal request

Webhook Errors

Errors that can occur when configuring or testing webhooks.

StatusCauseResolution
400
URL must use HTTPSProvide an HTTPS endpoint URL
400
Invalid event type in subscriptionUse valid event types (e.g., rollover.started, settlement.funds_sent)
400
Test delivery failedVerify your endpoint is reachable and returns 2xx

Service Errors

Server-side errors that may require retrying your request.

500 / 503 Errors

CodeCauseAction
VAULT_UNAVAILABLEEncryption service temporarily downRetry with exponential backoff
MAINTENANCE_MODEScheduled maintenance in progressWait for Retry-After header value
SERVICE_UNAVAILABLEDependent service unreachableRetry with exponential backoff
JSON
// HTTP 503 - Maintenance
{
"error": "Service Unavailable",
"code": "MAINTENANCE_MODE",
"requestId": "req_a1b2c3d4",
"retryAfter": 3600
}

Handling Errors

Best practices for building resilient integrations that handle errors gracefully.

Use Exponential Backoff for Retries

For 429 and 5xx errors, implement exponential backoff with jitter to avoid thundering herd problems.

Node.js
async function apiRequest(url, options, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.ok) return response.json();
// Don't retry client errors (except 429)
if (response.status < 500 && response.status !== 429) {
const error = await response.json();
throw new Error(`${error.code}: ${error.message}`);
}
if (attempt < maxRetries) {
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter
? parseInt(retryAfter) * 1000
: Math.min(1000 * 2 ** attempt, 30000) + Math.random() * 1000;
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error('Max retries exceeded');
}

Monitor Rate Limit Headers Proactively

Check X-RateLimit-Remaining on every response. If it drops below 10% of your limit, slow down requests before hitting a 429.

Handle Validation Errors with the Details Array

Map the path field to your form inputs for inline error display. The code field in each detail uses standard validation codes (e.g., invalid_type, too_small, invalid_string).

Log the Error Code, Not Just the Message

Always log the code field for debugging. Error messages may be updated for clarity, but codes remain stable across API versions.

Ready to Get Started?

Explore more guides or request sandbox access to start building on TrustRails