## How it works

HTTP status describes the request outcome; the payment's own status describes whether it was paid. Keep these two error channels separate in your integration.

## Implementation

Validate field names, amounts, currencies and shop selection before retrying. Invalid input requires a corrected request; invalid credentials require a key or scope fix. Handle rate limits and transient network or server failures with bounded backoff. A processor decline can be returned in a successful HTTP response and is not a reason to blindly repeat the charge. Log a request or payment identifier and a redacted diagnostic message.

## Fields

| `type` | When |
| --- | --- |
| `invalid_request` | `4xx` errors |
| `api` | SpicePay-side `500` |
| `connector` | Processor error (`CE_` codes) |
| `blocked` | Payment blocked; comes with HTTP `200`, so check for `error` |

## Common codes

| Code | HTTP | Meaning | What to do |
| --- | --- | --- | --- |
| `IR_01` | 401 | API key missing or invalid | Check the `api-key` header. |
| `IR_18` | 401 | Not authorized; `message` says why | Check the key and request. |
| `IR_22` | 403 | Key may not access this resource | Use a key with access. |
| `IR_04` | 400 | Required field missing | Add the field in `message`. |
| `IR_21` | 400 | Several required fields missing | See `data`. |
| `IR_05` | 422 | Wrong field format | Fix the field. |
| `IR_06` | 422 | Invalid request data, including unknown fields | Fix the request. |
| `IR_07` | 400 | Invalid field value | Fix the value. |
| `IR_08` | 400 | `client_secret` missing or expired | Create a new payment or session. |
| `IR_09` | 400 | `client_secret` does not match the payment | Send the payment's own secret. |
| `IR_13` | 400 | Refunds would exceed the captured amount | Lower `amount`. |
| `IR_14` | 400 | Payment state does not allow this call | Retrieve it; `message` names the expected states. |
| `IR_28` | 400 | Currency not supported | Use a supported currency. |
| `IR_30` | 400 | Connector account misconfigured | Fix the connector credentials. |
| `IR_39` | 400 | No connector takes this payment method | Enable the method or change the request. |
| `IR_52` | 429 | Too many requests | Wait for `Retry-After` (also `data.retry_after_secs`). |
| `HE_01` | 400 | Object already exists (reused `refund_id` or `payment_id`) | Use the existing object. |
| `HE_02` | 404 | Object does not exist | Check the ID and shop. |
| `HE_03` | 400 | Object state does not allow this (refund on an unpaid payment) | Retrieve the object. |
| `HE_04` | 404 | Related object not found (dispute, file, successful payment) | Check the ID. |
| `CE_00`–`CE_09` | varies | Processor error | See `message` and `reason`. |

## HTTP example

```json
{
  "error": {
    "type": "invalid_request",
    "code": "IR_04",
    "message": "Missing required param: amount"
  }
}
```

## Related guides

- [Payment lifecycle](/docs/general/payment-lifecycle/)
- [Idempotency](/docs/payment-api/idempotency/)
