Advanced error handling
This guide describes how to build resilient integrations with the Paypercut API.
It covers retry strategies, idempotency, and how to handle transient failures safely.
Overview
Not all errors should be treated the same.
Your integration should distinguish between:
- permanent failures that require correction
- temporary failures that can be retried
- network-level failures where the outcome is unknown
Blindly retrying all failed requests can lead to duplicate operations, inconsistent state, and degraded user experience.
Retry strategy
Retries should only be performed when a request fails due to a temporary condition.
Safe to retry
Retry when the failure is likely temporary:
- HTTP
500(internal error) - HTTP
502,503,504(upstream issues) - network timeouts
- connection failures
- payment declines with
advice_code = try_again_later
Do not retry
Do not retry when the failure is permanent:
- HTTP
400(invalid request) - HTTP
401(authentication failed) - HTTP
403(forbidden) - card declines with
advice_code = do_not_try_again - validation errors
Exponential backoff
When retrying, use exponential backoff.
Example strategy:
- Retry after 1 second
- Retry after 2 seconds
- Retry after 4 seconds
- Retry after 8 seconds
Avoid tight retry loops. Always introduce delays between retry attempts.
Idempotency
Idempotency ensures that retrying a request does not create duplicate operations.
This is critical for:
- creating payments
- creating accounts
- any operation with side effects
Idempotent requests
Your integration should send an idempotency key with all POST requests that create or mutate state.
Example:
POST /v2/payments
Idempotency-Key: 01HZY6...
Behavior
When the same idempotency key is reused:
- the first request is processed normally
- subsequent identical requests return the same result
This guarantees that retries do not create duplicate resources.
When to use idempotency
Use idempotency for:
- payment creation
- account creation
- payout operations
- any request that may be retried automatically
Always reuse the same idempotency key when retrying the same logical operation.
Network failures
Network failures are different from API errors.
Examples:
- request timeout
- connection reset
- DNS failure
In these cases, the request outcome is unknown.
Handling unknown outcomes
When a request fails at the network level:
- the request may have succeeded
- the request may have failed
- the client did not receive the response
To handle this safely:
- retry using the same idempotency key
- avoid issuing a new request without idempotency protection
Payment-specific retries
For payments, retry behavior should be guided by decline data.
Retry only when:
advice_code = try_again_later- the decline category is temporary or soft
Do not retry when:
advice_code = do_not_try_again- the decline is permanent (for example, insufficient funds or expired card)
Request customer action when:
decline_code = authentication_required- card details must be corrected
- a different payment method is required
Handling timeouts
If a request times out:
- do not assume failure
- retry with the same idempotency key
- check resource state if possible
Logging and observability
Your integration should log:
- request payloads (excluding sensitive data)
- response status codes
- error objects
trace_id
The trace_id is the primary identifier used to debug issues with Paypercut support.
Recommended integration pattern
Ensure all state-changing requests include an idempotency key.
Process successful responses and error responses accordingly.
Retry only for transient failures using exponential backoff.
Store the trace ID for debugging and support.
Best practices
- Use idempotency for all write operations
- Implement exponential backoff for retries
- Avoid retrying permanent failures
- Use decline and advice codes for payment decisions
- Treat network failures as unknown outcomes
- Log all errors with trace IDs

