# Error handling & response codes

PayLater returns conventional HTTP status codes and a JSON body describing what went wrong. Most errors carry an `error` (and sometimes a `message`) field.

**Example error**

```json
{
  "error": "Refund Error",
  "message": "Transaction happened less than 10 minutes ago. Please try again later."
}
```

## Authentication errors

| Example | Cause |
| --- | --- |
| `{ "error": "invalid_client", "error_description": "Invalid client or Invalid client credentials" }` | Wrong `client_id` / `client_secret`. |
| `{ "error": "unsupported_grant_type", "error_description": "Unsupported grant_type" }` | `grant_type` must be `client_credentials`. |

## Common API errors

| Example | Cause |
| --- | --- |
| `{ "error": "Invalid API Key" }` | Missing or invalid bearer token. |
| `{ "error": "Order ID must be unique" }` | Reusing an `order_id`. |
| `{ "error": "Order ID is required" }` | Required parameter omitted. |
| `{ "error": "Merchant ID cannot be null" }` | Missing outlet/merchant context. |
| `{ "error": "Amount must be between 300 and 25000" }` | `amount` outside the accepted range. |
| `{ "message": "Shopper not found" }` | Lookup did not match a registered shopper. |

## Request to Pay errors

| Reference | HTTP | Meaning |
| --- | --- | --- |
| `RTP-409-DUPLICATE-REFERENCE` | `409` | A Request-to-Pay already exists for this merchant order reference. |
| `RTP-UPSTREAM-ERROR` | `404` | Unable to process Request-to-Pay right now. Please try again later. |

## Refund errors

| Message | Meaning |
| --- | --- |
| `Transaction Reference is required` | `order_id` omitted. |
| `Order cannot be refunded as it happened more than 29 days ago.` | Outside the 29-day window. |
| `Order contains transactions other than down payment and cannot be refunded.` | Not refundable. |
| `Transaction happened less than 10 minutes ago. Please try again later.` | Must wait at least 10 minutes. |
| `Invalid Transaction Reference.` | Unknown order. |
| `Invalid Transaction type.` | Not a refundable transaction type. |

## Payment status codes

| status | Meaning |
| --- | --- |
| `0` | Customer did not proceed |
| `1` | Pending |
| `2` | Success |
| `3` | Failed |

> **Tip: Webhooks over polling**
>
> Wherever possible, rely on signed [webhooks](https://docs.paylaterapp.com/webhooks.html) for state changes instead of polling.
