Skip to main content

Reference

Errors

Finora Business uses a consistent response envelope. When something goes wrong, you get an HTTP status, a stable error code, a human message, and a request ID you can quote in support tickets.

The response envelope

Every response — successful or not — follows the same shape. Success responses include a data object:

{
  "success": true,
  "data": { ... },
  "meta": {
    "requestId": "req_a1b2c3d4e5f6g7h8",
    "timestamp": "2026-04-17T10:30:00.000Z",
    "rateLimit": {
      "limit": 60,
      "remaining": 58,
      "reset": "2026-04-17T10:31:00.000Z"
    }
  }
}

Error responses include an error object instead:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request body validation failed",
    "details": [
      { "field": "lineItems[0].unitPrice", "message": "must be a positive number" },
      { "field": "dueDate", "message": "must be after invoiceDate" }
    ],
    "requestId": "req_a1b2c3d4e5f6g7h8"
  }
}

Always show the requestId to your users (or log it). It's how we trace requests through our logs when you file a support ticket.

General error codes

HTTPCodeMeaning
400INVALID_REQUESTMissing or invalid request parameters.
400MISSING_BUSINESS_IDbusinessId query parameter was not provided.
400INVALID_VERSIONAPI version not supported. Use /v1/.
400VALIDATION_ERRORRequest body fails schema validation. Details array lists each failed field.
400UNBALANCED_JOURNALJournal entry debits do not equal credits.
401UNAUTHORIZEDMissing or malformed Authorization header.
401INVALID_API_KEYAPI key is invalid, revoked, or expired (90-day rotation).
403FORBIDDENAuthenticated but no access to the requested business.
403BUSINESS_SUSPENDEDBusiness subscription expired or suspended.
404NOT_FOUNDResource not found.
405METHOD_NOT_ALLOWEDHTTP method not supported for this endpoint.
409CONFLICTResource already exists or state conflict (e.g. voiding an already-voided invoice).
422BUSINESS_LOGIC_ERRORValid request but violates a business rule.
429RATE_LIMITRate limit exceeded. See the retryAfter hint.
500INTERNAL_ERRORServer error. Details are logged; the response carries a requestId.

Billing & access error codes

These are specific to the Finora Business credit-and-trial model. See Billing & credits for the pricing context behind them.

HTTPCodeMeaning
402TRIAL_EXHAUSTEDYou used all 100 trial calls. Top up credits to continue, or use a test_sk_ key for free sandbox calls.
402INSUFFICIENT_CREDITSYour credit balance is zero. Top up in the dashboard.
403NO_SUBSCRIPTIONAPI keys require a Premium or Accountant Pro subscription.
403FREE_TIERSubscription was downgraded after the key was issued.
403ENTERPRISE_ONLYEndpoint is gated to enterprise accounts. Contact sales to upgrade.

Handling errors well

  • Branch on the code, not the message

    The message is for humans and may change. The code is machine-stable.

  • Respect retryAfter

    On 429 RATE_LIMIT, the error payload includes a retryAfter hint (seconds). Back off for at least that long.

  • Don't retry 4xx blindly

    Most 4xx codes indicate a problem with the request itself — fixing the input, not retrying, is the answer. 500 INTERNAL_ERROR and 429 RATE_LIMIT are the two worth retrying.

  • Surface billing errors to the operator

    Integrations that hit INSUFFICIENT_CREDITS or TRIAL_EXHAUSTED will stop working until credits are topped up. Alert the person who owns the Finora Business account, not just the log.