Payment methods

A payment method is the source or destination of funds in a transfer. One PaymentMethod primitive holds every flavor — a card, a bank account, a wallet credential — attached to an account and gated by the capabilities the account holds.

A merchant integration treats payment methods as the resource that's charged or paid out to. Concepts above this (Account, Capability) describe who can transact and what they're allowed to do; concepts below (Charge, Payout) describe each individual money movement. Payment methods sit in the middle — the durable record of "this card / this bank account, attached to this account."

Types

The type field on a payment method is one of:

typeWhat it representsAPI sub-object
cardDebit or credit card. Used for charges (card_send) and push-to-card payouts when the card is debit (card_receive).card — brand, last_four, exp_month, exp_year
achUS bank account (checking or savings). Used for ACH debits (bank_account_send) and ACH credits (bank_account_receive).ach — bank_name, last_four, account_type
paypalPayPal account credential. Wallet-style payment method primarily used for payouts.Wallet-specific
venmoVenmo account credential. Wallet-style payment method primarily used for payouts.Wallet-specific
cash_appCash App account credential. Wallet-style payment method primarily used for payouts.Wallet-specific

Two naming distinctions worth keeping straight:

  • The type is ach (not "bank_account") on the API surface. Don't expect a type: "bank_account" value in the wire format.
  • The capability is bank_account_send / bank_account_receive (not ach_send). The capability namespace and the type namespace use different vocab for the same rail.

Wallet types (paypal, venmo, cash_app) sit in the same PaymentMethod primitive but follow different attachment + verification flows than cards. They're primarily used as payout destinations on platforms supporting peer-to-peer-style recipient flows. Apple Pay and Google Pay are different — those wrap underlying cards through device-bound tokens and surface as type: card payment methods; see Use the payment request button for that flow.

State

A payment method walks through four states:

  • active — usable in transfers, as either source or destination depending on the account's capabilities.
  • blocked — temporarily unusable. Frame or your platform marked it suspect (suspected fraud, processor decline pattern, manual review). Charges and payouts against a blocked method fail; the record stays on the account and can be unblocked.
  • locked — short-term hold typically applied during in-flight verification or risk review. Distinct from blocked in that locked is process-driven (Frame's internal flow has the method paused) rather than policy-driven; it usually resolves automatically once the upstream check completes.
  • detached — explicitly removed from the account. Detached methods can't be used in transfers and don't appear in the account's default payment-method list. The record is retained for audit but functionally inactive.

Use the blockPaymentMethod endpoint to mark a method blocked (reversible) and detachPaymentMethod to remove it from the account (also reversible, but treat as the stronger action). The distinction matters when you're separating "freeze pending investigation" from "user requested removal."

Attachment

Every payment method belongs to exactly one account at a time, recorded as account_id on the PaymentMethod. A customer_id field still exists on the schema for backward compatibility with the deprecated Customer model — if you're integrating fresh, ignore it and use account_id. See accounts for the canonical-party-model background.

There are two paths to attach a method:

  • Hosted onboarding session — the payment_method step (and the payouts step for payout election) inside a session collects the card or bank-account details from the account holder and attaches the method automatically. Use this when KYC + payment method collection happens in the same flow.
  • Direct via createPaymentMethod — your application drives the UX (typically frame-js's Card or PaymentRequestButton component on the client, posting a token to your backend, which then creates the payment method). Use this when you want full control over the collection experience, or for non-onboarding flows (subscription renewals, replacing a card, etc.).

Both paths produce the same PaymentMethod record. The hosted session is faster to ship; the direct path is more flexible.

Relationship to capabilities

Payment methods don't activate on their own — they're gated by capabilities on the parent account:

CapabilityWhat it lets the payment method do
card_sendA card can be charged (debit or credit, source-side).
card_receiveA debit card can receive push-to-card payouts (destination-side). Requires KYC.
bank_account_sendA bank account can be debited via ACH (source-side).
bank_account_receiveA bank account can receive ACH credits (destination-side). Requires KYC.

A payment method exists whether or not its corresponding capability is active — but a transfer using it will fail with a capability error if the capability isn't active on the account. The capability is the gate; the payment method is just the artifact.

For payouts specifically, see accounts/onboarding: the payouts step inside a hosted session elects a specific payment method as the payout destination (account.payout_payment_method_id). Charge-side payment methods don't need an analogous election — any active card with card_send works as a source_payment_method_id.

Verification

Payment-method verification is a separate concern from capability activation. Two independent verifications can run against a payment method:

  • Card verification — $1 pre-auth + 3DS challenge + code entry; stores a cryptogram on the payment method for dispute defense.
  • Bank account verification — instant hosted bank-login (Plaid-backed) confirming ownership of the linked account.

A payment method can be active without these verifications — the capability gating is the floor, the verifications are additive signal. Whether you require them depends on your platform's risk policy. See the dedicated verification concepts for the mechanics.

Gotchas

Symptom: a transfer fails with a capability error even though the payment method shows status: active. Why: the payment method is active, but the capability required for the flow shape (e.g., card_receive for the destination side of a payout) isn't active on the account. Fix: check the capability status on the account, not just the payment method state. The payment method being on file is necessary but not sufficient.

Symptom: you charged a customer's card last month; this month the same card returns decline. Why: the card was reissued, expired, or the issuer flagged the previous transaction. Frame doesn't proactively notify when a card becomes invalid — issuers don't broadcast that signal reliably. Fix: listen for decline codes on the transfer (see decline codes) and prompt the customer to update the payment method when an issuer returns a "do not honor" or "card not active" category.

Symptom: you detached a payment method, then a webhook fired referencing its ID. Why: detached methods stay queryable by ID for audit. Webhooks that reference historical transactions still carry the original payment_method_id even after detachment. Fix: this is expected; status: detached on the payment method indicates the relationship is over but historical references persist.

Reference

For the full API surface, see POST/v1/payment_methods and the rest of the Payment Methods resource.