← All documentationContents ↓

Error Handling

Standard error envelope, error codes, HTTP status codes, and how to handle errors with the TypeScript SDK.

Error Response Format

All Simply360 API errors follow a consistent envelope. When a request fails, the response body contains an error object with a machine-readable code and a human-readable message, plus a meta object that includes a unique request identifier.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The field 'email' is required.",
    "details": { "field": "email" }
  },
  "meta": {
    "requestId": "req_abc123def456"
  }
}

Envelope Fields

FieldTypeDescription
error.code string Stable, machine-readable error code. Use this for programmatic handling.
error.message string Human-readable description. May change over time — do not match against this string in code.
error.details object Optional, error-specific structured details (e.g., the offending field name).
meta.requestId string Unique identifier for the request. Include this when contacting support.

Common Error Codes

Error CodeHTTP StatusDescription
VALIDATION_ERROR 400 The request body or query parameters failed validation. Inspect error.details and error.message for which fields are invalid.
AUTHENTICATION_REQUIRED 401 No valid credential was provided. Ensure your Authorization header includes a valid bearer token.
INVALID_API_KEY 401 The API key was not found, is inactive, or failed verification. Related codes: API_KEY_EXPIRED and INVALID_SESSION_TOKEN (expired or revoked session token).
PERMISSION_DENIED 403 The credential is valid but lacks access to this resource or operation. Related code: FEATURE_PERMISSION_DENIED (a required feature permission is missing).
NOT_FOUND 404 The requested resource does not exist or is not accessible to your team.
CONFLICT 409 The request conflicts with the current state of the resource (e.g., a duplicate of an existing item).
RATE_LIMIT_EXCEEDED 429 You've exceeded a request quota. Wait until the window resets (see the X-RateLimit-Reset header) before retrying.
INTERNAL_ERROR 500 An unexpected server error occurred. If it persists, contact support with the requestId.
TIMEOUT 408 Returned by the SDK (not the server) when the configured request timeout elapses (default 30 seconds).
UNKNOWN SDK fallback when a non-2xx response has no parseable error code (e.g., a gateway error page).

HTTP Status Codes

Simply360 follows standard HTTP semantics:

StatusMeaning
200Success.
201Created — a new resource was successfully created.
204No Content — success with no response body. Rare; most delete endpoints return 200 with a confirmation body.
400Bad Request — malformed input or failed validation.
401Unauthorized — missing or invalid credentials.
403Forbidden — authenticated but lacking permission.
404Not Found.
409Conflict — the request conflicts with existing state.
429Too Many Requests — you've hit a rate limit.
500Internal Server Error.

Handling Errors in the TypeScript SDK

The SDK throws ApiError for any non-2xx response. ApiError extends Error and exposes:

  • statusCode — HTTP status (e.g., 404).
  • code — Machine-readable error code (e.g., "NOT_FOUND").
  • message — Human-readable message.
  • details — Optional Record<string, unknown> with structured context.
import { Simply360, ApiError } from '@simply360/sdk';

const s360 = new Simply360({ apiKey: process.env.S360_API_KEY! });

async function getRecord(recordId: string) {
  try {
    const response = await s360.dataRecords.get(recordId);
    return response.data;
  } catch (error) {
    if (error instanceof ApiError) {
      switch (error.code) {
        case 'AUTHENTICATION_REQUIRED':
        case 'INVALID_API_KEY':
          console.error('Invalid credentials. Check your API key.');
          break;

        case 'NOT_FOUND':
          console.warn(`Record ${recordId} not found.`);
          return null;

        case 'RATE_LIMIT_EXCEEDED': {
          // Rate-limit headers are on the HTTP response, not on ApiError.
          // Apply your own backoff before retrying.
          await new Promise((resolve) => setTimeout(resolve, 5000));
          return getRecord(recordId);
        }

        case 'VALIDATION_ERROR':
          console.error('Validation failed:', error.message, error.details);
          break;

        default:
          console.error(`API error [${error.statusCode}/${error.code}]: ${error.message}`);
      }
    }
    throw error;
  }
}

The requestId Field

Every API response includes a requestId in the meta object, and the same value is sent in the X-Request-Id response header. When contacting Simply360 support about an API issue, always include the requestId from the failed response — it lets the team locate the exact request in server logs and diagnose quickly.

If you are making raw HTTP requests without the SDK, parse the response body (or read the X-Request-Id header) to extract the requestId. Store it alongside any error report or log entry your application produces.

const response = await fetch('https://api.simply360.app/v1/data-records/WXYZ-5678-IJKL', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await response.json();

if (!response.ok) {
  console.error(`Request failed: ${body.error.message} (requestId: ${body.meta.requestId})`);
}

Timeouts

The SDK has a default request timeout of 30 seconds. When the timeout fires, the SDK throws an ApiError with statusCode: 408 and code: "TIMEOUT". You can configure the timeout per client:

const s360 = new Simply360({
  apiKey: process.env.S360_API_KEY!,
  timeout: 60000, // 60 seconds
});