Crear Solicitud de Pago
Crea una nueva Solicitud de Pago para recibir pagos.
Endpoint
Sección titulada «Endpoint»POST /v1/payment-linksAutenticación
Sección titulada «Autenticación»Requiere API Key con el ability payment_links:create.
Cuerpo de la Solicitud
Sección titulada «Cuerpo de la Solicitud»{ "amount": 100.0, "currency": "COP", "description": "Factura #1234 - Suscripción mensual", "amount_type": "receive", "customer_paid_fee": false, "webhook_url": "https://tu-servidor.com/webhooks/orden/1234", "success_url": "https://tu-servidor.com/pago-exitoso"}Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
amount | number | Sí | Monto del pago (mínimo 1). La moneda depende de amount_type — ver abajo |
currency | string | Sí | Moneda del comprador. Valores: ARS, BRL, COP, CLP, MXN, BOB, USD — USD funciona distinto, ver Pagos en USD |
description | string | Sí | Descripción del pago (máximo 255 caracteres) |
amount_type | string | No | Interpretación del monto. Valores: receive (default), charge |
customer_paid_fee | boolean | No | Si es true, la comisión se suma al monto que paga el comprador. Default: false |
source | string | No | Origen de la solicitud. Valores: integration (default), embedded_checkout, woocommerce |
close_on_complete | boolean | No | Si es true, el checkout se cierra automáticamente al completar el pago. Default: false |
webhook_url | string | No | URL para recibir notificaciones de esta solicitud (máximo 500 caracteres) |
success_url | string | No | URL de redirección después de completar el pago exitosamente (máximo 500 caracteres) |
Monto y comisión
Sección titulada «Monto y comisión»Dos parámetros determinan cuánto paga el comprador y cuánto recibes tú. Conviene leerlos juntos, porque el resultado depende de la combinación:
amount_typedefine en qué moneda está expresadoamounty quién absorbe el riesgo cambiario.customer_paid_feedefine quién paga la comisión de la transacción.
En qué moneda va amount
Sección titulada «En qué moneda va amount»| Valor | amount se expresa en | Riesgo cambiario |
|---|---|---|
receive (default) | La moneda de tu wallet | Lo absorbe la plataforma. El comprador paga el equivalente en su moneda local |
charge | La moneda del comprador (currency) | El comprador paga exactamente el monto que indicaste |
Quién paga la comisión
Sección titulada «Quién paga la comisión»| Valor | Descripción |
|---|---|
false (default) | La comisión la absorbe el comercio: se descuenta de los fondos que recibes |
true | La comisión se suma al monto que paga el comprador |
Combinaciones
Sección titulada «Combinaciones»Esta tabla describe el caso con conversión, que es donde amount_type decide algo. Si el comprador paga en la misma moneda de tu wallet — siempre con currency: "USD" — solo aplican las dos filas de customer_paid_fee, y “equivalente a amount” es simplemente amount.
amount_type | customer_paid_fee | Paga el comprador | Recibes tú |
|---|---|---|---|
receive | false (default) | Equivalente a amount en su moneda local | amount − comisión |
receive | true | Equivalente a amount + comisión | amount completo |
charge | false (default) | amount exacto | Equivalente a amount − comisión |
charge | true | amount + comisión | Equivalente a amount |
Ejemplos de uso
Sección titulada «Ejemplos de uso»Los cuatro ejemplos asumen un wallet en CLP y un comprador que paga en COP.
1. receive con el default (customer_paid_fee: false):
{ "amount": 100, "currency": "COP", "description": "Reserva de hotel", "amount_type": "receive"}→ El comprador paga el equivalente a 100 CLP en COP (~150,000 COP). Tú recibes 100 CLP menos la comisión.
2. receive con customer_paid_fee: true:
{ "amount": 100, "currency": "COP", "description": "Reserva de hotel", "amount_type": "receive", "customer_paid_fee": true}→ El comprador paga ~150,000 COP más la comisión. Tú recibes los 100 CLP completos.
3. charge con el default (customer_paid_fee: false):
{ "amount": 150000, "currency": "COP", "description": "Reserva de hotel", "amount_type": "charge"}→ El comprador paga exactamente 150,000 COP. Tú recibes el equivalente (~100 CLP) menos la comisión.
4. charge con customer_paid_fee: true:
{ "amount": 150000, "currency": "COP", "description": "Reserva de hotel", "amount_type": "charge", "customer_paid_fee": true}→ Si la comisión es de 3,000 COP, el comprador paga 153,000 COP. Tú recibes el equivalente a 150,000 COP.
Pagos en USD
Sección titulada «Pagos en USD»currency: "USD" cobra por débito bancario en Estados Unidos, no por los métodos locales del resto de monedas. El cuerpo de la solicitud es el mismo — no hay ningún campo nuevo:
{ "amount": 100, "currency": "USD", "description": "Invoice #1234"}La moneda del wallet la determina currency: pidiendo USD, los fondos se liquidan en tu USD Bank Account. No tienes que elegir proveedor ni wallet en ningún momento.
El ciclo es distinto: no es inmediato
Sección titulada «El ciclo es distinto: no es inmediato»Un débito bancario tarda días hábiles en liquidarse. Eso cambia dos cosas que probablemente ya tengas implementadas para las monedas locales:
| Monedas locales | USD | |
|---|---|---|
| Estados posibles | active → completed | active → in_transit → completed, y returned |
Cuándo llega payment.completed | Al momento de pagar | Al liquidar el débito, días después |
in_transitsignifica que el comprador ya autorizó el cobro y el débito está en camino. No es un fallo ni un pago confirmado: aún no hay dinero acreditado.returnedsignifica que el banco del comprador revirtió el débito después de haberse liquidado. Es el único estado en el que un pago que ya diste por bueno deja de serlo.
Ejemplo de Solicitud
Sección titulada «Ejemplo de Solicitud»curl -X POST "https://api.aloha.co/api/external/v1/payment-links" \ -H "X-API-KEY: tu_api_key_aqui" \ -H "Content-Type: application/json" \ -d '{ "amount": 100.00, "currency": "COP", "description": "Factura #1234 - Suscripción mensual", "amount_type": "receive", "success_url": "https://tu-servidor.com/pago-exitoso" }'const response = await fetch( 'https://api.aloha.co/api/external/v1/payment-links', { method: 'POST', headers: { 'X-API-KEY': 'tu_api_key_aqui', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 100.00, currency: 'COP', description: 'Factura #1234 - Suscripción mensual', amount_type: 'receive', success_url: 'https://tu-servidor.com/pago-exitoso' }) });const data = await response.json();
console.log('Payment Link URL:', data.data.url);import requests
headers = { 'X-API-KEY': 'tu_api_key_aqui', 'Content-Type': 'application/json'}
payload = { 'amount': 100.00, 'currency': 'COP', 'description': 'Factura #1234 - Suscripción mensual', 'amount_type': 'receive', 'success_url': 'https://tu-servidor.com/pago-exitoso'}
response = requests.post( 'https://api.aloha.co/api/external/v1/payment-links', headers=headers, json=payload)data = response.json()
print('Payment Link URL:', data['data']['url'])<?php$ch = curl_init();
$payload = json_encode([ 'amount' => 100.00, 'currency' => 'COP', 'description' => 'Factura #1234 - Suscripción mensual', 'amount_type' => 'receive', 'success_url' => 'https://tu-servidor.com/pago-exitoso']);
curl_setopt_array($ch, [ CURLOPT_URL => 'https://api.aloha.co/api/external/v1/payment-links', CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => [ 'X-API-KEY: tu_api_key_aqui', 'Content-Type: application/json' ]]);
$response = curl_exec($ch);$data = json_decode($response, true);
echo 'Payment Link URL: ' . $data['data']['url'];Respuesta Exitosa (201 Created)
Sección titulada «Respuesta Exitosa (201 Created)»{ "success": true, "message": "Payment link created successfully", "data": { "id": "9d8f7a6b-5c4d-3e2f-1a0b-9c8d7e6f5a4b", "url": "https://checkout.aloha.co/s/9d8f7a6b-5c4d-3e2f-1a0b-9c8d7e6f5a4b", "expires_at": "2025-12-10T10:30:00.000000Z" }}Campos de Respuesta
Sección titulada «Campos de Respuesta»| Campo | Tipo | Descripción |
|---|---|---|
id | string (UUID) | Identificador único de la Solicitud de Pago |
url | string | URL del checkout para compartir con el cliente |
expires_at | string | Fecha de expiración (ISO 8601) |
Errores Posibles
Sección titulada «Errores Posibles»Error de Validación (422)
Sección titulada «Error de Validación (422)»{ "success": false, "code": "VALIDATION_FAILED", "message": "Validation failed", "errors": { "amount": ["The amount field is required."], "currency": ["The currency must be 3 characters."], "description": ["The description field is required."] }}API Key Inválida (401)
Sección titulada «API Key Inválida (401)»{ "success": false, "code": "INVALID_API_KEY", "message": "Invalid API key configuration"}Wallet No Encontrado (422)
Sección titulada «Wallet No Encontrado (422)»{ "success": false, "code": "WALLET_NOT_FOUND", "message": "No virtual wallet configured for this account"}Pagos en USD No Habilitados (422)
Sección titulada «Pagos en USD No Habilitados (422)»{ "success": false, "code": "USD_ACCOUNT_NOT_ENABLED", "message": "USD payment links are not enabled for this account."}Tabla de Errores
Sección titulada «Tabla de Errores»| Código HTTP | Código de Error | Descripción |
|---|---|---|
| 401 | INVALID_API_KEY | API Key inválida o expirada |
| 401 | missing_api_key | No se proporcionó API Key |
| 403 | insufficient_scope | La API Key no tiene el ability payment_links:create |
| 422 | VALIDATION_FAILED | Error de validación en los parámetros |
| 422 | WALLET_NOT_FOUND | No hay wallet virtual configurado |
| 422 | USD_ACCOUNT_NOT_ENABLED | Se pidió currency: "USD" y la cuenta no tiene los pagos en USD habilitados |