Skip to main content
Creating a charge is not an idempotent operation by nature: two calls with the same body create two distinct resources. So that you can retry without duplicating and reconcile your operations against those of TapiPay, the API follows the header-based idempotency pattern (the same approach as Stripe).

How it works

Send the Idempotency-Key header in your creation requests. It is optional, and your body stays clean: control information is not mixed with the resource data.
The response always includes the externalRequestId field, whether or not you sent the key:
  • If you sent Idempotency-Key: externalRequestId is exactly the value you sent.
  • If you did not send it: the backend generates an externalRequestId (a UUID) and returns it to you, so that you can use it in future queries and reconciliation.
In both cases the debtId is debt_ + externalRequestId.

Permanent deduplication

The externalRequestId is a permanent unique key within your organization: there is a uniqueness constraint with no expiration (no TTL or time window).
Retrying with an already-used Idempotency-Key does not return the original resource: it returns a 409 RESOURCE_CONFLICT error. The resource is not duplicated and you receive an explicit signal that the key was already taken.
409 RESOURCE_CONFLICT
This is why the key must be unique per operation intent: use a distinct key for each charge you want to create, and reuse the same one only when you are retrying exactly the same operation after a timeout or a network error.

Dual function: idempotency and reconciliation

The externalRequestId serves two roles at once:

Idempotency

Protects against duplicates when you retry a request that failed or expired.

Reconciliation

It is the external key of the debt. You can filter and list by it: GET /debts?externalRequestId=....

Where each key applies

Each creation resource has its own external key.

Subscriptions

The key of a subscription is externalSubscriptionId, which goes in the body and is unique per organization. Repeating it returns 409 RESOURCE_CONFLICT. POST /subscriptions does not use the Idempotency-Key header. The debts generated by the subscription use externalRequestId = <externalSubscriptionId>-cycle-<n>, with n starting at 0, so you can find the first cycle’s debt with GET /debts?externalRequestId=SUB-2026-007-cycle-0. See Subscriptions. The key of a payment link is externalPaymentLinkId:
  • If you send it in the body, that value is used and the Idempotency-Key header is ignored.
  • If you do not send it but you send the Idempotency-Key header, the header value is used as externalPaymentLinkId.
  • If you send neither, the link has no external key: externalPaymentLinkId is null and each request creates a new link.
Repeating an externalPaymentLinkId returns 409 RESOURCE_CONFLICT and no debt is created. See Payment links.
Idempotency applies per organization. The same key in two distinct organizations does not interfere with each other.