# Errors

Errors use standard HTTP status codes. An error response never includes `data`, so you can't read partial results from a failed request.

## Error shape

```json title="json · 422 Unprocessable Content"
{
    "code": "4220000",
    "success": false,
    "message": "The given data was invalid.",
    "errors": {
        "amount": [
            "The amount field must be greater than 0."
        ],
        "success_url": [
            "The success url field must be a valid URL."
        ]
    }
}
```

## Fields

| Field | Type | Description |
| --- | --- | --- |
| `code` | `string` | A 7-digit code for the exact case, listed below. Branch on this, not on `message`. |
| `success` | `boolean` | Always `false` on an error. |
| `message` | `string` | What went wrong, for people. It can change; don’t parse it. |
| `errors` | `object` | Only on `422`: each field that failed, with its messages. |

```json title="json · 409 Conflict"
{
    "code": "4090001",
    "success": false,
    "message": "This Idempotency-Key was already used with a different request."
}
```

## Status codes

| Status | Meaning |
| --- | --- |
| `200` | Read or action succeeded. |
| `201` | A resource was created. |
| `202` | Accepted: queued to run shortly, such as a webhook repost. |
| `400` | The request body could not be read. |
| `401` | Missing or invalid API key. |
| `403` | The key can’t make this request, for example from an address outside its allowlist. |
| `404` | The resource doesn’t exist, or it belongs to another merchant or mode. |
| `405` | This method isn’t allowed on this path. |
| `409` | Conflict, such as an `external_reference_id` or Idempotency-Key reused with a different request, or canceling a payment that is no longer pending. |
| `422` | Validation failed. A number sent as a string also fails here. |
| `429` | Too many requests. Wait, then retry. |
| `500` | Something went wrong on our side. Retry the same request. |
| `501` | That channel isn’t live through the API yet. |

## Error codes

| code | HTTP | When | What to do |
| --- | --- | --- | --- |
| `4000000` | 400 | The request body isn’t valid JSON. | Send a valid JSON body with `Content-Type: application/json`. |
| `4010000` | 401 | The API key is missing, malformed, deleted or regenerated. | Send a current key as `Authorization: Bearer wv_...`. |
| `4030000` | 403 | This key can’t make this request, for example from an address outside its IP allowlist. | Call from an allowed address, or update the key’s allowlist in the dashboard. |
| `4030001` | 403 | A live key was sent from a browser page. Live keys belong on your server. | Use a test key in the browser (Try It takes test keys only), and call Weav with live keys only from your server. |
| `4040000` | 404 | Not found in this mode for your account. | Check the reference and that you use a live or test key to match. |
| `4050000` | 405 | This method isn’t allowed on this path. | Check the method in the endpoint’s docs. |
| `4090001` | 409 | The `external_reference_id` (or Idempotency-Key) was already used with a different request. | Use a new reference for a new payment; never change a request and keep its reference. |
| `4090002` | 409 | The same request is still in progress. | Wait a moment, then retry it. |
| `4090101` | 409 | The payment can’t be canceled: it’s no longer pending. | Retrieve the payment for its final status. |
| `4090102` | 409 | The payment can’t be canceled at the provider right now. | Retry shortly. The payment stays pending until then. |
| `4090201` | 409 | The webhook is still being sent. | Repost it once the current delivery finishes. |
| `4090301` | 409 | The checkout can’t be canceled: it’s no longer open. | Retrieve the checkout for its status. |
| `4090302` | 409 | The checkout’s payment in progress can’t be canceled at the provider right now. | Retry shortly. The checkout stays open until then. |
| `4090401` | 409 | The saved card can’t be removed at the card processor right now. | Retry shortly. It stays chargeable until then. |
| `4220000` | 422 | Validation failed. `errors` lists each field, for example an amount outside your [payment limits](https://docs.weavpayments.com/reference/channels/list-channels), a reused `external_reference_id` or a private webhook URL. | Fix the fields named in `errors` and send again. |
| `4220101` | 422 | The channel is off for your account. | Turn it on under Channels in the dashboard, or contact support. |
| `4220102` | 422 | The channel doesn’t accept that currency. | Use a currency listed in `errors.currency`. |
| `4220103` | 422 | This payment method can’t be charged. | Charge only an `ACTIVE` one. Ask your customer to save their card again if it failed or was removed. |
| `4220401` | 422 | Saving cards is off for your account. | Contact support. Weav turns it on once it has your PCI DSS evidence. |
| `4290000` | 429 | Too many requests for your account. | Wait for `Retry-After` seconds, then retry. See [Rate limiting](https://docs.weavpayments.com/rate-limiting). |
| `4290201` | 429 | This payment’s webhook was reposted less than 30 seconds ago. | Wait for `Retry-After` seconds. To check the payment’s status, [retrieve the payment](https://docs.weavpayments.com/reference/payments/retrieve-payment) instead. |
| `4290202` | 429 | Your account reposted 20 webhooks in this mode in the last minute. | Wait for `Retry-After` seconds. Weav already retries every webhook for about 7 days, so there’s no need to repost in bulk. |
| `5000000` | 500 | Something went wrong on our side. | Retry the same request. If it keeps happening, contact support. |
| `5010100` | 501 | That channel isn’t live through the API yet. | Use a test key for now, or contact support. |

A code’s meaning never changes once published. New codes may be added, so treat an unknown one by its HTTP status.
