Docs Error Codes

Error Codes

Complete reference of all Holdify API error codes.

All Holdify API errors follow a consistent format. Errors include a machine-readable code, human-readable message, and a link to documentation.

Error response format
json
{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Too many requests, please retry after 60 seconds",
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "docs_url": "https://holdify.io/docs/errors#rate-limiting"
}

Quick reference

CodeHTTPDescription
INVALID_API_KEY401Invalid API Key
API_KEY_EXPIRED401API Key Expired
RATE_LIMIT_EXCEEDED429Rate Limit Exceeded
BUDGET_EXCEEDED429Budget Exceeded
IDEMPOTENCY_KEY_CONFLICT409Idempotency Key Conflict
IDEMPOTENCY_KEY_REQUIRED400Idempotency Key Required
INVALID_REQUEST_BODY400Invalid Request Body
RESOURCE_NOT_FOUND404Resource Not Found
ACCESS_DISABLED403Access Disabled
WEBHOOK_SIGNATURE_INVALID401Invalid Webhook Signature
INTERNAL_SERVER_ERROR500Internal Server Error
SERVICE_UNAVAILABLE503Service Unavailable

Authentication Errors

INVALID_API_KEY

Invalid API Key

401

Description

The provided API key is invalid, malformed, or has been revoked.

Remediation

Verify your API key is correct and active. Generate a new key via POST /v1/api-keys if needed.

API_KEY_EXPIRED

API Key Expired

401

Description

The API key has expired and is no longer valid for authentication.

Remediation

Rotate your API key using POST /v1/api-keys/{id}/rotate to generate a new one.

Rate Limiting

RATE_LIMIT_EXCEEDED

Rate Limit Exceeded

429

Description

Too many requests have been made in a short period. The rate limit window will reset shortly.

Remediation

Wait for the time specified in the Retry-After header before retrying. Consider implementing exponential backoff.

BUDGET_EXCEEDED

Budget Exceeded

429

Description

The dollar-based budget for this API key has been exhausted. No further requests will be processed until the budget resets or is increased.

Remediation

Wait for the budget period to reset, upgrade your plan, or contact the account owner to increase the budget limit.

Details fields

FieldDescription
budget_limitThe total budget limit in USD
budget_spentThe amount already spent in USD
reset_atUnix timestamp when the budget resets

Idempotency

IDEMPOTENCY_KEY_CONFLICT

Idempotency Key Conflict

409

Description

A request with the same Idempotency-Key was already processed with a different request body (different request_hash).

Remediation

Use a unique Idempotency-Key for each distinct request. The key should only be reused for retries of the exact same request.

IDEMPOTENCY_KEY_REQUIRED

Idempotency Key Required

400

Description

The Idempotency-Key header is required for this endpoint but was not provided.

Remediation

Include an Idempotency-Key header with a unique value (UUID recommended) for each request.

Request Validation

INVALID_REQUEST_BODY

Invalid Request Body

400

Description

The request body failed validation. Check the 'details' field for specific validation errors.

Remediation

Review the API documentation for the expected request format and fix the validation errors listed in 'details'.

Resource Errors

RESOURCE_NOT_FOUND

Resource Not Found

404

Description

The requested resource does not exist. The 'details' field contains the resource type and ID.

Remediation

Verify the resource ID is correct. The resource may have been deleted or never existed.

Details fields

FieldDescription
resourceThe type of resource that was not found (e.g., 'api_key', 'entitlement')
idThe ID that was requested

Access Errors

ACCESS_DISABLED

Access Disabled

403

Description

Access to this resource or feature has been disabled. This may be due to an inactive entitlement, suspended account, or revoked access.

Remediation

Check your entitlement status. Contact support if you believe this is an error.

Webhook Errors

WEBHOOK_SIGNATURE_INVALID

Invalid Webhook Signature

401

Description

The webhook signature verification failed. The request may have been tampered with or the wrong secret was used.

Remediation

Ensure you are using the correct webhook secret. Verify the signature is computed correctly using HMAC-SHA256.

Server Errors

INTERNAL_SERVER_ERROR

Internal Server Error

500

Description

An unexpected error occurred on the server. This has been logged and will be investigated.

Remediation

Retry the request with exponential backoff. If the issue persists, contact support with the request_id.

SERVICE_UNAVAILABLE

Service Unavailable

503

Description

The service is temporarily unavailable due to maintenance or high load.

Remediation

Retry after the time specified in the Retry-After header. The service should recover shortly.

Budget headers

When using dollar-based budgets, Holdify returns additional headers on every response:

Budget response headers
http
X-Budget-Limit: 500.00
X-Budget-Spent: 124.50
X-Budget-Remaining: 375.50
X-Budget-Currency: USD
X-Budget-Reset: 2025-02-01T00:00:00Z

Use these headers to display budget information to your customers or trigger alerts before budgets are exhausted. When a budget is exceeded, you'll receive a 429 BUDGET_EXCEEDED error.

Handling errors in code

Use the SDK's HoldifyError class to handle errors gracefully. Here's a complete example:

Error handling example
typescript
import { Holdify, HoldifyError } from '@holdify/sdk';

const holdify = new Holdify({
  apiKey: process.env.HOLDIFY_PROJECT_KEY,
});

async function verifyRequest(apiKey: string) {
  try {
    const result = await holdify.verify(apiKey);

    if (!result.valid) {
      return { error: 'Invalid API key', status: 401 };
    }

    if (result.remaining <= 0) {
      return {
        error: 'Rate limit exceeded',
        status: 429,
        retryAfter: result.reset
      };
    }

    // Check budget remaining (if using dollar-based budgets)
    if (result.budget && result.budget.remaining <= 0) {
      return {
        error: 'Budget exceeded',
        status: 429,
        headers: {
          'X-Budget-Remaining': '0',
          'X-Budget-Reset': result.budget.reset_at
        }
      };
    }

    return { success: true, plan: result.plan };

  } catch (error) {
    if (error instanceof HoldifyError) {
      switch (error.code) {
        case 'RATE_LIMIT_EXCEEDED':
          // Wait and retry
          await new Promise(r => setTimeout(r, error.retryAfter * 1000));
          return verifyRequest(apiKey);
        case 'BUDGET_EXCEEDED':
          // Cannot retry - budget is exhausted
          return { error: 'Budget exceeded', status: 429, budgetExceeded: true };
        case 'SERVICE_UNAVAILABLE':
          // Fail open or closed based on your needs
          console.warn('Holdify unavailable, failing open');
          return { success: true, fallback: true };
        default:
          console.error(`Holdify error: ${error.code}`, error.message);
          return { error: 'Verification failed', status: 500 };
      }
    }
    throw error;
  }
}