Skip to main content
The Stripe Clone API uses conventional HTTP response codes to indicate the success or failure of a request. Codes in the 2xx range indicate success, codes in the 4xx range indicate a client error, and codes in the 5xx range indicate a server error. All errors return a JSON body with a consistent structure:
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "A human-readable description of the error.",
    "param": "amount"
  }
}

Error Types

TypeHTTP StatusDescription
api_error500Something went wrong on our end. These are rare and indicate an internal problem.
authentication_error401Invalid or missing API key. Verify your credentials.
invalid_request_error400 / 404The request had invalid parameters or referenced a resource that does not exist.
rate_limit_error429Too many requests hit the API too quickly. Back off and retry with exponential backoff.
payment_error402Payment processing failed. The card may have been declined or the payment method is invalid.

Error Codes

resource_missing

The requested resource does not exist.
  • HTTP Status: 404
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No such payment intent: 'pi_nonexistent'",
    "param": "id"
  }
}
How to fix: Verify the resource ID you are passing. Ensure the resource was created in the same environment (test vs. live mode) that you are querying.

parameter_invalid

A parameter provided in the request is invalid.
  • HTTP Status: 400
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Invalid value for 'currency': must be a 3-letter ISO currency code.",
    "param": "currency"
  }
}
How to fix: Check the API reference for allowed values for the parameter indicated in the param field. Correct the value and retry.

parameter_missing

A required parameter is missing from the request.
  • HTTP Status: 400
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "Missing required parameter: 'amount'.",
    "param": "amount"
  }
}
How to fix: Include the required parameter listed in the param field. Consult the API reference for the endpoint to see all required parameters.

amount_invalid

The refund amount must be a positive integer.
  • HTTP Status: 400
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "amount_invalid",
    "message": "Refund amount must be a positive integer.",
    "param": "amount"
  }
}
How to fix: Ensure the amount field is a positive integer representing the smallest currency unit (e.g., cents for USD).

amount_too_large

The refund amount exceeds the amount available to refund on the charge.
  • HTTP Status: 400
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "amount_too_large",
    "message": "Refund amount (5000) exceeds the available amount to refund (3000).",
    "param": "amount"
  }
}
How to fix: Check the charge’s amount_refunded and amount fields to calculate the remaining refundable amount. Pass an amount that does not exceed this value.

payment_intent_unexpected_state

The PaymentIntent’s current status does not allow the requested action.
  • HTTP Status: 400
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "payment_intent_unexpected_state",
    "message": "This PaymentIntent's status is 'succeeded' and cannot be confirmed. Only a PaymentIntent with status 'requires_confirmation' can be confirmed.",
    "param": null
  }
}
How to fix: Verify the PaymentIntent’s current status before performing the action. Only call confirm on intents with status requires_confirmation, and only call cancel on intents that have not yet succeeded.

invalid_state_transition

The requested status transition is not allowed for the PaymentIntent.
  • HTTP Status: 400
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_state_transition",
    "message": "Cannot transition PaymentIntent from 'canceled' to 'requires_confirmation'.",
    "param": "status"
  }
}
How to fix: Review the PaymentIntent lifecycle. A canceled intent cannot be reused. Create a new PaymentIntent instead.

payment_not_initialized

The payment has not been initialized with the payment engine.
  • HTTP Status: 400
  • Type: payment_error
{
  "error": {
    "type": "payment_error",
    "code": "payment_not_initialized",
    "message": "This PaymentIntent has not been initialized with a payment engine. Confirm the intent to begin processing.",
    "param": null
  }
}
How to fix: Ensure the PaymentIntent has been confirmed and that a valid payment method is attached before attempting to process the payment.

idempotency_key_reuse

The same idempotency key was used with different request parameters.
  • HTTP Status: 422
  • Type: invalid_request_error
{
  "error": {
    "type": "invalid_request_error",
    "code": "idempotency_key_reuse",
    "message": "Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a new key.",
    "param": null
  }
}
How to fix: Use a unique idempotency key for each distinct request. If you need to retry a request with different parameters, generate a new idempotency key.

internal_error

An unexpected error occurred on the server.
  • HTTP Status: 500
  • Type: api_error
{
  "error": {
    "type": "api_error",
    "code": "internal_error",
    "message": "An unexpected error occurred. Please retry your request.",
    "param": null
  }
}
How to fix: Retry the request with exponential backoff. If the error persists, contact support. Using an idempotency key ensures the request is safe to retry.

Handling Errors

We recommend writing code that gracefully handles all possible API errors:
import requests

try:
    response = requests.post(
        "https://api.leanrails.com/v1/payment_intents",
        auth=("sk_test_xxx", ""),
        json={"amount": 2000, "currency": "usd"}
    )
    response.raise_for_status()
    payment_intent = response.json()
except requests.exceptions.HTTPError as e:
    error = e.response.json().get("error", {})
    error_type = error.get("type")
    error_code = error.get("code")

    if error_type == "authentication_error":
        # Check your API key
        pass
    elif error_type == "invalid_request_error":
        # Fix the request parameters
        print(f"Invalid parameter: {error.get('param')}")
    elif error_type == "rate_limit_error":
        # Back off and retry
        pass
    elif error_type == "api_error":
        # Retry with exponential backoff
        pass