kepa

Safe retries

Retry a payment without creating a second charge.

Before a money-moving request, generate one unique Idempotency-Key and store it with your payment attempt. If you do not receive a response, send the same request again with the same key.

The rule

  • Same key and same request: returns the original result or continues the original operation.
  • Same key and different request: is rejected. A key belongs to one exact operation.
  • New key: means a new operation and can create another charge.
const paymentAttemptId = crypto.randomUUID(); // create once

async function authorize(body) {
  return fetch("https://api.kepapay.co/api/v1/terminal/transactions/authorize", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.KEPA_DEVICE_TOKEN}`,
      "Idempotency-Key": paymentAttemptId,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
}

// If the network fails, call authorize again with the same body and key.

When to retry

  • Retry network failures and 5xx responses with the same key and unchanged body.
  • Do not retry validation, authentication, or ownership errors unchanged.
  • Do not automatically retry an issuer decline. Ask for another payment method.
  • After a successful response, store payment.id and stop retrying.

Terminal timeouts

If a terminal loses the authorization response, first retry with the same key or query recovery status using that key. Follow the returned recoveryAction. Never generate a new key just because the original result is uncertain.

Which operations require a key?

The endpoint reference marks Idempotency-Key as required or optional for each operation. Do not assume every POST accepts it. Terminal authorization and pre-authorization capture require it; use it on payment and checkout creation whenever the endpoint offers it.