RevKeen Docs

Errors

Error envelope, status codes, and retry guidance for the RevKeen API

The RevKeen API returns errors in a consistent envelope with a machine-readable code, a human-readable message, and — where applicable — the offending param and structured field-level details.

Reserve the message for display and the code for branching logic.

Non-2xx status codes always return an error object. Inspect error.code before error.message when writing retry or recovery logic.

Error envelope

{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_error",
    "message": "Customer email is required.",
    "param": "customer.email",
    "details": {
      "fields": {
        "customer.email": ["must be a valid email address"]
      }
    }
  }
}
FieldTypePresent onPurpose
error.typestring (enum)All errorsBroad category: invalid_request_error, authentication_error, permission_error, etc.
error.codestring (enum)All errorsStable machine-readable identifier. Safe for logic branching.
error.messagestringAll errorsHuman-readable description. Content may change; do not parse.
error.paramstringValidation errorsDotted path of the offending parameter.
error.detailsobjectValidation errorsStructured extras — most commonly details.fields[param] = [reasons].

HTTP status codes

StatusMeaningWhen you see it
400Invalid requestMalformed JSON, unknown fields, failed validation. Do not retry without fixing the payload.
401UnauthenticatedMissing, malformed, or revoked API key.
403Permission deniedKey is valid but lacks the required scope, or the resource belongs to a different merchant.
404Not foundResource does not exist, or is not visible to your API key.
409ConflictIdempotency-Key collision with a different body, or a concurrent state-transition conflict.
422Unprocessable entityBusiness-rule failure (for example, refunding more than the original charge).
429Rate limit exceededBack off using the Retry-After header.
500Server errorTransient — retry with exponential backoff.
503Service unavailableCapacity issue — retry with exponential backoff.

Retry guidance

Status / ConditionRetryable?Strategy
500, 502, 503, 504YesExponential backoff, at least 3 attempts, capped at ~30s total.
429YesHonour the Retry-After header (seconds). Do not retry sooner.
Network timeout on a mutationYesRetry with the same Idempotency-Key — see Idempotency.
400, 404, 422NoPermanent — fix the payload or resource first.
401, 403NoRotate or rescope the API key, then retry.
409 (idempotency conflict)NoThe key was reused with a different body. Generate a new key.

Validation errors

Validation errors (type: invalid_request_error, code: validation_error) always include a details.fields map. Keys are dotted parameter paths; values are arrays of reasons.

{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_error",
    "message": "One or more fields are invalid.",
    "details": {
      "fields": {
        "items[0].quantity": ["must be greater than 0"],
        "customer.email":    ["must be a valid email address"]
      }
    }
  }
}

Render field errors next to the offending input rather than surfacing message alone.

Rate-limit errors

429 Too Many Requests responses always include a Retry-After header in seconds:

HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json

{ "error": { "type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Too many requests." } }

Published plan limits are on the rate limits reference.

Examples

curl -i https://staging-api.revkeen.com/v2/customers/cus_does_not_exist \
  -H "x-api-key: $REVKEEN_API_KEY"
# HTTP/1.1 404 Not Found
# { "error": { "type": "invalid_request_error", "code": "resource_missing", "message": "Customer not found." } }
import { RevKeen, RevKeenError } from "@revkeen/sdk";

const client = new RevKeen({ apiKey: process.env.REVKEEN_API_KEY! });

try {
  await client.customers.retrieve("cus_does_not_exist");
} catch (err) {
  if (err instanceof RevKeenError) {
    if (err.code === "resource_missing") {
      // permanent — do not retry
    }
  }
  throw err;
}
import revkeen "github.com/RevKeen/sdk-go"

_, err := client.Customers.Retrieve(ctx, "cus_does_not_exist")
if rkErr, ok := revkeen.AsError(err); ok {
  if rkErr.Code == "resource_missing" {
    // permanent — do not retry
  }
}
use RevKeen\RevKeenClient;
use RevKeen\Exception\RevKeenException;

$client = new RevKeenClient(['api_key' => getenv('REVKEEN_API_KEY')]);

try {
    $client->customers->retrieve('cus_does_not_exist');
} catch (RevKeenException $e) {
    if ($e->getCode() === 'resource_missing') {
        // permanent — do not retry
    }
    throw $e;
}

See also

On this page