curl --request POST \
--url https://examples.staging.rampapay.com/v1/payouts \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"transaction_id": "W-1001",
"type": "qr",
"qr": {
"content": "000201010212…"
},
"quote_id": "6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10",
"description": "Almuerzo"
}
'const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
transaction_id: 'W-1001',
type: 'qr',
qr: {content: '000201010212…'},
quote_id: '6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10',
description: 'Almuerzo'
})
};
fetch('https://examples.staging.rampapay.com/v1/payouts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://examples.staging.rampapay.com/v1/payouts"
payload = {
"transaction_id": "W-1001",
"type": "qr",
"qr": { "content": "000201010212…" },
"quote_id": "6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10",
"description": "Almuerzo"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "po_9Fz3Kd7RwP2mX8cT4nB6vQ1h",
"type": "qr",
"status": "completed",
"transaction_id": "W-1001",
"resolution_id": "qrr_8KqT2mWx5ZbN7cJ4hRvP1sLd",
"quote": {
"id": "6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10",
"source": {
"currency": "USDT",
"amount": "101.500000"
},
"target": {
"currency": "BOB",
"amount": "1000.00"
},
"rate": "9.9500",
"fee": {
"currency": "USDT",
"amount": "1.000000"
},
"expires_at": "2026-09-27T14:05:00.000Z"
},
"source": {
"currency": "USDT",
"amount": "101.500000"
},
"target": {
"currency": "BOB",
"amount": "1000.00"
},
"qr": {
"amount_mode": "closed",
"merchant": {
"name": "Café del Prado",
"bank_code": "1014"
}
},
"error": null,
"completed_at": "2026-09-27T14:02:12.000Z",
"created_at": "2026-09-27T14:02:11.000Z"
}Pay out at an accepted quote
Scope: payouts:write
type says where the money goes, and you send the one object it names: qr — {"content": …}, the QR your end user scanned — or bank_transfer, a Bolivian bank account. bank_transfer is not available yet: it is validated, then answered 422 PAYOUT_TYPE_NOT_AVAILABLE, so you can build against it now. Sending the other type’s object is a 400.
Send it with the quote_id your end user accepted. It is paid at once and the answer says how it ended: completed, debiting exactly the quote’s source.amount; cancelled, rejected or failed with error.code saying why — nothing is debited then; or, rarely, processing while the network’s answer is late — poll GET /payouts/{id} or wait for the webhook; sending the same request again (same transaction_id and body) is always safe. An open-amount QR is paid the quote’s target.amount. When the quote named a resolution_id, the payout carries it too, in its answer and its webhooks.
transaction_id is your own id and the idempotency key. One transaction id is one payment: sending it again with the same body returns the same payment, so retrying after a timeout or a 503 is safe; sending it with a different body is refused. No Idempotency-Key header is needed.
curl --request POST \
--url https://examples.staging.rampapay.com/v1/payouts \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"transaction_id": "W-1001",
"type": "qr",
"qr": {
"content": "000201010212…"
},
"quote_id": "6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10",
"description": "Almuerzo"
}
'const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
transaction_id: 'W-1001',
type: 'qr',
qr: {content: '000201010212…'},
quote_id: '6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10',
description: 'Almuerzo'
})
};
fetch('https://examples.staging.rampapay.com/v1/payouts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://examples.staging.rampapay.com/v1/payouts"
payload = {
"transaction_id": "W-1001",
"type": "qr",
"qr": { "content": "000201010212…" },
"quote_id": "6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10",
"description": "Almuerzo"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "po_9Fz3Kd7RwP2mX8cT4nB6vQ1h",
"type": "qr",
"status": "completed",
"transaction_id": "W-1001",
"resolution_id": "qrr_8KqT2mWx5ZbN7cJ4hRvP1sLd",
"quote": {
"id": "6f0c2a8e-4b7d-4f1e-9a51-3c2d8e7b9a10",
"source": {
"currency": "USDT",
"amount": "101.500000"
},
"target": {
"currency": "BOB",
"amount": "1000.00"
},
"rate": "9.9500",
"fee": {
"currency": "USDT",
"amount": "1.000000"
},
"expires_at": "2026-09-27T14:05:00.000Z"
},
"source": {
"currency": "USDT",
"amount": "101.500000"
},
"target": {
"currency": "BOB",
"amount": "1000.00"
},
"qr": {
"amount_mode": "closed",
"merchant": {
"name": "Café del Prado",
"bank_code": "1014"
}
},
"error": null,
"completed_at": "2026-09-27T14:02:12.000Z",
"created_at": "2026-09-27T14:02:11.000Z"
}Authorizations
On the example server, any key that starts with rpk_mock_, e.g. rpk_mock_yourname. Never your real key.
Body
string, 1–100 of A–Z a–z 0–9 . _ : -. Required. Your id for this payout, and its idempotency key.
qr | bank_transfer. Required. Where the money goes; send the object of the same name, and only that one.
qr, bank_transfer uuid. Required. The id of the firm quote the end user accepted, for the amount the destination receives, before it expires.
uuid Show child attributes
Show child attributes
Show child attributes
Show child attributes
string, ≤ 200. Sent with the payment when the QR carries no description of its own.
Response
Paid · Not paid — QR for another amount
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes