Pay out to an account
This guide covers paying out to an Account — pushing money out to the account holder's debit card or bank account. Frame models payouts as transfers with a destination payment method and no source. Same primitive as charges, opposite direction.
The work is mostly upstream: the recipient account has to be onboarded with the right capability before any payout can succeed. Once they're onboarded, the payout call itself is a single API request.
Payout-category billing agreement required. Transfers::CreateService validates that your merchant has an active billing agreement covering the payout category before the call reaches the processor — without one, every payout returns a validation error. New merchants are provisioned with payout-category agreements at signup, but many pre-2026 merchants only have charge-category agreements. Check the merchant dashboard's Transfer billing agreements view; contact Frame support if you need a payout-category agreement provisioned.
Prerequisites
| Requirement | Details |
|---|---|
| Recipient account | An individual Account that has completed KYC (kyc capability active). |
| Payout capability | Either card_receive (push-to-card) or bank_account_receive (ACH credit), with status active. |
| Destination payment method | A debit card or bank account attached to the recipient. The payment method is what *_receive capabilities verify against. |
| Active billing agreement | Your platform must have an active billing agreement covering the payout category. New merchants get this provisioned by default. |
If the recipient hasn't been onboarded yet, start with Run onboarding — request kyc plus the payout capability you need, redirect through an onboarding session, and verify the capability statuses came back active before continuing here.
1. Confirm the recipient account is ready
Retrieve the account and check the payout-relevant capabilities.
You want both:
kyccapabilityactive— Frame won't push funds to an unverified individual.card_receive(orbank_account_receive) capabilityactive— the payment method is attached and verified.
If either is pending or disabled, route the account holder back through onboarding before attempting a payout.
curl --request GET \
--url https://api.framepayments.com/v1/accounts/99c6b0da-... \
--header 'Authorization: Bearer SECRET_KEY'
{
"capabilities": [
{ "name": "kyc", "status": "active" },
{ "name": "card_receive", "status": "active" }
]
}
2. Resolve the destination payment method
Each capability is bound to the payment method that verified it. For a payout you need the payment_method_id of the card or bank account that Frame pushes funds to.
List the payment methods on the recipient account and find the one whose type matches the capability you're paying through:
card_receive→ payment method of typecard(typically a debit card).bank_account_receive→ payment method of typebank_account.
If the recipient has multiple eligible payment methods, your application chooses which one — Frame doesn't pick a default.
curl --request GET \
--url 'https://api.framepayments.com/v1/accounts/99c6b0da-.../payment_methods' \
--header 'Authorization: Bearer SECRET_KEY'
3. Create the payout transfer
A payout is a transfer with destination_payment_method_id set and no source_payment_method_id. Frame interprets that shape as a push to the destination. See the transfers concept for the full flow-selection logic.
Pass the destination payment method and the amount in the smallest currency unit (cents for USD). Include account_id to attribute the payout to the recipient — this is what surfaces in reconciliation and webhooks downstream.
speed is required for ACH destinations, forbidden for push-to-card. ACH accepts standard (default-ish timing, 1-2 business days), same_day (settles same business day), or asap (fastest available rail). Push-to-card has only one speed — omit the field for card_receive destinations.
description and metadata are for your own bookkeeping. They appear on the transfer and on any webhook payload that references it.
curl --request POST \
--url https://api.framepayments.com/v1/transfers \
--header 'Authorization: Bearer SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"amount": 50000,
"currency": "usd",
"account_id": "99c6b0da-...",
"destination_payment_method_id": "pm_a1b2c3d4-...",
"description": "May creator payout",
"metadata": {
"payout_period": "2026-05"
}
}'
curl --request POST \
--url https://api.framepayments.com/v1/transfers \
--header 'Authorization: Bearer SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"amount": 50000,
"currency": "usd",
"account_id": "99c6b0da-...",
"destination_payment_method_id": "pm_a1b2c3d4-...",
"speed": "standard",
"description": "May creator payout",
"metadata": {
"payout_period": "2026-05"
}
}'
4. Handle the response
The transfer is returned synchronously, but for payouts the settlement is asynchronous. The processor confirms the push over the network, not in-line with your API call. Expect the response to come back pending.
Three states to wire for:
pending— the initial state. Frame has accepted the payout; the processor hasn't confirmed yet.succeeded— funds have moved. The recipient sees them when their bank or card issuer posts.failed— the processor rejected.failure_reasondescribes why (typically invalid destination or recipient-side issues).
Don't act on pending as success. Wait for the webhook, or poll GET/v1/transfers/{id} with backoff.
{
"type": "transfer.succeeded",
"data": {
"id": "tr_...",
"status": "succeeded",
"amount": 50000,
"currency": "usd",
"account_id": "99c6b0da-...",
"destination_payment_method_id": "pm_a1b2c3d4-...",
"updated": 1748966400
}
}
Common variations
ACH speed tiers. When paying out to a bank_account_receive destination, the required speed parameter selects the settlement window: standard (1-2 business days), same_day (same business day), or asap (fastest available rail, processor-dependent). Push-to-card (card_receive) doesn't accept speed — it has one rail, and the issuing bank decides when funds actually post (usually minutes).
Payouts to businesses. Business accounts can receive payouts to a bank_account_receive capability bound to the business's bank account. The KYB flow during onboarding handles the entity verification; the payout call is the same.
Paying out to many recipients at once. If you're paying out to a long list of creators or sellers, create one transfer per recipient. Each transfer is independently settled; there is no bulk-payout primitive in V1.
Gotchas
Symptom: the payout call returns failed immediately with failure_reason: "destination_payment_method_invalid". Why: the destination payment method either doesn't belong to the account you specified, or it's a credit card (which doesn't support push-to-card). Fix: re-list the account's payment methods and confirm you're using a debit card or bank account, and that the account_id matches the payment method's owner.
Symptom: the transfer succeeded according to Frame but the recipient says nothing arrived. Why: the bank's posting delay, especially over weekends or for certain ACH timing windows. Fix: check updated on the transfer — that's when Frame last touched the record, which for a succeeded transfer is when the processor confirmed. Funds usually post within hours for push-to-card, 1-2 business days for ACH.
Next steps
- For the conceptual model behind charges, payouts, and transfers, see Transfers concept.