Endpoints

POST /api/v1/payments

Direct-charge flow — devolvemos el paymentFormUrl del provider upstream para que vos embebas / redirijas.

Dos flujos, dos endpoints — elegí uno:
Direct charge (este endpoint) — devolvemos paymentFormUrl del provider upstream (ej. secure-int.key2pay.io/checkout?token=…). Vos redirigís o embebés ese URL. Te da más control sobre la UI.
Hosted checkout POST /api/v1/checkout/sessions — devolvemos NUESTRO checkoutUrl y manejamos toda la UI por método (QR, CLABE, redirect, voucher). Vos solo redirigís. 1 línea de integración.
POST/api/v1/paymentssecret key

Inicia un cobro server-to-server. El shop se identifica vía el Bearer token (POST /api/v1/auth/token). Pasá `paymentMethodId` con el id 4-dígitos que devuelve GET /api/v1/payment-methods. Cada retailer / banco / método nativo tiene su propio id único (ej. 1001 → SPEI, 1002 → OXXO, 1003 → Walmart, 1004 → 7-Eleven, 1005 → BBVA, 1006 → Scotiabank) y el cascade rutea exactamente a ese upstream. El mismo `paymentMethodId` vuelve en la respuesta y queda queryable en GET /api/v1/payments. La respuesta incluye `paymentFormUrl` (URL del provider upstream — vos redirigís ahí o embebés). Si preferís nuestra UI hosted, usá POST /api/v1/checkout/sessions que devuelve `checkoutUrl` propio. La cripto de settlement, la wallet de destino y el nivel de KYC se derivan internamente del config del merchant — no se envían en el body. Nota: el path legacy `POST /api/v1/transactions` funciona exactamente igual; usa el que prefieras.

Body parameters
  • amountnumberrequired
    Monto en USD. > 0, máx 100,000.
  • paymentMethodIdstringrequired
    El código 4-dígitos de GET /api/v1/payment-methods. Cada retailer / banco / método nativo tiene su propio código único (ej. "1001" SPEI, "1002" OXXO, "1003" Walmart, "1005" BBVA). Los códigos son NUESTROS — asignados por la plataforma y estables aun cuando rotamos providers upstream. Este es el campo recomendado y el único que garantiza ruteo determinístico al rail específico.
  • paymentMethodstring
    Legacy. Slug ambiguo (card · debit · spei · pix · oxxo · voucher · bank_transfer · …). Se acepta solo como fallback cuando no se manda `paymentMethodId`. El cascade elige cualquier provider del bucket de slug + país, sin garantizar un retailer específico — por ejemplo `voucher` + MEX podría rutear Walmart o 7-Eleven. Usa `paymentMethodId` en código nuevo.
  • countrystring
    País del pagador. Acepta ISO-3 (BRA, MEX, COL, ARG, CHL, PER, …) o ISO-2 (BR, MX, CO, AR, CL, PE, …) indistintamente — normalizamos a ISO-3 internamente. Default: USA.
  • userEmailstring
    Email del pagador, máx 254 chars.
  • userNamestring
    Nombre del pagador, máx 120 chars.
  • userIpstring
    IP del pagador (también la inferimos del request).
  • merchantOrderIdstring
    Your own reference id (any string ≤120 chars). Stored on the transaction and queryable via GET /transactions?merchantOrderId=… for disaster-recovery lookup.
  • hostedCheckoutboolean
    When true, the response includes `checkoutUrl` — a Key2Pay-hosted page that renders QR / CLABE / redirect UI per the selected method. Redirect the customer there and listen for the webhook.
  • returnUrlstring
    Where the hosted checkout sends the customer once they finish (or click Return). Only used when `hostedCheckout: true`.
  • merchantIdstring
    Solo si tu token cubre múltiples merchants; default: el del shop.
  • shopIdstring
    Idem para múltiples shops.
Request
curl https://sandbox.key2pays.com/api/v1/payments \
  -H "Authorization: Bearer sk_test_51N8mP...exampleK3Y" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50,
    "paymentMethodId": "1001",
    "country": "MEX",
    "userEmail": "test@test.com",
    "merchantOrderId": "ORD-12345",
    "hostedCheckout": true,
    "returnUrl": "https://your-site.com/return"
  }'
Response
{
  "transactionId": "TXN-MVZQXW7B-A4F2",
  "status": "pending",
  "amount": 50.00,
  "amountLocal": 882.17,
  "currencyLocal": "MXN",
  "fxRate": 17.64,
  "paymentMethodId": "1001",
  "fees": {
    "platform": 1.45,
    "provider": 1.50,
    "network": 1.50,
    "total": 4.45
  },
  "settlement": {
    "type": "delayed",
    "delay": "48h",
    "reserve": 5,
    "status": "pending"
  },
  "paymentFormUrl": "https://secure-int.key2pay.io/checkout?token=…",
  "checkoutUrl": "https://sandbox.key2pays.com/c/TXN-MVZQXW7B-A4F2?returnUrl=https%3A%2F%2Fyour-site.com%2Freturn",
  "paymentData": {},
  "expiresAt": "2026-05-12T16:00:00.000Z"
}
No se exponen: la cripto de settlement, la wallet de destino, el provider que procesó la carga, el txId del provider externo, ni la traza interna del cascade. Esos detalles son internos — si el cascade cambia mañana, tu integración no se entera.
Formato de country: aceptamos ISO-2 ("MX", "BR","CO", …) e ISO-3 ("MEX", "BRA","COL", …) indistintamente. Internamente normalizamos a ISO-3 antes de rutear, así que cualquiera de los dos formatos funciona igual. Si pasás paymentMethodId sin country, el país se infiere del id 4-dígitos (cada uno está atado a un país específico).
Try itPOST/api/v1/paymentssandbox
Request body
amountintegerRequired
paymentMethodIdstringRequired
countryenum
userEmailstring
userNamestring
hostedCheckoutstring
Live snippet
curl -X POST "https://sandbox.key2pays.com/api/v1/api/v1/payments" \
  -H "Authorization: Bearer sk_test_…YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 50,
  "paymentMethodId": "1001",
  "country": "MEX",
  "userEmail": "test@test.com",
  "userName": "Cliente de Prueba",
  "hostedCheckout": "false"
}'
Snippet updates as you edit the form. Sandbox responses are deterministic.