Skip to main content

Error response shape

All API errors return a consistent JSON structure inside an error object:
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "The `amount` field must be a positive integer.",
    "param": "amount",
    "doc_url": "https://docs.leanrails.com/errors/parameter_invalid"
  }
}
FieldTypeDescription
typestringThe category of error. Always present.
codestringA machine-readable error code. Always present.
messagestringA human-readable explanation. Always present.
paramstring | nullThe request parameter that caused the error, if applicable.
doc_urlstringA link to the documentation for this error code.

Error types

TypeHTTP StatusDescription
api_error500An unexpected error on the server side.
authentication_error401The API key is missing, invalid, or expired.
invalid_request_error400, 422The request is malformed or contains invalid parameters.
rate_limit_error429Too many requests in a given time window.
payment_error402The payment itself failed (e.g., card declined).

Common error codes

resource_missing

The requested resource does not exist or is not accessible with the current API key.
curl https://api.leanrails.com/v1/payment_intents/pi_nonexistent \
  -u "$API_KEY:"
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No PaymentIntent found with ID 'pi_nonexistent'.",
    "param": "id",
    "doc_url": "https://docs.leanrails.com/errors/resource_missing"
  }
}

parameter_invalid

A request parameter has an invalid value.
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "The `currency` field must be a valid three-letter ISO currency code.",
    "param": "currency",
    "doc_url": "https://docs.leanrails.com/errors/parameter_invalid"
  }
}

parameter_missing

A required parameter was not provided.
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "The `amount` field is required.",
    "param": "amount",
    "doc_url": "https://docs.leanrails.com/errors/parameter_missing"
  }
}

amount_invalid

The amount value is not a valid positive integer.
{
  "error": {
    "type": "invalid_request_error",
    "code": "amount_invalid",
    "message": "Amount must be a positive integer representing cents.",
    "param": "amount",
    "doc_url": "https://docs.leanrails.com/errors/amount_invalid"
  }
}

amount_too_large

The amount exceeds the maximum allowed value.
{
  "error": {
    "type": "invalid_request_error",
    "code": "amount_too_large",
    "message": "Amount exceeds the maximum allowed value of 99999999.",
    "param": "amount",
    "doc_url": "https://docs.leanrails.com/errors/amount_too_large"
  }
}

payment_intent_unexpected_state

The PaymentIntent is not in the expected state for the requested operation.
# Trying to confirm an already succeeded PaymentIntent
curl -X POST https://api.leanrails.com/v1/payment_intents/pi_1abc123def456/confirm \
  -u "$API_KEY:" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "error": {
    "type": "invalid_request_error",
    "code": "payment_intent_unexpected_state",
    "message": "This PaymentIntent has a status of 'succeeded' and cannot be confirmed. Only PaymentIntents with status 'requires_confirmation' can be confirmed.",
    "param": null,
    "doc_url": "https://docs.leanrails.com/errors/payment_intent_unexpected_state"
  }
}

invalid_state_transition

The requested state transition is not allowed for the resource.
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_state_transition",
    "message": "Cannot transition from 'canceled' to 'requires_confirmation'.",
    "param": null,
    "doc_url": "https://docs.leanrails.com/errors/invalid_state_transition"
  }
}

payment_not_initialized

The payment has not been properly initialized before attempting the operation.
{
  "error": {
    "type": "payment_error",
    "code": "payment_not_initialized",
    "message": "A payment method must be attached before confirming this PaymentIntent.",
    "param": "payment_method",
    "doc_url": "https://docs.leanrails.com/errors/payment_not_initialized"
  }
}

idempotency_key_reuse

The idempotency key was already used with different request parameters.
{
  "error": {
    "type": "invalid_request_error",
    "code": "idempotency_key_reuse",
    "message": "This idempotency key has already been used with different request parameters.",
    "param": null,
    "doc_url": "https://docs.leanrails.com/errors/idempotency_key_reuse"
  }
}

internal_error

An unexpected server-side error occurred.
{
  "error": {
    "type": "api_error",
    "code": "internal_error",
    "message": "An internal error occurred. Please retry the request.",
    "param": null,
    "doc_url": "https://docs.leanrails.com/errors/internal_error"
  }
}

Handling errors in code

const fetch = require("node-fetch");

const API_KEY = process.env.API_KEY;
const credentials = Buffer.from(`${API_KEY}:`).toString("base64");

const response = await fetch("https://api.leanrails.com/v1/payment_intents", {
  method: "POST",
  headers: {
    Authorization: `Basic ${credentials}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({ amount: 2000, currency: "usd" }),
});

const body = await response.json();

if (!response.ok) {
  const { error } = body;

  switch (error.type) {
    case "authentication_error":
      // Check your API key configuration
      console.error("Auth failed:", error.message);
      break;

    case "invalid_request_error":
      // Fix the request parameters
      console.error(`Invalid param '${error.param}': ${error.message}`);
      break;

    case "rate_limit_error":
      // Back off and retry
      console.warn("Rate limited. Retrying after delay...");
      break;

    case "payment_error":
      // Show a message to the customer
      console.error("Payment failed:", error.message);
      break;

    case "api_error":
      // Retry with the same idempotency key
      console.error("Server error. Retrying...");
      break;
  }
}

HTTP status code summary

StatusMeaning
200Success
201Resource created
400Bad request (invalid parameters)
401Authentication failed
402Payment failed
404Resource not found
422Unprocessable (e.g., idempotency key reuse)
429Rate limited
500Internal server error