Credentials
API key only, as everywhere in the Business API. Every recipient and destination is scoped to the key’s business; there is no cross-business lookup and no way to reference another business’s recipient.Rate limits
All eleven operations share 120 requests per minute, counted once against your business and once against the key. The limit is declared on the controller, so a payout run competes with itself: creating a recipient, adding a detail, and resolving a destination all draw on the same allowance, as do transfers and FX quotes on the same controller. A payout batch therefore costs roughly:
At 120 per minute, a run of 500 saved payees needs about eight and a half minutes of steady pacing. Build the pacing in; do not discover it as
429s.
What Sakawave stores
Two consequences for your side of the integration:
- You cannot read routing values back. If your UI must show a customer the account number they saved, keep your own copy under your own controls — Sakawave will not return it.
- Correcting a value means replacing it. There is no update endpoint. Add a new payment detail and delete the old one.
The 24-hour window
A destination expires 24 hours after creation and is consumed by the transfer that spends it. Both produce the same error:destinationId on your payout row and reusing it on retry.
Defaults
Every recipient with any payment details has exactly one default.- The first detail added becomes the default whatever
isDefaultsays. - Setting
isDefaulton a later one moves the default. - Deleting the default promotes another automatically; you cannot end up with details and no default.
- There is no way to clear a default.
paymentDetailId uses the default. If your recipients hold several details, name the one you mean rather than depending on which is current.
No events
Recipients, payment details, and destinations emit no webhooks. Nothing tells you a destination expired, and nothing tells you a detail became provider-locked. Both surface as errors at the point of use.Legacy provider-locked details
A payment detail whose routing values live at the provider rather than with Sakawave carriesproviderLocked: true. Sakawave tries to resolve it when you use it; when it cannot, you get 409 payment_detail_provider_locked and the only fix through this API is to delete the detail and add it again with its routing fields.
Check for it proactively if you hold long-lived recipients:
Configuration checklist
-
fieldsbuilt from route descriptors at runtime, never hardcoded - A fresh destination resolved per transfer attempt, never reused
- Transfer idempotency carried by
externalReference, not by the destination - Your own copy kept of any routing value your UI must display
- Payout batches paced under 120 calls per minute across all eleven operations
-
displayNamefrom the destination shown for approval, since verification may have changed it - A check for
providerLockeddetails if your recipients predate the current routing model