Payments & customers
docs.api.pages.payment-requests
Ask a customer for a payment and get back, in one response, every way they can pay: card link, a SPEI CLABE for that charge, a cash voucher and whether they have an active direct debit. Built for AI agents: they do not pick a gateway or method.
Creating a request
Recaudo creates a payment link for the customer and builds every payment method available to your business. If one is not available (for example, cash is not set up) it comes back as null and the rest still work. It goes through the agent money limits: above the limit it returns 202.
curl -X POST https://recaudo.app/api/v1/payment-requests \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: abono-nov-7f3a" \
-H "Content-Type: application/json" \
-d '{"customer": "8c2f…", "amount": 1500.00, "description": "Abono de noviembre"}'
{
"object": "payment_request",
"id": "3f0a9c7e-\u2026",
"status": "pending",
"amount": 1500,
"amount_paid": 0,
"amount_remaining": 1500,
"currency": "MXN",
"url": "https://recaudo.app/pay/\u2026",
"options": {
"card": {
"url": "https://recaudo.app/pay/\u2026"
},
"spei": {
"clabe": "646180111800000000",
"bank": "STP",
"concept": "ord-\u2026",
"amount": 1500,
"expires_at": "2026-11-09T23:59:00-06:00"
},
"cash": {
"reference": "9300 0000 0000 00",
"url": "\u2026",
"amount": 1500,
"expires_at": "\u2026"
},
"direct_debit": null
},
"expires_at": "2026-11-14T12:00:00-06:00"
}
Parameters
customerCustomer UUID. Required.amountAmount in decimals. Required.descriptionWhat the customer sees. Required.invoice_idInvoice being paid; the payment is applied to it.allow_partialAllow partial payments.methodsWhat to build: card, spei, cash. Defaults to all.expires_atExpiry. Defaults to 7 days.
Note
Waiting for the payment
GET /v1/payment-requests/{id}/wait waits up to 25 seconds for the status or amount paid to change and returns the status with waited_seconds. If it is still pending, call again. The MCP tool is wait_for_payment.
https://recaudo.app/api/v1/payment-requests/{id}/wait?timeout=25
Statuses
pending, partially_paid, paid, expired, canceled.
Webhooks
payment_request.paid when the total is covered, payment_request.partially_paid on each partial payment and payment_request.expired on expiry. The body is the same payment_request object. The link events (payment_link.*) keep arriving too.