Supply your own payout ID
create accepts an optional id — a client-generated ID the new payout is created under. It must be a UUID (the API validates this); if omitted, the server generates one.
For idempotency, don’t use a random UUID per attempt — derive a deterministic UUID (v5) from the thing that makes the payout unique in your system, such as an invoice ID or payroll period, so every retry produces the same id:
createFinalized requires an id for exactly this reason — a create-and-finalize call must be safely retryable.
Individual payments
Within a batch, a payment’s identity is (batch, receiver, memo) — enforced by a unique constraint.- The same receiver can appear on multiple rows in one batch as long as each row carries a distinct memo. Put your per-payment business key in the memo — an invoice code or installment identifier like
INV-1042:install-3— and each obligation becomes its own idempotent row. - Re-adding the same (receiver, memo) never creates a second payment: a direct add is rejected as a duplicate, and an invite-driven attach updates the existing row’s amount in place.
- A retried add-payments call therefore cannot double-pay anyone — the repeated rows collide on (batch, receiver, memo) instead of duplicating.
Nonces
Every payout also carries anonce. The SDK generates one automatically; pass your own only if you need the nonce to be deterministic across systems.
Retry pattern
- Compute the payout
idfrom your business key before calling Pvium. - On a timeout or network error, retry the same call with the same
id. - A retried create whose
idalready exists is rejected as a duplicate — it will not create a second payout, and it will not return the existing one. Catch the conflict, fetch the payout withpvium.payout.get(id), and continue from its current state — it may already be created or even finalized. - Key webhook processing on payout and payment IDs, so re-deliveries are no-ops. See Webhooks.

