Documentación de la API
Guía completa para integrar Recaudo en tus aplicaciones
¿Integrando con un agente de IA?
Si usas Claude Code, Cursor, Codex, Windsurf u otro asistente de código, tenemos instrucciones listas para copiar y pegar.
Autenticación
La API de Recaudo utiliza API keys para autenticar las peticiones. Crea una cuenta para obtener tus API keys.
Importante: Nunca expongas tu Secret Key en codigo del lado del cliente. Usa la Public Key para operaciones frontend.
Tipos de API Keys
| Tipo | Prefijo | Uso |
|---|---|---|
| Public Key (Live) | pk_live_ |
Frontend, checkout forms |
| Secret Key (Live) | sk_live_ |
Backend, operaciones sensibles |
| Public Key (Test) | pk_test_ |
Desarrollo frontend |
| Secret Key (Test) | sk_test_ |
Desarrollo backend |
Autenticacion via Header
Incluye tu API key en el header Authorization como Bearer token:
curl https://recaudo.app/api/v1/customers \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json"
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://recaudo.app/api/v1/customers', [
'headers' => [
'Authorization' => 'Bearer sk_live_tu_secret_key',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
]
]);
$data = json_decode($response->getBody(), true);
const response = await fetch('https://recaudo.app/api/v1/customers', {
method: 'GET',
headers: {
'Authorization': 'Bearer sk_live_tu_secret_key',
'Content-Type': 'application/json',
}
});
const data = await response.json();
import requests
response = requests.get(
'https://recaudo.app/api/v1/customers',
headers={
'Authorization': 'Bearer sk_live_tu_secret_key',
'Content-Type': 'application/json',
}
)
data = response.json()
MCP Server
Integra Recaudo con asistentes de IA
Recaudo incluye un servidor MCP (Model Context Protocol) que permite a asistentes de IA como Claude Desktop, Cursor, Windsurf, Claude Code y otros clientes MCP interactuar directamente con tu cuenta: gestionar clientes, crear facturas, cobrar, enviar WhatsApp, CRM, automatizaciones y más.
Requisitos
- Node.js 18 o superior
- Una Secret Key de la API (
sk_live_osk_test_)
Configuración en Claude Desktop
Edita el archivo claude_desktop_config.json
(Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
| Windows: %APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"recaudo": {
"command": "npx",
"args": ["-y", "@recaudo/mcp-server"],
"env": {
"RECAUDO_API_KEY": "sk_live_tu_secret_key"
}
}
}
}
sk_live_tu_secret_key con tu Secret Key. Puedes generarla en
API Keys.
Reinicia Claude Desktop después de guardar la configuración.Configuración en Claude Code
claude mcp add recaudo -e RECAUDO_API_KEY=sk_live_tu_secret_key -- npx -y @recaudo/mcp-server
Configuración en Cursor / Windsurf
Crea el archivo .cursor/mcp.json en la raíz de tu proyecto:
{
"mcpServers": {
"recaudo": {
"command": "npx",
"args": ["-y", "@recaudo/mcp-server"],
"env": {
"RECAUDO_API_KEY": "sk_live_tu_secret_key"
}
}
}
}
Herramientas disponibles
El MCP Server expone 110 herramientas organizadas en 20 módulos:
| Grupo | Herramientas | Descripción |
|---|---|---|
| Clientes | 7 | CRUD, métodos de pago, suscripciones |
| Facturas | 9 | CRUD, parcialidades, moratorios |
| Links de Pago | 5 | Crear, cancelar, ver pagos |
| Cargos | 3 | Cobros directos, reembolsos |
| Productos | 10 | Catálogo: categorías y productos con inventario |
| Pedidos | 8 | Crear, enviar, entregar, completar pedidos |
| Conversaciones | 7 | WhatsApp, Messenger, Instagram: mensajes y templates |
| Planes | 3 | Listar y crear planes de suscripción |
| Suscripciones | 7 | Ciclo completo: crear, pausar, cancelar |
| Flujos | 6 | Desplegar flujos conversacionales |
| Webhooks | 4 | Configurar y probar webhooks |
Ejemplo de uso
Una vez configurado, puedes hablar con tu asistente de IA en lenguaje natural:
Usuario: Lista mis clientes con suscripción activa
Claude: Encontré 24 clientes con suscripción activa...
Usuario: Crea un link de pago de $500 para Juan Pérez
Claude: Link creado: https://recaudo.app/pay/abc123...
Usuario: ¿Cuántas facturas pendientes tengo?
Claude: Tienes 12 facturas pendientes por un total de $45,300.00...
El MCP Server usa tu Secret Key para autenticarse. Todas las operaciones respetan los mismos permisos y límites que la API REST.
Guía para Agentes de IA
Instrucciones para Claude Code, Codex, Cursor, Windsurf y otros asistentes de código
Si estás delegando la integración de Recaudo a un agente de IA (Claude Code, OpenAI Codex, Cursor, Windsurf, GitHub Copilot, etc.), copia el siguiente bloque de instrucciones y pégalo en tu prompt o archivo de contexto del proyecto (CLAUDE.md, .cursorrules, AGENTS.md, etc.). El agente tendrá todo lo necesario para integrar correctamente.
# Integración con Recaudo — Guía para Agentes de IA
## Qué es Recaudo
Recaudo es una plataforma de orquestación de pagos con API REST. Permite crear links de pago,
cobrar con tarjeta, gestionar clientes, suscripciones, facturas, WhatsApp y más.
## Base URL
```
https://recaudo.app/api/v1
```
## Autenticación
Todas las peticiones requieren el header:
```
Authorization: Bearer {SECRET_KEY}
```
La Secret Key se obtiene desde el panel en Configuración → API Keys.
NUNCA exponer la Secret Key en código frontend.
## Montos
TODOS los montos son en DECIMALES (100.00 = $100 pesos). NO usar centavos.
## Endpoints principales
### Clientes
- `GET /customers` — Listar clientes (paginado, ?search=, ?page=)
- `POST /customers` — Crear cliente (name, email, phone?, city?, notes?)
- `GET /customers/{id}` — Ver cliente
- `PUT /customers/{id}` — Actualizar cliente
- `DELETE /customers/{id}` — Eliminar cliente
### Links de Pago
- `GET /payment-links` — Listar links
- `POST /payment-links` — Crear link (title, amount, currency?, description?, expiration_days?)
- `GET /payment-links/{id}` — Ver link
- `PUT /payment-links/{id}` — Actualizar link
- `DELETE /payment-links/{id}` — Eliminar link
### Cargos (cobro directo con tarjeta tokenizada)
- `POST /charges` — Crear cargo (customer_id, amount, currency, payment_method_token, description?)
- `GET /charges/{id}` — Ver cargo
### Tokenización (guardar tarjeta)
- `POST /customers/{id}/payment-methods` — Tokenizar tarjeta (card_number, exp_month, exp_year, cvv, holder_name)
- `GET /customers/{id}/payment-methods` — Listar métodos de pago
- `DELETE /customers/{id}/payment-methods/{pm_id}` — Eliminar método
### Suscripciones
- `GET /subscriptions` — Listar suscripciones
- `POST /subscriptions` — Crear (customer_id, plan_name, amount, currency, interval: monthly|yearly, payment_method_token?)
- `GET /subscriptions/{id}` — Ver suscripción
- `POST /subscriptions/{id}/cancel` — Cancelar
- `POST /subscriptions/{id}/pause` — Pausar
- `POST /subscriptions/{id}/resume` — Reanudar
### Facturas
- `GET /invoices` — Listar facturas
- `POST /invoices` — Crear factura (customer_id, items[{description, quantity, unit_price}], due_date?, notes?)
- `GET /invoices/{id}` — Ver factura
- `POST /invoices/{id}/send` — Enviar por email
- `POST /invoices/{id}/mark-paid` — Marcar como pagada
### Webhooks
- `GET /webhook-endpoints` — Listar endpoints
- `POST /webhook-endpoints` — Crear endpoint (url, events[], description)
- `GET /webhook-endpoints/{id}` — Ver detalle con secret
- `PUT /webhook-endpoints/{id}` — Actualizar url, eventos, estado
- `DELETE /webhook-endpoints/{id}` — Eliminar endpoint
- `POST /webhook-endpoints/{id}/test` — Enviar evento de prueba
- `POST /webhook-endpoints/{id}/rotate-secret` — Rotar secret
- `GET /webhook-endpoints/{id}/deliveries` — Ver entregas
- `POST /webhook-endpoints/{id}/deliveries/{delivery_id}/resend` — Reenviar
### Conversaciones (WhatsApp)
- `GET /conversations` — Listar conversaciones
- `GET /conversations/{id}` — Ver conversación con mensajes
- `POST /conversations/{id}/messages` — Enviar mensaje (body)
- `POST /conversations/{id}/close` — Cerrar conversación
### Templates de WhatsApp (HSM)
- `GET /whatsapp-templates` — Listar templates aprobados
- `POST /whatsapp-templates/{id}/send` — Enviar template (customer_id, parameters?)
### Seguimientos (Cobranza)
- `GET /follow-ups` — Listar seguimientos (?status=pending|completed|overdue)
- `POST /follow-ups` — Crear (customer_id, title, description?, due_date, type: call|email|whatsapp|visit|other)
- `PUT /follow-ups/{id}` — Actualizar
- `POST /follow-ups/{id}/complete` — Marcar completado
### Productos (Tienda)
- `GET /products` — Listar productos
- `POST /products` — Crear (name, price, description?, sku?, stock?)
- `PUT /products/{id}` — Actualizar
- `DELETE /products/{id}` — Eliminar
### Pedidos (Tienda)
- `GET /orders` — Listar pedidos
- `GET /orders/{id}` — Ver pedido
- `PUT /orders/{id}/status` — Cambiar status (status: pending|processing|shipped|delivered|cancelled)
### Equipo
- `GET /team` — Listar miembros del equipo
### Fuentes de Clientes
- `GET /customer-sources` — Listar fuentes de clientes
## Paginación
Todas las listas devuelven paginación:
```json
{
"data": [...],
"meta": { "current_page": 1, "last_page": 5, "per_page": 25, "total": 112 },
"links": { "next": "...?page=2", "prev": null }
}
```
Parámetros: `?page=1&per_page=25` (máximo 100).
## Errores
```json
{
"error": { "code": "validation_error", "message": "...", "details": {...} }
}
```
Códigos HTTP: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, 422 Unprocessable, 429 Rate Limited, 500 Server Error.
## MCP Server (recomendado para Claude Code)
Si usas Claude Code, conecta el MCP server para acceso directo:
```bash
claude mcp add recaudo -e RECAUDO_API_KEY=sk_live_tu_key -- npx -y @recaudo/mcp-server
```
Esto te da 139 herramientas nativas sin necesidad de hacer requests HTTP manuales.
## Ejemplo rápido: crear cliente + link de pago
```bash
# 1. Crear cliente
curl -X POST https://recaudo.app/api/v1/customers \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"name": "Juan Pérez", "email": "juan@email.com", "phone": "+5255123456"}'
# 2. Crear link de pago
curl -X POST https://recaudo.app/api/v1/payment-links \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"title": "Consultoría", "amount": 1500.00, "currency": "MXN"}'
```
## Notas para el agente
- Siempre validar que la respuesta sea 2xx antes de proceder.
- Los IDs son UUIDs (formato: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
- El rate limit es 60 requests/minuto por API key.
- Para desarrollo, usa API keys de prueba (prefijo sk_test_).
- La moneda por defecto es MXN si no se especifica.
Claude Code
Pega las instrucciones en CLAUDE.md en la raíz de tu proyecto.
Cursor / Windsurf
Pega en .cursorrules o .windsurfrules en la raíz.
Codex / Copilot
Pega en AGENTS.md o inclúyelo en el prompt del sistema.
Tip: Si usas Claude Code, la mejor opción es conectar el MCP Server directamente.
Así el agente tiene acceso a 139 herramientas nativas sin necesidad de copiar estas instrucciones.
Solo ejecuta claude mcp add recaudo -e RECAUDO_API_KEY=sk_live_... -- npx -y @recaudo/mcp-server
Manejo de Errores
La API utiliza codigos de estado HTTP convencionales para indicar el exito o fallo de una peticion.
| Codigo | Descripcion |
|---|---|
| 200 | Peticion exitosa |
| 201 | Recurso creado exitosamente |
| 400 | Peticion invalida - revisa los parametros |
| 401 | No autorizado - API key invalida o faltante |
| 403 | Prohibido - no tienes permisos para este recurso |
| 404 | Recurso no encontrado |
| 422 | Error de validacion |
| 429 | Rate limit excedido |
| 500 | Error interno del servidor |
Formato de Error
{
"error": {
"type": "validation_error",
"code": "invalid_parameter",
"message": "El campo email es requerido",
"param": "email",
"doc_url": "https://docs.recaudo.app/errors/invalid_parameter"
}
}
Paginacion
Los endpoints que retornan listas de objetos soportan paginacion basada en cursor.
Parametros
| Parametro | Tipo | Descripcion |
|---|---|---|
limit |
integer | Numero de resultados por pagina (default: 10, max: 100) |
starting_after |
string | ID del ultimo objeto de la pagina anterior |
ending_before |
string | ID del primer objeto de la pagina siguiente (paginacion hacia atras) |
Ejemplo de Respuesta
{
"object": "list",
"data": [...],
"has_more": true,
"total_count": 150
}
Clientes
Los clientes representan a tus usuarios finales. Puedes asociarles metodos de pago, suscripciones y realizar cargos.
/v1/customers
Crear Cliente
Crea un nuevo cliente en tu cuenta.
Parametros
| Parametro | Tipo | Requerido | Descripcion |
|---|---|---|---|
email |
string | Sí | Email del cliente |
name |
string | Sí | Nombre completo |
phone |
string | No | Teléfono |
external_id |
string | No | ID del cliente en tu sistema |
tax_id |
string | No | Identificación fiscal (RFC) |
address |
string | No | Dirección (calle y número). Requerido para AMEX |
city |
string | No | Ciudad. Requerido para AMEX |
state |
string | No | Estado o provincia. Requerido para AMEX |
postal_code |
string | No | Código postal. Requerido para AMEX |
country |
string | No | Código de país ISO 3166-1 alpha-2 (ej: MX, US, CO). Requerido para AMEX |
metadata |
object | No | Datos adicionales (max 50 keys) |
curl -X POST https://recaudo.app/api/v1/customers \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"email": "cliente@ejemplo.com",
"name": "Juan Pérez",
"phone": "+52 55 1234 5678",
"address": "Av. Reforma 123, Col. Centro",
"city": "Ciudad de México",
"state": "CDMX",
"postal_code": "06600",
"country": "MX",
"tax_id": "XAXX010101000",
"metadata": {
"user_id": "usr_123"
}
}'
$response = $client->post('/api/v1/customers', [
'json' => [
'email' => 'cliente@ejemplo.com',
'name' => 'Juan Pérez',
'phone' => '+52 55 1234 5678',
'address' => 'Av. Reforma 123, Col. Centro',
'city' => 'Ciudad de México',
'state' => 'CDMX',
'postal_code' => '06600',
'country' => 'MX',
'tax_id' => 'XAXX010101000',
'metadata' => ['user_id' => 'usr_123']
]
]);
const customer = await fetch('/api/v1/customers', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_xxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'cliente@ejemplo.com',
name: 'Juan Pérez',
phone: '+52 55 1234 5678',
address: 'Av. Reforma 123, Col. Centro',
city: 'Ciudad de México',
state: 'CDMX',
postal_code: '06600',
country: 'MX',
tax_id: 'XAXX010101000',
metadata: { user_id: 'usr_123' }
})
});
response = requests.post(
'https://recaudo.app/api/v1/customers',
headers={'Authorization': 'Bearer sk_live_xxx'},
json={
'email': 'cliente@ejemplo.com',
'name': 'Juan Pérez',
'phone': '+52 55 1234 5678',
'address': 'Av. Reforma 123, Col. Centro',
'city': 'Ciudad de México',
'state': 'CDMX',
'postal_code': '06600',
'country': 'MX',
'tax_id': 'XAXX010101000',
'metadata': {'user_id': 'usr_123'}
}
)
{
"object": "customer",
"data": {
"id": "cus_a1b2c3d4e5f6",
"email": "cliente@ejemplo.com",
"name": "Juan Pérez",
"phone": "+52 55 1234 5678",
"address": "Av. Reforma 123, Col. Centro",
"city": "Ciudad de México",
"state": "CDMX",
"postal_code": "06600",
"country": "MX",
"tax_id": "XAXX010101000",
"metadata": { "user_id": "usr_123" },
"created_at": "2024-01-15T10:30:00Z"
}
}
/v1/customers
Listar Clientes
Obtiene una lista paginada de todos los clientes.
curl https://recaudo.app/api/v1/customers?limit=10 \
-H "Authorization: Bearer sk_live_xxx"
{
"object": "list",
"data": [
{
"id": "cus_a1b2c3d4e5f6",
"object": "customer",
"email": "cliente@ejemplo.com",
"name": "Juan Perez",
...
}
],
"has_more": true,
"total_count": 150
}
/v1/customers/:id
Obtener Cliente
Obtiene los detalles de un cliente existente.
/v1/customers/:id
Actualizar Cliente
Actualiza los datos de un cliente. Solo se modifican los campos enviados.
/v1/customers/:id
Eliminar Cliente
Elimina un cliente y sus datos asociados. Esta accion no se puede deshacer.
Links de Pago
Los links de pago te permiten cobrar a tus clientes sin necesidad de integracion compleja. Genera un link y compartelo.
/v1/payment-links
Crear Link de Pago
Crea un nuevo link de pago.
Parametros
| Parametro | Tipo | Requerido | Descripcion |
|---|---|---|---|
amount |
number | Si | Monto en decimales (ej: 100.00 = $100.00) |
currency |
string | Si | Codigo ISO (MXN, USD, COP, etc.) |
description |
string | No | Descripcion del cobro |
customer_id |
string | No | ID del cliente a asociar |
expires_at |
timestamp | No | Fecha de expiracion (ISO 8601) |
success_url |
string | No | URL de redireccion tras pago exitoso |
curl -X POST https://recaudo.app/api/v1/payment-links \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 500.00,
"currency": "MXN",
"description": "Pago de servicio mensual",
"customer_id": "cus_a1b2c3d4e5f6",
"success_url": "https://tuapp.com/pago-exitoso",
"metadata": {
"order_id": "ORD-123"
}
}'
$response = $client->post('/api/v1/payment-links', [
'json' => [
'amount' => 500.00,
'currency' => 'MXN',
'description' => 'Pago de servicio mensual',
'customer_id' => 'cus_a1b2c3d4e5f6',
'success_url' => 'https://tuapp.com/pago-exitoso',
'metadata' => [
'order_id' => 'ORD-123'
]
]
]);
const paymentLink = await fetch('/api/v1/payment-links', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_xxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 500.00,
currency: 'MXN',
description: 'Pago de servicio mensual',
customer_id: 'cus_a1b2c3d4e5f6',
success_url: 'https://tuapp.com/pago-exitoso',
metadata: { order_id: 'ORD-123' }
})
});
{
"id": "pl_x1y2z3a4b5c6",
"object": "payment_link",
"url": "https://pay.recaudo.app/pl_x1y2z3a4b5c6",
"amount": 500.00,
"currency": "MXN",
"description": "Pago de servicio mensual",
"status": "pending",
"customer_id": "cus_a1b2c3d4e5f6",
"success_url": "https://tuapp.com/pago-exitoso",
"metadata": {
"order_id": "ORD-123"
},
"expires_at": null,
"created_at": "2024-01-15T10:30:00Z"
}
Otros Endpoints
/v1/payment-links
Listar links de pago
/v1/payment-links/:id
Obtener link
/v1/payment-links/:id
Actualizar link
/v1/payment-links/:id/cancel
Cancelar link
Cargos Directos
Realiza cargos directos a metodos de pago guardados. Ideal para cargos recurrentes o one-click payments.
/v1/charges
Crear Cargo
Realiza un cargo a un metodo de pago guardado.
Parametros
| Parametro | Tipo | Requerido | Descripcion |
|---|---|---|---|
amount |
number | Si | Monto en decimales (ej: 100.00 = $100.00) |
currency |
string | Si | Codigo ISO de moneda |
payment_method |
string | Condicional* | ID del método de pago guardado |
token |
string | Condicional* | Token de tarjeta generado con recaudo.js (tok_xxx para Conekta, pm_xxx para Stripe) |
card |
object | No | Info de tarjeta de recaudo.js: { brand, last4, exp_month, exp_year }. Recomendado para mejor tracking |
customer |
string | Condicional* | ID del cliente (requerido si usa payment_method) |
description |
string | No | Descripcion del cargo |
curl -X POST https://recaudo.app/api/v1/charges \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 250.00,
"currency": "MXN",
"token": "tok_abc123...",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
},
"description": "Cargo por servicio premium"
}'
{
"id": "ch_abc123def456",
"object": "charge",
"amount": 250.00,
"currency": "MXN",
"status": "succeeded",
"customer_id": "cus_a1b2c3d4e5f6",
"payment_method_id": "pm_card_xyz123",
"description": "Cargo por servicio premium",
"payment_intent_id": "pi_789xyz",
"receipt_url": "https://pay.recaudo.app/receipts/ch_abc123",
"created_at": "2024-01-15T10:30:00Z"
}
/v1/charges/:id/refund
Reembolsar Cargo
Realiza un reembolso total o parcial de un cargo.
curl -X POST https://recaudo.app/api/v1/charges/ch_abc123/refund \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 100.00,
"reason": "customer_request"
}'
{
"id": "re_xyz789abc",
"object": "refund",
"amount": 100.00,
"currency": "MXN",
"charge_id": "ch_abc123def456",
"status": "succeeded",
"reason": "customer_request",
"created_at": "2024-01-15T11:00:00Z"
}
Tokenización
Tokeniza tarjetas de forma segura directamente desde tu frontend usando recaudo.js v2. La librería carga automáticamente el SDK del procesador de pagos (Conekta, Stripe) configurado en tu cuenta y tokeniza la tarjeta de manera transparente.
Integración en 4 pasos
Incluir la librería JavaScript
<script src="https://recaudo.app/js/recaudo.min.js"></script>
Inicializar la librería
Inicializa recaudo.js con tu Publishable Key. El método init() carga el SDK del procesador configurado.
// Crear instancia con tu Publishable Key
const recaudo = new Recaudo('pk_live_tu_publishable_key');
// Inicializar (carga el SDK del procesador automáticamente)
await recaudo.init();
// Verificar que está listo
console.log('Gateway:', recaudo.getGateway()); // 'conekta' o 'stripe'
Tokenizar la tarjeta
Los datos de la tarjeta se tokenizan directamente con el procesador de pagos. Nunca pasan por tu servidor.
async function handlePayment() {
try {
const token = await recaudo.createToken({
number: '4242424242424242',
exp_month: 12,
exp_year: 2027,
cvv: '123',
name: 'Juan Pérez',
email: 'juan@example.com',
// Campos opcionales (requeridos para AMEX)
address: 'Av. Reforma 123',
city: 'CDMX',
state: 'CDMX',
postal_code: '06600',
country: 'MX'
});
// token contiene:
// - id: Token del procesador (tok_xxx para Conekta, pm_xxx para Stripe)
// - gateway: 'conekta' o 'stripe'
// - card: { brand, last4, exp_month, exp_year }
// Enviar al backend para procesar
await fetch('/tu-backend/procesar-pago', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: token.id,
card: token.card, // Incluir info de tarjeta para mejor tracking
amount: 100.00
})
});
} catch (error) {
// error.type: 'validation_error', 'gateway_error', 'sdk_error'
console.error('Error:', error.message);
}
}
Procesar el cobro desde tu backend
Usa el token para crear un cargo o una suscripción. Incluye el objeto card para mejor tracking.
curl -X POST https://recaudo.app/api/v1/charges \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"amount": 100.00,
"currency": "MXN",
"token": "tok_abc123...",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
},
"description": "Compra en tienda",
"receipt_email": "cliente@example.com"
}'
curl -X POST https://recaudo.app/api/v1/subscriptions \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"plan": "plan_uuid_here",
"customer": "cus_uuid_here",
"token": "tok_abc123...",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
}
}'
Objeto Token (respuesta de createToken)
{
"id": "tok_2sR5Vx1J5K...", // Token del procesador (tok_xxx Conekta, pm_xxx Stripe)
"gateway": "conekta", // Procesador utilizado
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
},
"created_at": "2024-01-15T10:30:00.000Z"
}
Endpoints de la API
| Método | Endpoint | Descripción |
|---|---|---|
| GET | /v1/tokens/config |
Obtener configuración del procesador (usado por recaudo.js para cargar el SDK correcto) |
| GET | /v1/tokens/public-key |
Obtener clave pública para encriptación (legacy v1) |
| POST | /v1/tokens |
Crear token desde datos encriptados (legacy v1) |
| GET | /v1/tokens/:token |
Obtener información de un token |
| DELETE | /v1/tokens/:token |
Eliminar un token |
Métodos de recaudo.js
| Método | Descripción |
|---|---|
new Recaudo(publishableKey) |
Constructor. Crea una instancia con tu Publishable Key. |
init() |
Carga el SDK del procesador configurado. Debe llamarse antes de createToken(). |
createToken(cardData) |
Tokeniza los datos de la tarjeta con el procesador. |
getGateway() |
Retorna el nombre del procesador ('conekta', 'stripe'). |
isInitialized() |
Retorna true si init() ya fue llamado. |
detectCardBrand(number) |
Detecta la marca de la tarjeta (visa, mastercard, amex, etc). |
Manejo de Errores
Los errores de recaudo.js incluyen un tipo para facilitar su manejo:
try {
await recaudo.init();
const token = await recaudo.createToken(cardData);
} catch (error) {
switch (error.type) {
case 'validation_error':
// Datos de tarjeta inválidos
showError(error.message);
break;
case 'gateway_error':
// Error del procesador (tarjeta rechazada, etc)
showError(error.message);
break;
case 'sdk_error':
// Error cargando el SDK del procesador
showError('Error de conexión. Intenta de nuevo.');
break;
case 'configuration_error':
// Procesador no configurado
showError('Error de configuración.');
break;
default:
showError('Error inesperado.');
}
}
Suscripciones
Las suscripciones te permiten cobrar de forma recurrente a tus clientes. Soportan periodos de prueba, pausas y cambios de plan.
/v1/subscriptions
Crear Suscripción
Crea una nueva suscripción para un cliente. Puedes usar un método de pago almacenado o un token de recaudo.js.
Tokenización: Puedes usar el parámetro token con un token de recaudo.js (tok_xxx) en lugar de payment_method. El token será convertido automáticamente en un método de pago almacenado.
Parámetros
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
customer |
string (uuid) | Sí | ID del cliente |
plan |
string (uuid) | Sí | ID del plan de suscripción |
payment_method |
string (uuid) | No* | ID de método de pago almacenado. Requerido si no hay trial y no se usa token. |
token |
string | No* | Token de recaudo.js (tok_xxx para Conekta, pm_xxx para Stripe). Alternativa a payment_method. |
card |
object | No | Info de tarjeta de recaudo.js: { brand, last4, exp_month, exp_year }. Recomendado para mejor tracking |
trial_days |
integer | No | Días de prueba (0-365) |
amount |
numeric | No | Monto personalizado (override del plan) |
metadata |
object | No | Datos adicionales |
curl -X POST https://recaudo.app/api/v1/subscriptions \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"customer": "550e8400-e29b-41d4-a716-446655440000",
"plan": "660e8400-e29b-41d4-a716-446655440001",
"token": "tok_abc123def456",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
},
"metadata": {
"signup_source": "landing_page"
}
}'
curl -X POST https://recaudo.app/api/v1/subscriptions \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"customer": "550e8400-e29b-41d4-a716-446655440000",
"plan": "660e8400-e29b-41d4-a716-446655440001",
"payment_method": "770e8400-e29b-41d4-a716-446655440002",
"metadata": {
"signup_source": "landing_page"
}
}'
{
"id": "sub_1a2b3c4d5e6f",
"object": "subscription",
"status": "active",
"customer_id": "cus_a1b2c3d4e5f6",
"plan": {
"id": "plan_premium_monthly",
"name": "Premium Mensual",
"amount": 299.00,
"currency": "MXN",
"interval": "month"
},
"current_period_start": "2024-01-15T00:00:00Z",
"current_period_end": "2024-02-15T00:00:00Z",
"trial_end": null,
"cancel_at_period_end": false,
"created_at": "2024-01-15T10:30:00Z"
}
Acciones de Suscripcion
/v1/subscriptions/:id/cancel
Cancelar suscripcion
curl -X POST https://recaudo.app/api/v1/subscriptions/sub_1a2b3c/cancel \
-H "Authorization: Bearer sk_live_xxx" \
-d '{"cancel_at_period_end": true, "reason": "too_expensive"}'
/v1/subscriptions/:id/pause
Pausar suscripcion
curl -X POST https://recaudo.app/api/v1/subscriptions/sub_1a2b3c/pause \
-H "Authorization: Bearer sk_live_xxx"
/v1/subscriptions/:id/resume
Reanudar suscripcion
curl -X POST https://recaudo.app/api/v1/subscriptions/sub_1a2b3c/resume \
-H "Authorization: Bearer sk_live_xxx"
Facturas
Las facturas permiten gestionar cobros con soporte completo para parcialidades (pagos en cuotas), políticas de moratorios y seguimiento detallado de pagos. Ideal para colegiaturas, créditos y servicios recurrentes.
Endpoints Disponibles
/v1/invoices
Listar facturas
/v1/invoices
Crear factura (con o sin parcialidades)
/v1/invoices/:id
Obtener factura
/v1/invoices/:id
Actualizar factura
/v1/invoices/:id
Eliminar factura
/v1/invoices/:id/pay
Marcar como pagada
/v1/invoices/:id/void
Anular factura
/v1/invoices/:id/installments
Listar parcialidades
/v1/invoices/:id/installments/:installment_id
Actualizar parcialidad
Crear Factura
Crea una factura con items y opcionalmente configura parcialidades automáticas o manuales.
curl -X POST https://recaudo.app/api/v1/invoices \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_abc123",
"document_date": "2024-01-15",
"items": [
{
"description": "Colegiatura Enero 2024",
"quantity": 1,
"unit_price": 5000.00
}
],
"has_installments": true,
"installment_count": 3,
"installment_frequency": "monthly",
"first_installment_due_date": "2024-01-20"
}'
$response = $client->post('https://recaudo.app/api/v1/invoices', [
'headers' => [
'Authorization' => 'Bearer sk_live_tu_secret_key',
'Content-Type' => 'application/json',
],
'json' => [
'customer_id' => 'cus_abc123',
'document_date' => '2024-01-15',
'items' => [
[
'description' => 'Colegiatura Enero 2024',
'quantity' => 1,
'unit_price' => 5000.00,
]
],
'has_installments' => true,
'installment_count' => 3,
'installment_frequency' => 'monthly',
'first_installment_due_date' => '2024-01-20',
]
]);
const response = await fetch('https://recaudo.app/api/v1/invoices', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_tu_secret_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer_id: 'cus_abc123',
document_date: '2024-01-15',
items: [
{
description: 'Colegiatura Enero 2024',
quantity: 1,
unit_price: 5000.00
}
],
has_installments: true,
installment_count: 3,
installment_frequency: 'monthly',
first_installment_due_date: '2024-01-20'
})
});
response = requests.post(
'https://recaudo.app/api/v1/invoices',
headers={
'Authorization': 'Bearer sk_live_tu_secret_key',
'Content-Type': 'application/json',
},
json={
'customer_id': 'cus_abc123',
'document_date': '2024-01-15',
'items': [
{
'description': 'Colegiatura Enero 2024',
'quantity': 1,
'unit_price': 5000.00
}
],
'has_installments': True,
'installment_count': 3,
'installment_frequency': 'monthly',
'first_installment_due_date': '2024-01-20'
}
)
Parámetros de Parcialidades
| Parámetro | Tipo | Descripción |
|---|---|---|
has_installments |
boolean | Habilitar parcialidades |
installment_count |
integer | Número de parcialidades (2-48) |
installment_frequency |
string | weekly, biweekly o monthly |
first_installment_due_date |
date | Fecha de vencimiento de la primera parcialidad |
late_fee_policy_id |
uuid | ID de política de moratorios |
Parcialidades Manuales
Para mayor control, puedes definir cada parcialidad manualmente con sus propias fechas, montos y estado de pago. Útil para importar facturas existentes con pagos parciales.
{
"customer_id": "cus_abc123",
"items": [
{ "description": "Servicio anual", "quantity": 1, "unit_price": 12000.00 }
],
"installments": [
{
"due_date": "2024-01-15",
"amount": 4000.00,
"external_id": "FACT-001-P1",
"is_paid": true,
"amount_paid": 4000.00,
"paid_at": "2024-01-10"
},
{
"due_date": "2024-02-15",
"amount": 4000.00,
"external_id": "FACT-001-P2",
"is_paid": false
},
{
"due_date": "2024-03-15",
"amount": 4000.00,
"external_id": "FACT-001-P3",
"is_paid": false
}
]
}
Objeto Invoice
{
"id": "inv_abc123xyz",
"object": "invoice",
"invoice_number": "INV-2024-0001",
"external_id": "FACT-001",
"status": "partial",
"customer_id": "cus_a1b2c3d4e5f6",
"currency": "MXN",
"subtotal": 5000.00,
"tax_amount": 0,
"total": 5000.00,
"amount_paid": 1666.67,
"amount_due": 3333.33,
"document_date": "2024-01-15",
"due_date": "2024-03-20",
"has_installments": true,
"installment_count": 3,
"installment_frequency": "monthly",
"items": [
{
"id": "ii_xyz789",
"description": "Colegiatura Enero 2024",
"quantity": 1,
"unit_price": 5000.00,
"total": 5000.00
}
],
"installments": [
{
"id": "inst_001",
"installment_number": 1,
"status": "paid",
"principal_amount": 1666.67,
"late_fee_amount": 0,
"total_amount": 1666.67,
"amount_paid": 1666.67,
"amount_due": 0,
"due_date": "2024-01-20",
"paid_at": "2024-01-18T14:30:00Z",
"days_overdue": 0,
"external_id": null
},
{
"id": "inst_002",
"installment_number": 2,
"status": "pending",
"principal_amount": 1666.67,
"late_fee_amount": 0,
"total_amount": 1666.67,
"amount_paid": 0,
"amount_due": 1666.67,
"due_date": "2024-02-20",
"paid_at": null,
"days_overdue": 0,
"external_id": null
},
{
"id": "inst_003",
"installment_number": 3,
"status": "pending",
"principal_amount": 1666.66,
"late_fee_amount": 0,
"total_amount": 1666.66,
"amount_paid": 0,
"amount_due": 1666.66,
"due_date": "2024-03-20",
"paid_at": null,
"days_overdue": 0,
"external_id": null
}
],
"created_at": "2024-01-15T00:00:00Z"
}
Estados de Parcialidades
| Estado | Descripción |
|---|---|
| pending | Pendiente de pago, no vencida |
| partial | Pago parcial recibido |
| paid | Completamente pagada |
| overdue | Vencida sin pagar (puede generar moratorios) |
| cancelled | Cancelada (factura anulada) |
Moratorios
Las parcialidades vencidas pueden generar moratorios automáticamente según la política configurada.
El campo late_fee_amount muestra el moratorio acumulado
y se suma al total_amount de la parcialidad.
Importante: Los moratorios se calculan sobre el saldo pendiente del principal, no sobre moratorios previos (evita interés compuesto no deseado).
Webhooks
Los webhooks te permiten recibir notificaciones en tiempo real sobre eventos en tu cuenta. Configura un endpoint HTTPS y recibe actualizaciones automaticas.
Tipos de Eventos
Pagos
payment.createdpayment.succeededpayment.failedpayment.refunded
Links de Pago
payment_link.createdpayment_link.paidpayment_link.expired
Suscripciones
subscription.createdsubscription.updatedsubscription.canceledsubscription.pausedsubscription.resumedsubscription.trial_ending
Facturas
invoice.createdinvoice.paidinvoice.payment_failedinvoice.upcoming
Formato del Payload
{
"id": "evt_1a2b3c4d5e6f",
"object": "event",
"type": "payment.succeeded",
"api_version": "2024-01-01",
"created": 1705312200,
"data": {
"object": {
"id": "pi_abc123xyz",
"object": "payment_intent",
"amount": 500.00,
"currency": "MXN",
"status": "succeeded",
"customer_id": "cus_a1b2c3d4e5f6",
...
}
}
}
Verificacion de Firma (HMAC)
Cada webhook incluye un header X-Recaudo-Signature que debes verificar
para asegurar que el mensaje viene de Recaudo.
<?php
// Obtener el payload y la firma
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_RECAUDO_SIGNATURE'];
$secret = 'whsec_tu_webhook_secret';
// Extraer timestamp y firma del header
// Formato: t=timestamp,v1=signature
$parts = explode(',', $signature);
$timestamp = substr($parts[0], 2);
$receivedSignature = substr($parts[1], 3);
// Calcular la firma esperada
$signedPayload = $timestamp . '.' . $payload;
$expectedSignature = hash_hmac('sha256', $signedPayload, $secret);
// Verificar
if (hash_equals($expectedSignature, $receivedSignature)) {
// Firma valida - procesar el evento
$event = json_decode($payload, true);
switch ($event['type']) {
case 'payment.succeeded':
// Manejar pago exitoso
break;
case 'subscription.canceled':
// Manejar cancelacion
break;
}
http_response_code(200);
} else {
// Firma invalida
http_response_code(400);
}
const crypto = require('crypto');
app.post('/webhooks/recaudo', express.raw({type: 'application/json'}), (req, res) => {
const payload = req.body;
const signature = req.headers['x-recaudo-signature'];
const secret = 'whsec_tu_webhook_secret';
// Extraer timestamp y firma
const parts = signature.split(',');
const timestamp = parts[0].split('=')[1];
const receivedSignature = parts[1].split('=')[1];
// Calcular firma esperada
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Verificar
if (crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(receivedSignature)
)) {
const event = JSON.parse(payload);
switch (event.type) {
case 'payment.succeeded':
// Manejar pago exitoso
break;
case 'subscription.canceled':
// Manejar cancelacion
break;
}
res.status(200).send('OK');
} else {
res.status(400).send('Invalid signature');
}
});
import hmac
import hashlib
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhooks/recaudo', methods=['POST'])
def webhook():
payload = request.data
signature = request.headers.get('X-Recaudo-Signature')
secret = 'whsec_tu_webhook_secret'
# Extraer timestamp y firma
parts = signature.split(',')
timestamp = parts[0].split('=')[1]
received_signature = parts[1].split('=')[1]
# Calcular firma esperada
signed_payload = f"{timestamp}.{payload.decode()}"
expected_signature = hmac.new(
secret.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
# Verificar
if hmac.compare_digest(expected_signature, received_signature):
event = request.json
if event['type'] == 'payment.succeeded':
# Manejar pago exitoso
pass
elif event['type'] == 'subscription.canceled':
# Manejar cancelacion
pass
return 'OK', 200
else:
return 'Invalid signature', 400
Mejores Practicas
- Siempre verifica la firma HMAC antes de procesar el evento
- Responde con 200 rapidamente y procesa de forma asincrona
- Implementa idempotencia usando el ID del evento
- Usa HTTPS con un certificado valido
- Los webhooks se reintentan automaticamente si fallas (hasta 3 veces)
API de Webhook Endpoints
Administra tus webhook endpoints programáticamente.
/v1/webhook-endpoints
Crear un nuevo webhook endpoint.
{
"url": "https://tu-servidor.com/webhooks/recaudo",
"events": ["payment.succeeded", "invoice.paid", "customer.created"],
"description": "Webhook principal de producción",
"is_active": true
}
/v1/webhook-endpoints
Listar todos los webhook endpoints configurados.
/v1/webhook-endpoints/{'{id}'}
Ver detalle del endpoint incluyendo el secret para verificar firmas.
{
"id": "we_abc123",
"url": "https://tu-servidor.com/webhooks/recaudo",
"events": ["payment.succeeded", "invoice.paid"],
"secret": "whsec_tu_webhook_secret",
"is_active": true,
"description": "Webhook principal",
"created_at": "2026-04-01T00:00:00Z"
}
/v1/webhook-endpoints/{'{id}'}
Actualizar URL, eventos o estado del endpoint.
{
"url": "https://nueva-url.com/webhooks",
"events": ["payment.succeeded", "payment.failed"],
"is_active": false
}
/v1/webhook-endpoints/{'{id}'}
Eliminar un webhook endpoint.
/v1/webhook-endpoints/{'{id}'}/test
Enviar un evento de prueba al endpoint para verificar la conectividad.
/v1/webhook-endpoints/{'{id}'}/rotate-secret
Generar un nuevo secret para el endpoint. El secret anterior dejará de ser válido inmediatamente.
/v1/webhook-endpoints/{'{id}'}/deliveries
Ver el historial de entregas del endpoint con status y response codes.
/v1/webhook-endpoints/{'{id}'}/deliveries/{'{delivery_id}'}/resend
Reenviar una entrega fallida.
Productos
Gestiona tu catálogo de productos y categorías. Los productos pueden tener control de inventario, precios de comparación, impuestos y metadatos personalizados.
Listar categorías
/v1/product-categories
Parámetros opcionales: is_active, parent_id (UUID o "root"), limit, page
Crear categoría
/v1/product-categories
{
"name": "Electrónicos",
"description": "Productos electrónicos y gadgets",
"parent_id": null,
"sort_order": 1,
"is_active": true
}
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre de la categoría |
parent_id | uuid | No | Categoría padre (para subcategorías) |
description | string | No | Descripción |
sort_order | integer | No | Orden de visualización |
is_active | boolean | No | Si está activa (default: true) |
Obtener / Actualizar / Eliminar categoría
/v1/product-categories/{'{id}'}
/v1/product-categories/{'{id}'}
/v1/product-categories/{'{id}'}
Al eliminar una categoría, sus subcategorías se mueven al padre y los productos se desvinculan.
Listar productos
/v1/products
Parámetros opcionales: status (active, draft, archived), category (UUID), search, featured, in_stock, limit, page
Crear producto
/v1/products
{
"name": "Laptop Pro 15",
"price": 25999.00,
"currency": "MXN",
"sku": "LAP-PRO-15",
"description": "Laptop profesional de 15 pulgadas",
"product_category_id": "uuid-de-la-categoria",
"track_stock": true,
"stock_quantity": 50,
"tax_rate": 16,
"is_featured": true,
"metadata": {
"brand": "TechCorp",
"warranty_months": 24
}
}
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre del producto |
price | number | Sí | Precio en decimales (100.00 = $100) |
currency | string | No | Moneda ISO 4217 (default según tenant) |
status | string | No | active, draft, archived (default: active) |
product_category_id | uuid | No | UUID de la categoría |
sku | string | No | Código SKU |
description | string | No | Descripción larga |
compare_at_price | number | No | Precio de comparación (antes) |
cost_price | number | No | Costo del producto |
track_stock | boolean | No | Activar control de inventario |
stock_quantity | integer | No | Cantidad en stock |
tax_rate | number | No | Tasa de impuesto (%) |
is_featured | boolean | No | Producto destacado |
image_url | url | No | URL de la imagen |
metadata | object | No | Metadatos personalizados |
Obtener / Actualizar / Eliminar producto
/v1/products/{'{id}'}
/v1/products/{'{id}'}
/v1/products/{'{id}'}
No se puede eliminar un producto con pedidos pendientes.
Pedidos
Crea y gestiona pedidos para tus clientes. Al crear un pedido se genera automáticamente una factura y un link de pago. Los precios se toman directamente del catálogo de productos.
Listar pedidos
/v1/orders
Parámetros opcionales: status, payment_status, customer (UUID), search, limit, page
Status: pending, confirmed, processing, shipped, delivered, completed, canceled, refunded
Payment status: pending, paid, partially_paid, refunded
Crear pedido
/v1/orders
{
"customer_id": "uuid-del-cliente",
"items": [
{ "product_id": "uuid-producto-1", "quantity": 2 },
{ "product_id": "uuid-producto-2", "quantity": 1 }
],
"notes": "Entregar antes de las 5pm",
"shipping_name": "Juan Pérez",
"shipping_phone": "+5215512345678",
"shipping_address": "Av. Reforma 123, CDMX"
}
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
customer_id | uuid | Sí | UUID del cliente |
items | array | Sí | Lista de productos con product_id y quantity |
notes | string | No | Notas visibles para el cliente |
internal_notes | string | No | Notas internas |
currency | string | No | Moneda ISO 4217 |
shipping_name | string | No | Nombre del destinatario |
shipping_phone | string | No | Teléfono del destinatario |
shipping_address | string | No | Dirección de envío |
metadata | object | No | Metadatos personalizados |
Obtener pedido
/v1/orders/{'{id}'}
Incluye cliente, items con productos y factura asociada.
Ciclo de vida del pedido
/v1/orders/{'{id}'}/cancel
— Cancelar pedido (restaura stock)
/v1/orders/{'{id}'}/ship
— Marcar como enviado
/v1/orders/{'{id}'}/deliver
— Marcar como entregado
/v1/orders/{'{id}'}/complete
— Marcar como completado
Flujo típico: pending → confirmed → shipped → delivered → completed
Items del pedido
/v1/orders/{'{id}'}/items
Retorna los items del pedido con detalle de cada producto.
Conversaciones
Envía y recibe mensajes a través de WhatsApp, Facebook Messenger e Instagram. La API detecta automáticamente el canal de cada conversación y enruta los mensajes al servicio correcto.
Listar conversaciones
/v1/conversations
Parámetros opcionales: channel (whatsapp, messenger, instagram), status (open, waiting, resolved, closed), customer (UUID), assigned_to (UUID), limit, page
Obtener conversación
/v1/conversations/{'{id}'}
Incluye cliente y agente asignado.
Listar mensajes
/v1/conversations/{'{id}'}/messages
Parámetros opcionales: type (text, image, video, audio, document, template), limit, page
Enviar mensaje
/v1/conversations/{'{id}'}/messages
{
"body": "Hola, tu pedido ha sido enviado. Número de guía: ABC123"
}
{
"body": "Aquí está tu factura",
"media_url": "https://ejemplo.com/factura.pdf",
"media_type": "document"
}
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
body | string | No* | Texto del mensaje (máx 4096 chars) |
media_url | url | No* | URL del archivo multimedia |
media_type | string | No | image, video, audio, document |
* Se requiere al menos body o media_url.
Enviar template de WhatsApp
/v1/conversations/{'{id}'}/send-template
{
"template_id": "uuid-del-template",
"variables": {
"1": "Juan Pérez",
"2": "$1,500.00",
"3": "15 de marzo"
}
}
Solo disponible para conversaciones de WhatsApp. Los templates deben estar aprobados por Meta.
Resolver / Cerrar conversación
/v1/conversations/{'{id}'}/resolve
— Marcar como resuelta
/v1/conversations/{'{id}'}/close
— Cerrar definitivamente
Flujos de Conversación
La API de Flujos de Conversación te permite desplegar flujos automatizados de WhatsApp a tus clientes, similar a como funcionan las plataformas de engagement como Treble. Puedes iniciar campañas masivas, monitorear el estado de las ejecuciones y actualizar variables en tiempo real.
/api/v1/flows
Lista todos los flujos de conversación disponibles para tu tenant.
Respuesta
{
"object": "list",
"data": [
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "Flujo de Cobranza",
"description": "Recordatorio de pago con opciones",
"type": "collection",
"purpose": "Recordatorio",
"channel": "whatsapp",
"status": "published",
"version": 1,
"total_runs": 150,
"total_responses": 89,
"response_rate": 59.3,
"published_at": "2024-01-15T10:30:00Z",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"url": "/v1/flows"
}
/api/v1/flows/{flow_id}/deploy
Despliega un flujo a uno o más destinatarios. Cada destinatario recibirá el flujo de forma independiente. Puedes incluir variables personalizadas que se usarán para reemplazar placeholders en los mensajes.
Cuerpo de la Petición
{
"recipients": [
{
"phone": "+5215512345678",
"variables": {
"nombre": "Juan Pérez",
"monto": "$1,500.00",
"fecha_limite": "15 de febrero"
}
},
{
"phone": "+5215587654321",
"variables": {
"nombre": "María García",
"monto": "$2,300.00",
"fecha_limite": "20 de febrero"
}
}
],
"phone_number_id": "uuid-de-tu-numero-whatsapp", // Opcional: número desde el cual sale el flow. Si se omite, usa el default del tenant.
"scheduled_at": null // Opcional: programar para después
}
phone_number_id identifica el número desde el cual sale el flow. Acepta dos formatos:
el UUID interno del PhoneNumber, o el meta_phone_number_id (el ID numérico que Meta asigna al número, ej. 748899301642932).
Lo puedes obtener desde /admin/settings/integrations/whatsapp/numbers.
Si tu tenant solo tiene un número de WhatsApp, no es necesario enviarlo.
Respuesta
{
"success": true,
"message": "Flow deployed to 2 recipients",
"data": {
"flow_id": "01234567-89ab-cdef-0123-456789abcdef",
"batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"total_recipients": 2,
"runs_created": 2,
"scheduled_at": null,
"run_ids": [
"f1a2b3c4-d5e6-7890-abcd-111111111111",
"f1a2b3c4-d5e6-7890-abcd-222222222222"
]
}
}
/api/v1/flows/{flow_id}/runs
Lista las ejecuciones de un flujo con filtros opcionales.
Parámetros de Query
| Parámetro | Tipo | Descripción |
|---|---|---|
| status | string | Filtrar por estado: pending, running, waiting, completed, failed, cancelled |
| batch_id | string | Filtrar por ID de lote (retornado en el deploy) |
| phone | string | Filtrar por número de teléfono del destinatario |
| limit | integer | Resultados por página (default 20) |
Respuesta
{
"object": "list",
"data": [
{
"id": "f1a2b3c4-d5e6-7890-abcd-111111111111",
"flow_id": "01234567-89ab-cdef-0123-456789abcdef",
"flow_name": "Flujo de Cobranza",
"phone_number": "+5215512345678",
"country_code": "MX",
"customer_id": "cust-uuid-123",
"customer_name": "Juan Pérez",
"conversation_id": "conv-uuid-789",
"status": "completed",
"source": "api",
"batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"context": {
"nombre": "Juan Pérez",
"monto": "$1,500.00"
},
"current_node_id": null,
"error_message": null,
"scheduled_at": null,
"started_at": "2024-01-20T10:00:00Z",
"finished_at": "2024-01-20T10:05:30Z",
"created_at": "2024-01-20T09:59:58Z"
}
],
"has_more": false,
"url": "/v1/flows/01234567-89ab-cdef-0123-456789abcdef/runs"
}
/api/v1/flows/{flow_id}/runs/{run_id}
Obtiene el detalle de una ejecución específica del flujo.
Respuesta
{
"object": "flow_run",
"id": "f1a2b3c4-d5e6-7890-abcd-111111111111",
"flow_id": "01234567-89ab-cdef-0123-456789abcdef",
"flow_name": "Flujo de Cobranza",
"phone_number": "+5215512345678",
"country_code": "MX",
"customer_id": "cust-uuid-123",
"customer_name": "Juan Pérez",
"conversation_id": "conv-uuid-789",
"status": "waiting",
"source": "api",
"batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"context": {
"nombre": "Juan Pérez",
"monto": "$1,500.00",
"respuesta_cliente": "Sí, pagaré mañana"
},
"current_node_id": "node_1768811907821_4wexo4g3h",
"error_message": null,
"scheduled_at": null,
"started_at": "2024-01-20T10:00:00Z",
"finished_at": null,
"created_at": "2024-01-20T09:59:58Z"
}
/api/v1/flows/{flow_id}/runs/{run_id}/variables
Actualiza las variables de una ejecución en curso. Útil para inyectar información externa que será usada en los siguientes nodos del flujo.
Cuerpo de la Petición
{
"variables": {
"crm_status": "contacted",
"agent_notes": "Cliente confirmó pago para mañana",
"follow_up_date": "2024-01-21"
}
}
/api/v1/flows/{flow_id}/runs/{run_id}/cancel
Cancela una ejecución que está pendiente o en espera. Las ejecuciones completadas o fallidas no pueden cancelarse.
Respuesta
{
"success": true,
"message": "Flow run cancelled successfully",
"data": {
"id": "f1a2b3c4-d5e6-7890-abcd-111111111111",
"flow_id": "01234567-89ab-cdef-0123-456789abcdef",
"flow_name": "Flujo de Cobranza",
"phone_number": "+5215512345678",
"country_code": "MX",
"customer_id": "cust-uuid-123",
"customer_name": "Juan Pérez",
"conversation_id": null,
"status": "cancelled",
"source": "api",
"batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"context": {
"nombre": "Juan Pérez"
},
"current_node_id": null,
"error_message": null,
"scheduled_at": null,
"started_at": null,
"finished_at": "2024-01-20T11:00:00Z",
"created_at": "2024-01-20T09:59:58Z"
}
}
Webhooks de Conversación
Configura webhooks para recibir notificaciones en tiempo real sobre eventos de conversación y flujos. Los webhooks se configuran desde el panel de Webhook Endpoints.
Eventos Disponibles
| Evento | Descripción |
|---|---|
| conversation.created | Nueva conversación iniciada |
| conversation.assigned | Conversación asignada a un agente |
| conversation.transferred | Conversación transferida a otro agente o grupo |
| conversation.resolved | Conversación marcada como resuelta |
| conversation.closed | Conversación cerrada con motivo |
| conversation.message.received | Mensaje recibido del cliente |
| conversation.message.sent | Mensaje enviado al cliente |
| flow_run.started | Ejecución de flujo iniciada |
| flow_run.completed | Ejecución de flujo completada |
| flow_run.failed | Ejecución de flujo fallida |
| flow_run.waiting | Flujo esperando respuesta del cliente |
Ejemplo de Payload (conversation.message.received)
{
"id": "evt_123456",
"type": "conversation.message.received",
"created_at": "2024-01-20T10:05:30Z",
"data": {
"id": "msg_abc123",
"conversation_id": "conv_xyz789",
"direction": "inbound",
"type": "text",
"body": "Sí, haré el pago mañana",
"sender_identifier": "+5215512345678",
"created_at": "2024-01-20T10:05:30Z",
"conversation": {
"id": "conv_xyz789",
"channel": "whatsapp",
"channel_identifier": "+5215512345678",
"status": "open",
"customer_id": "cust_abc",
"customer_name": "Juan Pérez",
"assigned_user_id": "user_123",
"assigned_user_name": "Ana López"
}
}
}
Casos de Uso
Campaña de Cobranza Masiva
Despliega un flujo de recordatorio de pago a miles de clientes con variables personalizadas (nombre, monto, fecha). El flujo puede incluir múltiples mensajes, esperas por respuesta, y ramificaciones basadas en las respuestas del cliente.
Integración con CRM
Usa los webhooks para sincronizar el estado de las conversaciones con tu CRM. Cuando un cliente responde, actualiza automáticamente su registro con la respuesta y programa seguimientos.
Encuestas y NPS
Despliega flujos interactivos con botones para recopilar feedback de clientes. Usa las variables del run para almacenar las respuestas y consultar los resultados vía API.
Seguimientos
Programa y gestiona tareas de seguimiento con tus clientes
Listar seguimientos
/v1/follow-ups
Retorna una lista paginada de seguimientos. Puedes filtrar por estado, tipo, agente o cliente.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
status | string | No | Filtrar por estado: pending, completed, overdue |
type | string | No | Filtrar por tipo: call, message, whatsapp, email, meeting, task |
user_id | uuid | No | Filtrar por agente asignado |
customer_id | uuid | No | Filtrar por cliente |
limit | integer | No | Resultados por página (default: 20) |
curl https://recaudo.app/api/v1/follow-ups?status=pending \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json"
{
"object": "list",
"data": [
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"title": "Llamar para confirmar pago",
"description": "El cliente solicitó una llamada de seguimiento",
"status": "pending",
"type": "call",
"scheduled_at": "2026-04-10T14:00:00Z",
"completed_at": null,
"customer": {
"id": "uuid-del-cliente",
"name": "Juan Pérez",
"phone": "+5215512345678"
},
"user": {
"id": "uuid-del-agente",
"name": "María López"
},
"created_at": "2026-04-08T10:00:00Z",
"updated_at": "2026-04-08T10:00:00Z"
}
],
"total": 15
}
Crear seguimiento
/v1/follow-ups
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
title | string | Sí | Título del seguimiento (máx 255 chars) |
description | string | No | Descripción o notas adicionales |
customer_id | uuid | No | UUID del cliente asociado |
conversation_id | uuid | No | UUID de la conversación asociada |
user_id | uuid | No | UUID del agente asignado |
scheduled_at | datetime | Sí | Fecha y hora programada (ISO 8601) |
type | string | No | call, message, whatsapp, email, meeting, task |
curl -X POST https://recaudo.app/api/v1/follow-ups \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Llamar para confirmar pago",
"description": "El cliente pidió que le llamemos el jueves",
"customer_id": "uuid-del-cliente",
"user_id": "uuid-del-agente",
"scheduled_at": "2026-04-10T14:00:00Z",
"type": "call"
}'
{
"object": "follow_up",
"data": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"title": "Llamar para confirmar pago",
"description": "El cliente pidió que le llamemos el jueves",
"status": "pending",
"type": "call",
"scheduled_at": "2026-04-10T14:00:00Z",
"completed_at": null,
"customer": {
"id": "uuid-del-cliente",
"name": "Juan Pérez"
},
"user": {
"id": "uuid-del-agente",
"name": "María López"
},
"created_at": "2026-04-08T10:00:00Z"
}
}
Completar seguimiento
/v1/follow-ups/{'{id}'}/complete
Marca un seguimiento como completado. Opcionalmente puedes agregar notas.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
notes | string | No | Notas sobre la resolución |
curl -X POST https://recaudo.app/api/v1/follow-ups/{id}/complete \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{ "notes": "Cliente confirmó que realizará el pago mañana" }'
{
"object": "follow_up",
"data": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"title": "Llamar para confirmar pago",
"status": "completed",
"completed_at": "2026-04-08T15:30:00Z",
"notes": "Cliente confirmó que realizará el pago mañana"
}
}
Reprogramar seguimiento
/v1/follow-ups/{'{id}'}/reschedule
Cambia la fecha programada de un seguimiento pendiente.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
scheduled_at | datetime | Sí | Nueva fecha y hora programada (ISO 8601) |
curl -X POST https://recaudo.app/api/v1/follow-ups/{id}/reschedule \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{ "scheduled_at": "2026-04-12T10:00:00Z" }'
{
"object": "follow_up",
"data": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"title": "Llamar para confirmar pago",
"status": "pending",
"scheduled_at": "2026-04-12T10:00:00Z"
}
}
Templates de WhatsApp
Consulta los templates aprobados disponibles para envío
Listar templates
/v1/whatsapp-templates
Retorna todos los templates de WhatsApp configurados para tu cuenta. Incluye el estado de aprobación de Meta.
curl https://recaudo.app/api/v1/whatsapp-templates \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json"
{
"object": "list",
"data": [
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "recordatorio_pago",
"description": "Recordatorio de pago pendiente",
"content_type": "text",
"variables": ["nombre", "monto", "fecha_limite"],
"meta_template_status": "APPROVED"
},
{
"id": "98765432-10fe-dcba-9876-543210fedcba",
"name": "confirmacion_pedido",
"description": "Confirmación de pedido realizado",
"content_type": "text",
"variables": ["nombre", "numero_pedido"],
"meta_template_status": "APPROVED"
}
]
}
Los templates deben estar aprobados por Meta (meta_template_status: "APPROVED") para poder ser enviados.
Mensajes Interactivos
Envía mensajes con botones o listas de opciones por WhatsApp
Enviar mensaje interactivo
/v1/conversations/{'{id}'}/interactive
Envía un mensaje interactivo de WhatsApp con botones de respuesta rápida o una lista de opciones. Solo disponible para conversaciones de WhatsApp.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
type | string | Sí | Tipo de mensaje: buttons o list |
body | string | Sí | Texto del mensaje (máx 1024 chars) |
buttons | array | Sí* | Botones de respuesta (mín 1, máx 3). Requerido si type=buttons |
buttons.*.title | string | Sí | Texto del botón (máx 20 chars) |
sections | array | Sí* | Secciones de la lista. Requerido si type=list |
sections.*.title | string | No | Título de la sección (máx 24 chars) |
sections.*.rows | array | Sí | Opciones de la sección (mín 1, máx 10) |
sections.*.rows.*.title | string | Sí | Texto de la opción (máx 24 chars) |
sections.*.rows.*.description | string | No | Descripción de la opción (máx 72 chars) |
button_text | string | No | Texto del botón de la lista (default: "Seleccionar", máx 20 chars) |
* buttons es requerido cuando type=buttons. sections es requerido cuando type=list.
curl -X POST https://recaudo.app/api/v1/conversations/{id}/interactive \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"type": "buttons",
"body": "¿Deseas confirmar tu pago de $1,500.00?",
"buttons": [
{ "title": "Sí, confirmar" },
{ "title": "No, cancelar" },
{ "title": "Hablar con agente" }
]
}'
curl -X POST https://recaudo.app/api/v1/conversations/{id}/interactive \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"type": "list",
"body": "Selecciona el método de pago que prefieres:",
"button_text": "Ver opciones",
"sections": [
{
"title": "Métodos de pago",
"rows": [
{ "title": "Tarjeta de crédito", "description": "Visa, Mastercard, AMEX" },
{ "title": "Transferencia SPEI", "description": "Pago inmediato desde tu banco" },
{ "title": "Pago en OXXO", "description": "Genera una referencia de pago" }
]
}
]
}'
{
"object": "message",
"data": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"conversation_id": "uuid-de-la-conversacion",
"type": "interactive",
"direction": "outbound",
"status": "sent",
"created_at": "2026-04-08T10:30:00Z"
}
}
Asignar Conversación
Asigna conversaciones a agentes humanos de tu equipo
Asignar agente
/v1/conversations/{'{id}'}/assign
Asigna una conversación a un miembro de tu equipo. Al asignar, la conversación se marca como manejada por un humano y se desactiva el agente de IA.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
user_id | uuid | No | UUID del miembro del equipo. Usa GET /v1/team para obtener los IDs disponibles |
curl -X POST https://recaudo.app/api/v1/conversations/{id}/assign \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{ "user_id": "uuid-del-agente" }'
{
"object": "conversation",
"data": {
"id": "uuid-de-la-conversacion",
"channel": "whatsapp",
"status": "open",
"is_handled_by_ai": false,
"assigned_user": {
"id": "uuid-del-agente",
"name": "María López"
},
"customer": {
"id": "uuid-del-cliente",
"name": "Juan Pérez",
"phone": "+5215512345678"
},
"updated_at": "2026-04-08T10:30:00Z"
}
}
Equipo
Consulta los miembros activos de tu equipo
Listar miembros del equipo
/v1/team
Retorna todos los miembros activos de tu equipo. Útil para obtener IDs de agentes al asignar conversaciones o seguimientos.
curl https://recaudo.app/api/v1/team \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json"
{
"object": "list",
"data": [
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "María López",
"email": "maria@empresa.com",
"phone": "+5215512345678",
"job_title": "Gerente de Cobranza",
"status": "active"
},
{
"id": "98765432-10fe-dcba-9876-543210fedcba",
"name": "Carlos Ramírez",
"email": "carlos@empresa.com",
"phone": "+5215598765432",
"job_title": "Agente de Soporte",
"status": "active"
}
]
}
Fuentes de Clientes
Consulta las fuentes de adquisición configuradas para tus clientes
Listar fuentes de clientes
/v1/customer-sources
Retorna todas las fuentes de adquisición de clientes configuradas. Útil para asignar una fuente al crear o actualizar clientes.
curl https://recaudo.app/api/v1/customer-sources \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json"
{
"object": "list",
"data": [
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "Sitio Web",
"slug": "sitio-web"
},
{
"id": "98765432-10fe-dcba-9876-543210fedcba",
"name": "Referido",
"slug": "referido"
},
{
"id": "abcdef01-2345-6789-abcd-ef0123456789",
"name": "Facebook Ads",
"slug": "facebook-ads"
}
]
}