PayFacto API - v2.0 - Error Types & Error Object
PayFacto API - v2.0 - Error Types & Error Object
Reference for the error object returned by the PayFacto Payment API v2.0 when a request fails. Covers all error types, the structure of the error response, and recommended actions for each type.
βοΈ
Overview β When Errors Occur
The PayFacto Payment API v2.0 uses standard HTTP status codes to indicate the outcome of a request. A response in the 2xx range indicates success. A response in the 4xx or 5xx range indicates an error β the response body will contain an error object with details.
| HTTP Code | Meaning | Notes |
|---|
| 200 OK | Success (idempotent repeat) | A POST with a previously used Idempotency-Key β the original response is returned. No new resource was created. |
| 201 Created | Success (new resource) | A new charge, refund, or verification was created. Check the response body for the resource details. |
| 400 Bad Request | Invalid request | A required field is missing, has the wrong type, or fails validation. Error type: INVALID_REQUEST_ERROR. |
| 401 Unauthorized | Authentication failure | The Authorization header is missing, malformed, or the credentials are incorrect. |
| 402 Payment Required | Transaction declined | The card issuer declined the transaction. Error type: CARD_ERROR. Check result.declineCode. |
| 404 Not Found | Resource not found | The UUID in the URL does not match any resource in this merchant account. |
| 409 Conflict | Idempotency conflict | A duplicate Idempotency-Key was submitted with a different request body. Error type: IDEMPOTENCY_ERROR. |
| 422 Unprocessable | Invalid state transition | The resource exists but cannot be modified in its current state (e.g. capturing an already-captured charge). |
| 500 Internal Server Error | PayFacto server error | An unexpected error on PayFacto's side. Retry once after a short delay. Error type: INTERNAL_ERROR. |
| 502 / 503 | Downstream or service error | A network or processor issue. Error type: DOWNSTREAM_ERROR. Retry with exponential backoff. |
βΉοΈ
Always check the HTTP status code before parsing the response body. A 2xx response will never contain an error object. A 4xx or 5xx response will always contain an error object.
π
Error Object Structure
When a request fails, the API returns a JSON error object at the root of the response body. The structure is consistent across all error types.
| Field | Type | | Description |
|---|
| type | string | required | The error classification. Always one of the five error type values β see Error Types below. |
| message | string | required | A human-readable summary of what went wrong. Suitable for logging but not for display to end users. |
| code | string | optional | A machine-readable error code providing more detail within the error type. For example invalid_field or card_declined. |
| details | string | optional | Additional context about the error β for example, which field failed validation or what the constraint was. |
| invalidFields | array | optional | Present on INVALID_REQUEST_ERROR only. An array of objects, each with field (the field name) and message (why it failed). |
| chargeId | string | optional | Present when the error is related to a specific charge β for example on a capture or void that fails. |
JSON β Example error response (HTTP 400)
{
"type": "INVALID_REQUEST_ERROR",
"message": "Request validation failed.",
"code": "invalid_field",
"details": "One or more fields failed validation.",
"invalidFields": [
{ "field": "amount", "message": "Must be a positive integer." },
{ "field": "invoiceNumber", "message": "Exceeds maximum length of 25 characters." }
]
}JSON β Example error response (HTTP 402 β card declined)
{
"type": "CARD_ERROR",
"message": "The card was declined by the issuer.",
"code": "card_declined",
"result": {
"declineCode": "INSUFFICIENT_FUNDS",
"isoResponseCode": "051",
"issuerMessage": "INSUFFICIENT FUNDS",
"processorResponseCode": "05"
}
}There are five possible values for the type field. Each maps to a distinct root cause and requires a different handling strategy.
CARD_ERRORDo not retryHTTP 402
When it occurs
The card issuer refused the transaction. The card data is structurally valid but the issuer declined for a business reason β insufficient funds, card blocked, expired card, CVV mismatch, etc. Check result.declineCode for the specific reason.
Recommended action
Do not retry automatically. Surface an appropriate message to the customer based on the decline code β for example, ask them to use a different card, check their balance, or contact their bank. See the Decline Codes reference for the full list.
INVALID_REQUEST_ERRORDo not retryHTTP 400
When it occurs
The request is malformed or contains invalid field values. A required field is missing, a value is the wrong type, a string exceeds its maximum length, or an enum field contains an unrecognised value. Check invalidFields for the specific fields that failed.
Recommended action
Fix the request before retrying. Do not retry with the same payload β it will fail again. Inspect invalidFields to identify exactly which fields need to be corrected.
IDEMPOTENCY_ERRORDo not retryHTTP 409
When it occurs
A request was submitted with an Idempotency-Key that was already used for a different request body. The key is already associated with a previous transaction that had different parameters.
Recommended action
Generate a new Idempotency-Key (UUID v4) for the new payment attempt. Never reuse a key from a previous transaction β only reuse it when retrying the exact same request after a timeout.
DOWNSTREAM_ERRORRetryableHTTP 502HTTP 503
When it occurs
An error occurred in a downstream system β the card network, the acquirer, or the processor β that prevented the transaction from completing. This is not a PayFacto error and is typically transient.
Recommended action
Retry the request once after a short delay (e.g. 5β10 seconds). If the error persists across multiple retries, contact PayFacto Support. Use a new Idempotency-Key on each retry attempt.
INTERNAL_ERRORRetryableHTTP 500
When it occurs
An unexpected error occurred on PayFacto's infrastructure. This is rare and is not caused by the request content.
Recommended action
Retry once after a short delay. If the problem persists, contact PayFacto Support and include the request details and timestamp. Use a new Idempotency-Key on each retry.
β οΈ
INVALID_REQUEST_ERROR β Field Validation Details
When type is INVALID_REQUEST_ERROR, the response includes an invalidFields array. Each entry identifies a specific field that failed validation.
| Field | Type | | Description |
|---|
| invalidFields[].field | string | required | The dot-notation path of the field that failed validation. For example: paymentMethod.card.number or amount. |
| invalidFields[].message | string | required | A human-readable description of why the field failed β for example: "Must be a positive integer" or "Exceeds maximum length of 25 characters". |
JSON β Multiple field validation errors
{
"type": "INVALID_REQUEST_ERROR",
"message": "Request validation failed.",
"code": "invalid_field",
"invalidFields": [
{
"field": "amount",
"message": "Must be a positive integer in the smallest currency unit (cents)."
},
{
"field": "paymentMethod.type",
"message": "Must be one of: CARD, TERMINAL, PAYMENT_TOKEN, CASH."
},
{
"field": "invoiceNumber",
"message": "Exceeds maximum length of 25 characters."
}
]
}β οΈ
The message values in invalidFields are for developer logging only β they are not stable and may change between API versions. Use field to programmatically identify which input to highlight in your UI.
π
Error Handling Patterns
Recommended patterns for handling each error type in your integration.
β
Card Declined (CARD_ERROR)
Check result.declineCode and surface a specific message to the customer β for example "Insufficient funds β please try another card." Do not show raw decline codes or issuer messages to end users. Do not retry with the same card automatically.
β οΈ
Validation Error (INVALID_REQUEST_ERROR)
Iterate over invalidFields and map each field path to the corresponding input in your UI. Highlight the field and display the message as help text. Fix the payload and resubmit β do not generate a new Idempotency-Key for a corrected validation error retry.
π
Idempotency Conflict (IDEMPOTENCY_ERROR)
Generate a fresh UUID v4 as the new Idempotency-Key and submit the request again. Log the conflict so you can audit which key was reused. Ensure your key generation is per-attempt, not per-session or per-order.
π
Transient Error (DOWNSTREAM_ERROR / INTERNAL_ERROR)
Implement exponential backoff: wait 1s, retry; wait 2s, retry; wait 4s, retry β up to 3 attempts. Use a fresh Idempotency-Key on each retry. After 3 failed attempts, surface a generic error and notify the customer to try again later. Log the full error object and timestamp for support escalation.
π
Timeout (No Response)
If your HTTP client times out before receiving a response, the transaction may or may not have been processed. Do not assume failure. Retry the request using the same Idempotency-Key β if the original succeeded, PayFacto will return 200 OK with the original response. If it failed, a new attempt will be made. Always set a reasonable HTTP client timeout (recommended: 30 seconds).