Quickstart
Run four curl commands against a sandbox account and produce a successful card charge. New sandbox merchants ship with a default fee plan and active billing agreements, so there's nothing to provision before you start.
If you don't have a Frame account yet, see Install for the dashboard + keys flow first.
1. Set your sandbox key
export FRAME_SECRET_KEY=sk_sandbox_...
2. Create an account
The Account is who the charge is associated with. Request the card_send capability so the account can be charged.
curl --request POST \
--url https://api.framepayments.com/v1/accounts \
--header "Authorization: Bearer $FRAME_SECRET_KEY" \
--header 'Content-Type: application/json' \
--data '{
"type": "individual",
"capabilities": ["card_send"],
"profile": {
"individual": {
"email": "marcia@example.com",
"name": { "first_name": "Marcia", "last_name": "Longo" }
}
}
}'
Copy the account id from the response.
3. Create a payment method
Attach a test card to the account. Sandbox accepts raw card numbers — production integrations encrypt card data with Frame.js. See Testing for the full test-card list.
curl --request POST \
--url https://api.framepayments.com/v1/payment_methods \
--header "Authorization: Bearer $FRAME_SECRET_KEY" \
--header 'Content-Type: application/json' \
--data '{
"type": "card",
"account": "<account_id>",
"card_number": "4242424242424242",
"cvc": "123",
"exp_month": "12",
"exp_year": "2030"
}'
Copy the payment method id from the response.
4. Create a transfer
Call POST/v1/transfers with the account and payment method IDs. 2000 charges $20.00 — amounts are integers in the smallest currency unit.
curl --request POST \
--url https://api.framepayments.com/v1/transfers \
--header "Authorization: Bearer $FRAME_SECRET_KEY" \
--header 'Content-Type: application/json' \
--data '{
"amount": 2000,
"currency": "USD",
"account_id": "<account_id>",
"source_payment_method_id": "<payment_method_id>",
"description": "First transfer"
}'
The response returns the Transfer with "status": "succeeded" — Frame handles the charge in-line, so charge-flow transfers reach a terminal status before the response returns. Confirm the new transfer in the Frame Dashboard's Transfers view (sandbox mode). For asynchronous flows (payouts, 3D Secure, manual confirmation), subscribe to the transfer.succeeded and transfer.failed webhooks instead of inferring from the response.
Next
- Transfers concept — lifecycle, event model, how transfers compose
- Accept a payment — production-shape integration with Frame.js + webhook handling
- Testing — declined cards, 3D Secure, ACH test accounts