Skip to content
Last updated

Error Response Structure

PERS API uses structured error responses for consistent error handling across all endpoints. All errors follow the same format with security-filtered messages and correlation IDs for support.

Why Structured Errors?

  • Consistency: All errors follow a uniform structure and categorization
  • Security: Sensitive system details are filtered out; only safe messages are returned
  • Traceability: Every error includes a correlation ID for support and debugging
  • Programmatic Handling: Structured format enables reliable error processing

API Error Format

All PERS API errors return structured JSON responses following RFC 7807 (Problem Details for HTTP APIs):

{
  "status": 404,
  "title": "Resource Not Found",
  "detail": "User with ID 12345 could not be found",
  "message": "The requested user could not be found",
  "code": "USER_NOT_FOUND",
  "category": "DOMAIN_RULE",
  "timestamp": "2026-01-15T10:30:00.000Z",
  "correlationId": "pers-abc123-def456",
  "retryable": false,
  "domain": "user"
}

Error Response Fields

FieldTypeDescription
statusnumberHTTP status code
titlestringHuman-readable error summary
detailstringSpecific error explanation
messagestringError message (usually same as detail)
codestringError code for programmatic handling
categorystringError classification (VALIDATION, SECURITY, etc.)
timestampstringISO timestamp when error occurred
correlationIdstringRequest correlation ID for distributed tracing and support
retryablebooleanWhether operation can be retried
domainstringDomain that generated the error (user, campaign, transaction, etc.)
detailsobjectAdditional structured error context (optional)
targetstringTarget property/parameter for validation errors (optional)

TypeScript Support

For TypeScript applications, import error types from the shared library:

import type { StructuredError, ErrorCategory } from '@explorins/pers-shared';

Error Categories & HTTP Status Mapping

CategoryHTTP StatusDescriptionRetryable
VALIDATION400Invalid request data or formatNo
SECURITY401/403Authentication/authorization failuresNo
DOMAIN_RULE404/409/422Business logic and resource errorsNo/Maybe
TECHNICAL500Application/configuration issuesMaybe
RATE_LIMIT429API rate limit exceededYes
TIMEOUT504Request timeoutYes
INFRASTRUCTURE503External service failuresYes
UNKNOWN500Unclassified errorsMaybe

Common Error Codes by Domain

User Domain

CodeDescription
USER_NOT_FOUNDUser with specified ID does not exist
USER_ALREADY_EXISTSUser with this identifier already exists
USER_NOT_AUTHORIZEDUser lacks required permissions

Campaign Domain

CodeDescription
CAMPAIGN_NOT_FOUNDCampaign does not exist
CAMPAIGN_NOT_ACTIVECampaign is not currently active
CAMPAIGN_ALREADY_CLAIMEDUser has already claimed this campaign
CAMPAIGN_CLAIM_LIMIT_REACHEDUser has reached claim limit
CAMPAIGN_COOLDOWN_ACTIVEClaim cooldown period is active
CAMPAIGN_CONDITION_NOT_METCampaign conditions not satisfied

Transaction Domain

CodeDescription
TRANSACTION_NOT_FOUNDTransaction does not exist
TRANSACTION_ALREADY_COMPLETEDTransaction was already processed
TRANSACTION_EXPIREDTransaction has expired
INSUFFICIENT_BALANCEInsufficient token balance

Authentication Domain

CodeDescription
AUTHENTICATION_REQUIREDValid credentials required
AUTHORIZATION_FAILEDInsufficient permissions
INVALID_TOKENJWT token is invalid
TOKEN_EXPIREDJWT token has expired

Webhook Domain

CodeDescription
WEBHOOK_NOT_FOUNDWebhook configuration not found
WEBHOOK_INACTIVEWebhook is disabled
WEBHOOK_SOURCE_NOT_ALLOWEDCaller source not in allowed list
WEBHOOK_SIGNATURE_INVALIDSignature verification failed

Generic Codes

CodeDescription
RESOURCE_NOT_FOUNDGeneric resource not found
RESOURCE_CONFLICTConcurrent modification detected
VALIDATION_ERRORInput validation failed
BUSINESS_RULE_VIOLATIONBusiness rule constraint violated
INTERNAL_ERRORUnexpected server error

Error Handling Examples

Example Error Response

Authentication Error (401)

{
  "status": 401,
  "title": "Authentication Required",
  "detail": "Valid authentication credentials are required",
  "message": "Please log in to access this resource",
  "code": "AUTHENTICATION_REQUIRED",
  "category": "SECURITY",
  "timestamp": "2026-01-15T10:30:00.000Z",
  "correlationId": "pers-def456-ghi789",
  "retryable": false
}

Validation Error (400)

{
  "status": 400,
  "title": "Validation Error",
  "detail": "The email field is required",
  "message": "The email field is required",
  "code": "VALIDATION_ERROR",
  "category": "VALIDATION",
  "timestamp": "2026-01-15T10:30:00.000Z",
  "correlationId": "pers-jkl012-mno345",
  "details": {
    "field": "email",
    "rejectedValue": null
  },
  "retryable": false
}

Client-Side Error Handling

// Example: Handling API errors in JavaScript/TypeScript
async function callAPI() {
  try {
    const response = await fetch('/api/users', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer your-token',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ name: 'John' })
    });
    
    if (!response.ok) {
      const error = await response.json();
      
      // Handle different error categories
      if (error.category === 'SECURITY') {
        // Redirect to login
        window.location.href = '/login';
      } else if (error.category === 'VALIDATION') {
        // Show validation errors to user
        showValidationError(error.details);
      } else {
        // Show generic error message
        showErrorMessage(error.message);
      }
      return;
    }
    
    const data = await response.json();
    // Handle success response
  } catch (networkError) {
    // Handle network errors
    showErrorMessage('Network error. Please try again.');
  }
}

Advanced Error Features

Correlation ID Tracking

Every request and error response includes a unique correlation ID for distributed tracing:

  • Automatically generated for each request
  • Included in response headers: X-Correlation-ID
  • Persisted across service boundaries for end-to-end tracing
  • Essential for debugging issues across distributed systems

Security Filtering

The API implements intelligent message safety filtering:

  • System internals (stack traces, database errors) are never exposed
  • Sensitive data (secrets, keys, credentials) is automatically filtered
  • Business-friendly error messages are preserved
  • Technical errors are sanitized for user consumption

Category-Specific Error Interfaces

For enhanced type safety in TypeScript applications:

import type { 
  ValidationStructuredError,
  DomainRuleStructuredError,
  SecurityStructuredError,
  RateLimitStructuredError
} from '@explorins/pers-shared';

// Validation errors include field violations
interface ValidationStructuredError {
  category: 'VALIDATION';
  details: {
    violations: Array<{
      field: string;
      code: string;
      message: string;
      rejectedValue?: any;
    }>;
  };
  target: string; // Required field
  retryable: false;
}

// Rate limit errors include quota information
interface RateLimitStructuredError {
  category: 'RATE_LIMIT';
  details: {
    limit: number;
    remaining: number;
    resetTime: string; // ISO 8601
    window: string; // e.g., "1h", "1d"
  };
  retryable: true;
}

Response Headers

Error responses include correlation tracking headers:

  • X-Correlation-ID: Unique request identifier (set for all responses)
  • X-Response-Time: ISO timestamp of response generation
  • Access-Control-Expose-Headers: Exposes correlation ID for CORS requests

Note: Additional error metadata (category, retryable, etc.) is available in the response body, not as separate headers.

Security Features

  • System error details are never exposed to API consumers
  • Sensitive data automatically filtered using pattern matching
  • Every error includes a correlation ID for traceability
  • All errors are logged with full context for debugging
  • Consistent error categorization across all domains
  • Message safety filtering prevents information leakage

For further details, see the Authentication Guide and Developer Resources.