Errors
VNSwitch uses HTTP status codes to say whether a request worked, and returns a JSON body with an
error object when it did not. Read the code to decide what to do: it is stable, while
message is written for people and can change.
Response (HTTP 404)
{
"error": {
"type": "invalid_request",
"message": "Payment does not exist in our records",
"code": "HE_02"
}
}Error response format
| Field | Type | Description |
|---|---|---|
error.type | string | Broad category, see the table below. |
error.code | string | Specific error code, for example IR_04 or HE_02. Use this in your code. |
error.message | string | Human-readable explanation. Log it; do not parse it. |
error.reason | string | Optional extra detail, for example which provider rejected the request. |
error.connector | string | Optional. The payment provider involved, for provider errors. |
error.data | any | Optional extra data, for example the list of missing fields for IR_21. |
error.payment_id | string | Optional. The payment the error is about. |
Values of error.type:
type | Meaning |
|---|---|
invalid_request | The request was wrong or not allowed: bad or missing fields, bad key, unknown object, wrong state. |
api | Something went wrong inside VNSwitch. |
connector | The payment provider returned an error. The HTTP status is the provider’s status. |
blocked | The payment was blocked by a risk or blocklist rule. |
integrity_check_failed | The provider’s response did not match the request (for example a different amount). |
If the request body is not valid JSON, or a field has the wrong JSON type (for example a decimal number in amount), VNSwitch answers 400 with code IR_06. In this one case the category field is named error_type instead of type. Rely on error.code and the HTTP status, which are always present.
blocked and integrity_check_failed errors are returned with HTTP status 200. Always check for an error object in the body, not only the status code.
Error codes
Codes starting with IR_ are invalid requests, HE_ are errors found by VNSwitch while
handling a valid request, and CE_ come from the payment provider.
| HTTP | Code | Meaning | What to do |
|---|---|---|---|
| 401 | IR_01 | API key missing or invalid. | Check the api-key header and that you use the key for the right
environment. |
| 404 | IR_02 | Unknown URL. | Check the path and the base URL. |
| 405 | IR_03 | HTTP method not allowed for this URL. | Check the method. |
| 400 | IR_04 | A required parameter is missing. The message names it. | Add the field. |
| 422 | IR_05 | A field has the wrong format. | Fix the field. |
| 400 / 422 | IR_06 | Invalid request body or invalid data. | Fix the request. |
| 400 | IR_07 | A field has an invalid value. | Fix the value. |
| 400 | IR_08 | client_secret missing or expired. | Create a new payment or fetch a fresh secret. |
| 400 | IR_09 | client_secret does not belong to this payment. | Use the secret of the same payment. |
| 400 | IR_12 | Maximum number of refunds reached for this payment. | Do not retry. |
| 400 | IR_13 | Refund amount is more than the captured amount. | Lower the amount; check earlier refunds. |
| 400 | IR_14 | The object is in a state that does not allow this action (for example capturing a payment that already succeeded). | Retrieve the object and check its status. |
| 400 | IR_16 | A precondition for the action is not met. The message explains it. | Fix the cause, then retry. |
| 400 | IR_19 | Not supported (for example a payment method type). | Use a supported option. |
| 400 | IR_20 | The payment provider does not support this action. | Use another flow or provider. |
| 400 | IR_21 | Several required parameters are missing. data lists them. | Add the fields. |
| 403 | IR_22 | Your key is not allowed to access this resource. | Check that the object belongs to your account. |
| 400 | IR_28 | Currency not supported. | Use a currency enabled for your account. |
| 400 | IR_39 | No payment provider on your account can process this payment method. | Contact info@nivc.ai to enable it. |
| 400 | IR_52 | The payment session has expired. | Create a new payment. |
| 500 | HE_00 | Internal error in VNSwitch. | Retry safely (see below). |
| 400 | HE_01 | Duplicate: an object with this ID already exists (for example the same payment_id or refund). | Do not create it again. Retrieve the existing object. |
| 404 | HE_02 | The object does not exist (payment, refund, customer, mandate, payment method, payout, event). | Check the ID and the environment. |
| 400 | HE_03 | Validation failed (for example refunding a payment that has not succeeded, or mandate validation). | Fix the cause; do not retry unchanged. |
| 404 | HE_04 | Object not found (for example dispute, file, address, successful payment). | Check the ID. |
| 501 | IR_00 | Not available yet. | Do not retry. |
| 400 | CE_01 | Authorization with the provider failed. | Ask the customer to try again or use another method. |
| 400 | CE_02 | Authentication (for example 3-D Secure) with the provider failed. | Ask the customer to try again. |
| 400 | CE_03 | Capture failed at the provider. | Retrieve the payment, then decide. |
| 400 | CE_04 | The card data is invalid. | Ask the customer to check the card details. |
| 400 | CE_05 | The card has expired. | Ask for another card. |
| 400 | CE_06 | Refund failed at the provider. | Retrieve the refund, then decide. |
| Provider’s | CE_00 | Other error from the payment provider. connector and reason give details. | Log it; retry only if the status is 5xx. |
| 200 | HE_03 (type blocked) | The payment was blocked by a blocklist rule. | Do not retry. |
| 200 | IE_00 | Integrity check failed. | Retrieve the object and contact info@nivc.ai. |
A payment that the bank or provider declines is not always an API error. Often the request succeeds (HTTP 200) and the payment has status: “failed” with error_code and error_message fields. Handle both cases. See Payment lifecycle.
Retry failed requests safely
Money must never move twice because you retried. Follow these rules:
- Never retry a 4xx error unchanged. It fails again. Fix the request first.
HE_01(duplicate) means the first request already worked: retrieve the object instead. - 5xx errors, timeouts and network failures are unknown outcomes. The request may or may
not have been processed. Before you send it again, find out what happened:
- If you set your own
payment_idwhen creating the payment, retry with the samepayment_id. If the first attempt went through, you getHE_01instead of a second payment; then retrieve the payment. - For other actions (confirm, capture, refund, payout), retrieve the object first and check
its
status. Only repeat the action if it did not happen.
- If you set your own
- Back off between retries, for example 1, 2, 4 and 8 seconds, and stop after a few tries.
- Do not retry
blocked,IR_12,IR_13or card errors (CE_04,CE_05). These need a different request or a different payment method. - Treat webhooks as the source of truth for results that arrive later. See Webhooks.
Log error.code, error.message and the object ID for every error. Include them when you
contact info@nivc.ai.