Skip to main content
POST
Create Payout
Creates a payout from the trading account or from one of the account’s virtual accounts to an active destination on an active beneficiary. Hop calls the first a withdrawal and the second a payout; the API uses one object for both, told apart by funding_source (see Withdrawals and payouts). Funds are held the moment the payout is created; Hop submits it to a provider later, so a successful response means the payout was accepted and funded, not that it has been sent. Every successful response is 200, including the first successful create. Compare the returned id to tell a new payout from an idempotent replay. Requires an API key with write access on the payments scope.

Path Parameters

string
required
The account’s external ID (starts with acct_)

Headers

string
required
Key for this payout: any string up to 255 characters, a UUID recommended but not enforced. Scoped to the account in the path: a key this account has used before returns that payout with 200 when the body is the same and 409 IDEMPOTENCY_CONFLICT when it differs; the same key on another account is a separate payout. See Idempotency.
Reuse the same key and request body when retrying. Changing payment_rail, amount, beneficiary, currency or another request field returns 409 IDEMPOTENCY_CONFLICT; use a new key for a new payout. Older payouts created before payload comparison was introduced may still return the original payout without checking the body. For an existing payout created without payment_rail, replaying the original request with payment_rail omitted or set to null remains valid. This compatibility does not allow a new virtual-account-funded payout to omit payment_rail.

Request Body

string
required
Beneficiary external ID (starts with bene_). Must be active and belong to this account.
string
required
Payout destination external ID (starts with dest_). Must be active and belong to that beneficiary.
string
required
Payout amount as a decimal string, greater than 0. It must not carry more decimal places than the currency allows.
string
required
Currency code from the accepted list. It must be enabled for payouts on the account and equal the destination’s currency: a destination pays out in one currency only.
object
Balance to fund the payout from: {"type": "trading_account"} (a withdrawal) or {"type": "virtual_account", "virtual_account_id": "va_…"} (a payout). Defaults to the trading account when omitted. The virtual account must belong to this account, be active, and hold the payout currency.
string
Required and non-null when funding_source.type is virtual_account.Omit payment_rail for trading-account funding. Virtual-account payouts support the rails below. Cut-offs are in UTC on working days; settlement times apply to payouts submitted before the cut-off.
string
Optional note carried on the payout (max 500 characters)
object
Fee the platform charges its end user, debited from the funding source on top of amount and credited to the platform’s fee-collection account when the payout completes (released back if the payout fails or is cancelled, but not refunded on a return). Platform customers only: end-customer accounts. Fields: currency (string, must equal the payout currency) and amount (string, > 0, at most the currency’s decimal places); unknown keys are rejected.

Response

Returns 200 with the payout, flat: the beneficiary and destination appear as plain id strings. List Payouts returns the expanded objects. A new payout starts as pending, or pending_approval when an approval policy applies. It becomes processing when Hop submits it to a rail. pending means the payout has not yet been processed. Wait for processing or completed, through Get Payout or a webhook endpoint.
string
Payout identifier (starts with po_)
string
Always returns "payout"
string
Account ID (starts with acct_)
string
Beneficiary ID (starts with bene_). null only on payouts Hop booked manually on your behalf.
string
Payout destination ID (starts with dest_). null only on payouts Hop booked manually on your behalf.
string
Blockchain network for a crypto payout, otherwise null
string
Blockchain transaction hash for a crypto payout, otherwise null. It appears once the payout is on chain, so it is null on a payout that has not been submitted yet.
string
Payout amount (decimal)
string
Currency code
string | null
Selected payout rail, using the lowercase values listed in Create Payout. Returned from creation onward when a rail was selected. null means no explicit selection, including on historical payouts. This field records the selection, not confirmation of the rail actually used by the provider.
string
Amount converted to USD, or null when no rate was available
object
Balance funding the payout, always present: {"type": "trading_account"} for a withdrawal, {"type": "virtual_account", "virtual_account_id": "va_…"} for a payout
object
Platform fee charged on top of amount (currency, amount), or null when none
string
Payout status, one of eight values:
  • pending: funded and queued, either awaiting Hop’s review or approved and awaiting submission
  • pending_approval: waiting for approval in your portal under an approval policy
  • processing: submitted to the provider
  • completed: the provider confirmed the payment left
  • failed: the payout could not be funded or the provider rejected it; the hold is released
  • cancelled: cancelled before submission; the hold is released
  • returned: the payment left but the receiving bank returned it
  • voided: a completed payout reversed by Hop
Transitions: pending → pending_approval | processing | completed | failed | cancelled; pending_approval → pending | cancelled; processing → completed | failed; completed → returned | voided. failed, cancelled, returned and voided are terminal.
string
SWIFT UETR (unique end-to-end transaction reference) for a wire, or null. Also available as tracking_details.uetr; this top-level field remains for compatibility.
object
Payment-network tracking identifiers, populated as they become available. The object is always present; unavailable or inapplicable identifiers are null. The same object is included in payout webhooks.
string
ISO 8601 timestamp when the payout was initiated
string
ISO 8601 timestamp when Hop sent the payment command to the provider, or null
string
ISO 8601 timestamp when the payout completed, or null
string
ISO 8601 timestamp when the payout failed, or null
string
Reason for failure, or null
string
ISO 8601 timestamp when the payout was voided, or null
string
Reason the payout was voided, or null
string
Note carried on the payout, or null
string
ISO 8601 timestamp when created
string
ISO 8601 timestamp when last updated
string
Actor that created the payout: the API key id (starts with ak_), or hop_admin for a manual payout
string
Actor that last updated the payout, or null

Errors

The trading account may only pay a beneficiary marked self_owned, that is, your own bank account at another institution: a payout funded from the trading account is a withdrawal. Third parties must be paid from a virtual account. The rule is re-checked when the payout is approved, so flipping a beneficiary after creation does not bypass it. When a payout funded from the trading account is rejected for INSUFFICIENT_FUNDS or CREDIT_LIMIT_EXCEEDED, the payout is persisted in failed state under that Idempotency-Key. The 422 response includes error.details.payout_id, and subscribed endpoints receive payout.failed. No funds are held and no payout.created event is emitted for this failure. Retrying with the same key and body returns 200 with the same failed payout. Inspect its status; after resolving the funding issue, use a new key to create a new payout.

Request Example

Response Example

status is pending_approval here only when an approval policy is configured for your organization.