Payouts to users or suppliers
What it is
You need to move money out of your Fintoc Account to any third-party bank account. Transfers are sent in real time (SPEI in Mexico, TEF in Chile) and every state change is broadcast via webhooks.
Best for
Any product that needs to move money out: lending disbursements, marketplace payouts, wallet withdrawals, refunds and supplier payments.
How the money flows
sequenceDiagram
autonumber
participant You as Your backend
participant Fintoc
participant Rail as SPEI / TEF
You->>Fintoc: POST /v2/transfers
Fintoc-->>You: Transfer pending
Fintoc->>Rail: Submit
Rail-->>Fintoc: Settled / rejected
Fintoc->>You: transfer.outbound.succeeded · .rejected · .failed
How to configure it
1. Fund the Account you're paying from
Outbound transfers debit from an Account. Add funds by sending a transfer from your company's bank account to that Account's root_account_number. You'll see the deposit arrive as an inbound transfer.
2. Create the transfer
Always sign the request with a valid JWS signature and include an Idempotency-Key header so retries are safe.
Mexico — counterparty only needs account_number (CLABE). For mobile numbers or debit cards, include counterparty.institution_id (see SPEI institution codes).
curl --request POST \
--url https://api.fintoc.com/v2/transfers \
--header 'Authorization: sk_test_...' \
--header 'Fintoc-JWS-Signature: ...' \
--header 'Idempotency-Key: 1ebfd86c-a75b-4606-872f-9f1cdd9724ca' \
--header 'content-type: application/json' \
--data '{
"amount": 59013,
"currency": "mxn",
"account_id": "acc_M8sKf230BgHjD4",
"comment": "Pago credito 10451",
"reference_id": "150195",
"counterparty": { "account_number": "012969123456789120" },
"metadata": { "customer_id": "12050123", "order_id": "ord_abc" }
}'
Chile — counterparty needs 5 fields: holder_id (RUT), holder_name, account_number, account_type, and institution_id (see Chile institution codes).
curl --request POST \
--url https://api.fintoc.com/v2/transfers \
--header 'Authorization: sk_test_...' \
--header 'Fintoc-JWS-Signature: ...' \
--header 'Idempotency-Key: 1ebfd86c-a75b-4606-872f-9f1cdd9724ca' \
--header 'content-type: application/json' \
--data '{
"amount": 1869,
"currency": "CLP",
"account_id": "acc_M8sKf230BgHjD4",
"comment": "Pago credito 10451",
"counterparty": {
"holder_id": "771433855",
"holder_name": "Pied Piper SpA",
"account_number": "502955923",
"account_type": "checking_account",
"institution_id": "cl_banco_de_chile"
},
"metadata": { "customer_id": "12050123" }
}'
Always use an Idempotency KeyA network blip mid-request is the single most common cause of duplicate transfers in production. Generate a UUID per logical transfer (e.g. per withdrawal in your DB), and reuse the same key on retries. See Idempotent requests.
3. Track status with webhooks
Transfers don't always settle synchronously. Drive your state machine off webhooks, not off the API response body.
Event | When it fires | Recommended action |
|---|---|---|
| Money was credited to the counterparty. | Mark as paid in your system, notify the user, store the |
| 🇲🇽 Banxico or the destination bank rejected the transfer (see SPEI codes). | Refund your user's internal balance / mark the withdrawal as failed. |
| Transfer never reached the destination due to a processing error. | Retry with a new idempotency key, or surface the error to the user. |
Webhooks may arrive out of orderA
transfer.outbound.rejectedcan arrive before a.succeededfor the same transfer, even though the timeline was succeed → reject. Always branch ondata.statusin your handler, not on event order.
4. (Optional) Verify the destination first
For user-entered destinations (first withdrawal or disbursement), strongly consider verifying the CLABE before the real payout. See Verify a CLABE.
Updated about 2 hours ago