VRPlatformVRPlatform

Error Contract

Handle structured API errors without parsing messages

API failures use a structured envelope:

{
  "code": "FORBIDDEN",
  "message": "Cannot modify transaction - attached to published statement",
  "issues": [],
  "context": { "lockReason": "statement" }
}
  • code is the stable error class for program behavior.
  • issues contains field or domain-specific validation details.
  • context contains typed recovery information such as lock reasons, supported archive outcome, next action, or retry delay. It is omitted when the error carries no recovery information.
  • message is display text and must not be parsed.
  • links appears only on strict query-validation errors and points to the public interactive reference (docs) and OpenAPI document (schema). It is never an empty object.

Codes And HTTP Status

code values on the wire map to HTTP status as follows:

codeHTTP status
BAD_REQUEST400
UNAUTHORIZED401
FORBIDDEN403
NOT_FOUND404
METHOD_NOT_SUPPORTED405
CONFLICT409
RATE_LIMITED429
UNPROCESSABLE_CONTENT422
INTERNAL_SERVER_ERROR500
NOT_IMPLEMENTED501
SERVICE_UNAVAILABLE503, or 504 when a database connection is interrupted

Branch on code, not on raw status, and treat unknown codes as non-retryable failures.

Lock Context

Lock failures are 403 FORBIDDEN and identify the lock in context:

  • Mutation locks return context.lockReason, either "statement" (attached to a published owner statement) or "period" (blocked by books closing). Period locks also include context.booksClosedAt, the first open date in YYYY-MM-DD format.
  • Delete locks on referenced entities return 400 BAD_REQUEST with context.lockReasons (an array of human-readable reason strings) and context.suggestedOnLocked (for example "archive") when the operation supports an alternative outcome such as archiving instead of deleting.

Other domain errors can include nextAction or supportAction. Present only the actions returned or documented for that operation. See Requests, Locks & Issues.

Query Errors

Query parameters are strict. An unsupported parameter returns 400 with links to the API schema and an issue that identifies the operation schema location. Remove the parameter; it is not silently ignored.

{
  "code": "BAD_REQUEST",
  "message": "Invalid query parameters. Compare the request with the OpenAPI schema and remove unsupported parameters.",
  "issues": [
    {
      "message": "Unrecognized key: \"foo\"",
      "schema": "#/paths/transactions/get"
    }
  ],
  "links": {
    "docs": "https://api.vrplatform.app/spec",
    "schema": "https://api.vrplatform.app/openapi.json"
  }
}

Rate Limits

Webhook subscription, verification-test, and replay operations enforce the limits documented in Webhooks. An excess request returns RATE_LIMITED with HTTP 429 and Retry-After. Other API surfaces do not currently enforce application-level quotas.

Availability

Transient database connectivity exhaustion is returned as SERVICE_UNAVAILABLE. Retry only idempotently and with bounded backoff. A domain-specific service-unavailable response can include structured delay or pending-resource context.

See Error handling and retry policy and Requests, Locks & Issues.

On this page