Skip to main content

Best Practices: Ensuring Reliable Payment Integration

This section provides key recommendations to secure, optimize, and ensure the reliability of your payment integration using the Payment API.

Idempotency: Preventing Duplicate Transactions

Why is Idempotency Important?

Requests to the Payment API may be accidentally duplicated due to:

  • Network failures, causing a retry.
  • Timeouts, leading the merchant system to resend the same request.
  • User actions, such as clicking multiple times on a "Pay" button.

Without idempotency, these scenarios could result in duplicate payments or refunds.

Send no key at all, and a retry issued after a lost response is indistinguishable from a new operation: it either executes a second time, or is rejected with a 400 once the requested amount is no longer available on the payment. Idempotency keys are strongly recommended for batch and retry-driven integrations.

Best Practices

  • Send x-idempotency-key on every state-changing call: payment creation (POST /v2/payments), capture, refund, and void.
  • One key per operation, never one key per payment. Keys are scoped to the payment, and a payment can legitimately be captured, voided, or refunded several times — two partial captures on the same authorization, for example. If two different operations on the same payment reuse the same key, the second is treated as a replay and refused with a 409 instead of being executed.
  • Derive the key from the operation itself — your own capture or refund identifier, or the payment ID plus a sequence number. Never derive it from the payment or the order alone.
  • Keep the key stable across every retry, including a retry sent hours or days later. A key regenerated per HTTP attempt provides no protection at all.
  • Retry with the same key when a response is lost (client timeout, network error, 5xx). The operation is then executed at most once.
  • Store keys for at least as long as your retry window, so a late retry can reuse the original key.

Example: Using Idempotency in a Capture Request

curl -X POST "https://api.purse-sandbox.com/payment/v2/payments/${PAYMENT_ID}/captures" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--header "x-idempotency-key: CAP#1223445" \
--data '{
"amount": 5000,
"merchant_reference": "CAP#1223445"
}'

The key is derived from the merchant's own capture reference, so every retry of this capture carries the same value, while a second capture on the same payment gets a key of its own.

What happens if the same idempotency key is reused?

A request carrying a key already processed on the same payment is answered with a 409 Conflict — whether it is a genuine retry or a different operation that reused the key by mistake:

{
"type": "urn:eu.purse:write-conflict",
"title": "Idempotency violation",
"status": 409,
"instance": "/v2/payments/558f47c6-fd88-4c28-aa2f-5d3d7a44709f/captures",
"resource_id": "432ccde8-13e8-4c31-a900-a9c40546c12a"
}

resource_id points at the resource the first call created: the payment ID for POST /v2/payments, or the capture, void, or refund operation ID for the operation endpoints. Read it back to recover the outcome of that first call.

Replays while the first call is still running

A replay arriving while the first call is still in flight is held for a bounded number of attempts, then answered like any other replay. If the first call never completes at all, the replay errors instead of resolving — so a retry that keeps failing with a 5xx should be settled by reading the payment back with GET /v2/payments/{id}, not by replaying the key again.

Security: Protecting Payment Data

Best Practices

  • Always use HTTPS for all API requests to encrypt sensitive data.
  • Use OAuth2 authentication to secure API access and prevent unauthorized requests.
  • Restrict API keys and tokens to specific IPs, users, or actions to limit exposure.
  • Monitor API access logs to detect suspicious behavior and prevent fraud.

Webhook Security

All webhook events sent by the Payment API are digitally signed to ensure their authenticity.

  • Always verify the signature using the public keys provided by /payment/v2/signing-jwks.
  • Reject any webhook that fails signature validation to prevent spoofed requests.
curl -X GET "https://api.purse-sandbox.com/payment/v2/signing-jwks" \\
-H "Authorization: Bearer <access-token>"

The returned public keys can be used to validate webhook payloads before processing them.

Optimizing API Calls: Performance & Reliability

Best Practices

  • Efficient Token Usage → Store and reuse the access token until it expires instead of requesting a new one for each API call.
  • Avoid unnecessary polling → Use webhooks instead to receive real-time updates.
  • Use connection timeouts and retries with exponential backoff for network failures.

Handling Webhooks Efficiently

Best Practices

  • Respond to webhook requests within 5 seconds to avoid timeouts.
  • Perform minimal processing inside the webhook handler → Offload heavy tasks to a background queue.
  • Log all received webhooks to debug failures and reprocess missed events if necessary.
  • Validate webhook signatures to prevent unauthorized events from being processed.

Example: Webhook Payload

{
"id": "acb149dc-cbc7-4be5-b5c7-4d3f4d40b595",
"status": "AUTHORIZED",
"amount": 12000,
"currency": "EUR",
"customer": {
"email": "[email protected]"
},
"order": {
"reference": "123456789"
}
}

Error Handling & Retry Strategies

Best Practices

  • Check all API responses and handle errors appropriately.
  • Implement retries for network failures, but do not retry on client errors (4xx).
  • Log all failed API calls to investigate recurring issues.
  • Use unique request IDs to trace failed transactions and reprocess them if necessary.

Final Recommendations

Following these best practices will help you:

  • Ensure safe and secure payment processing.
  • Improve API efficiency and reduce unnecessary calls.
  • Prevent duplicate operations and avoid transaction inconsistencies.
  • Handle webhook events effectively without missing critical updates.

Now you're ready to build a robust and reliable payment integration!