Documentación
Sabado Cloud es una plataforma B2B que te conecta a varios servicios (WhatsApp Business como Tech Provider de Meta, MercadoPago como marketplace para cobros con split, correo electrónico gestionado con tu propio dominio, y facturación electrónica ARCA) detrás de una sola API REST y un solo set de webhooks firmados. Acá tenés todo lo que necesitás para integrarte.
Cómo se organizan estos docs
La doc está partida por servicio: cada servicio soportado tiene su propia sección en la barra lateral. Esta página cubre lo común a todos (autenticación, errores, idempotencia). Los endpoints específicos viven en su sección.
- WhatsApp Cloud API — mandar y recibir mensajes, plantillas, perfil del negocio, estado del número, estadísticas.
- Instagram y Messenger — los mensajes directos de Instagram y de la página de Facebook, por la misma API que WhatsApp (con la ventana de 24 horas de Meta).
- MercadoPago split — conectar el MP del comercio por OAuth, cobrar con un fee de plataforma y cancelar/reembolsar.
- Correo (email) — conectar un dominio, configurar su DNS, crear casillas y alias, y leer / enviar mensajes por API.
- Facturación (ARCA) — emitir comprobantes electrónicos (Factura C / A / B) por el CUIT del negocio, con delegación de Clave Fiscal.
- Google Calendar — conectar el calendario del negocio con un link y crear, mover y borrar eventos; agenda y horarios ocupados.
- Webhooks — recibir eventos firmados (mensajes entrantes, cambios de estado, pagos aprobados / rechazados / reembolsados, etc.).
- Onboarding — cómo el cliente final conecta su WhatsApp (Embedded Signup con coexistence o migration).
Cuando agreguemos un servicio nuevo, va a aparecer como una sección
propia (/docs/<servicio>/) con su propio set de
endpoints. La estructura del sidebar y los conceptos comunes
(autenticación, errores, webhooks) se mantienen.
Quickstart de 5 minutos
Asumimos que ya tenés acceso al panel en
https://waba.galgo.io/customer. Si todavía no, escribinos
a contacto@sabado.cloud y te
damos uno.
1. Emitir tu primera credencial
Andá a API keys en tu panel y hacé click en Emitir credencial. Ponele un nombre (por ejemplo, Producción), guardá el secret que te aparece — es la única vez que lo vas a ver completo.
Cada credencial tiene un set de scopes (permisos
granulares). Pedí solo los que necesitás: messages.send
para mandar WhatsApp, mercadopago.write para cobrar,
etc. La lista completa la ves en el panel cuando emitís la key.
2. Registrar tu primer negocio
En Tus negocios,
click en Registrar negocio nuevo. Completá el nombre y
un identificador interno (ej: pizzeria-don-mario) que vas a
usar en la API.
Compartile al negocio el link de onboarding que te damos abajo. Cuando entren, conectan su WhatsApp Business sin perder el uso de la app del celular. Si además vas a cobrar con MercadoPago, el comercio conecta su cuenta MP por un botón aparte del panel; y si querés atender también los DMs de Instagram y Messenger, se conectan desde el panel con la cuenta de Facebook del negocio.
3. Mandar tu primer mensaje
Una vez que el negocio conectó su WhatsApp, podés enviar mensajes con
plantillas pre-aprobadas. Por ejemplo, la plantilla
hello_world que viene cargada por default:
curl -X POST "https://waba.galgo.io/v1/messages" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenant_ref": "pizzeria-don-mario",
"to": "5491155555555",
"type": "template",
"template": {
"name": "hello_world",
"language": "en_US"
}
}'
La respuesta tiene este formato:
{
"id": "019dcf...",
"tenant_ref": "pizzeria-don-mario",
"channel": "whatsapp",
"type": "template",
"status": "sent",
"to": "5491155555555",
"message_id": "wamid.HBg...",
"waba_message_id": "wamid.HBg...",
"error_code": null,
"error_message": null,
"idempotency_key": null,
"created_at": "2026-05-07T15:30:00Z",
"updated_at": "2026-05-07T15:30:00Z"
}
Para el detalle completo (tipos de mensaje, media, interactivos, templates, etc.) andá a WhatsApp Cloud API. Para cobros con MercadoPago, MercadoPago split.
4. Ver tu uso
Volvé a tu panel, andá a Uso y vas a ver el conteo de mensajes enviados, recibidos y entregas de webhook.
Listo. Ya estás integrado. El resto de la doc te cuenta cómo recibir mensajes y eventos entrantes, cómo manejar errores, cómo gestionar plantillas, y cómo cobrar con split de pagos.
Conceptos clave
| Concepto | Qué es |
|---|---|
| Cuenta | Tu cuenta en Sabado Cloud. Tiene API keys, webhook URL y un secret HMAC. |
| Negocio (tenant) | El cliente final tuyo. Cada uno tiene un external_ref único dentro de tu cuenta. Un mismo negocio puede tener conectados varios servicios (WhatsApp + MercadoPago, por ejemplo). |
| Mensaje | Cada envío o recepción que pasa por la API de WhatsApp. Los enviados tienen un ciclo de vida: queued → sent → delivered → read (o failed). |
| Plantilla | Texto pre-aprobado por Meta para enviar como primer mensaje a un contacto. Se gestiona en nombre del negocio. |
| Pago | Un cobro hecho con la cuenta MercadoPago del negocio vía Checkout Pro. Sabado retiene un marketplace_fee sobre cada cobro. |
| Dominio / Casilla | El dominio de correo del negocio (ej. tudominio.com) y las casillas que cuelgan de él (ej. ventas@tudominio.com). Sabado corre el servidor de correo; la contraseña de cada casilla se usa internamente y nunca se expone. |
| Webhook | Cada vez que pasa algo relevante (mensaje entrante, cambio de estado, pago aprobado/reembolsado, etc.) te mandamos un POST firmado a tu URL. |
Privacidad. Tu panel no muestra el contenido de los mensajes — solo los cuenta. Los mensajes sí quedan guardados de nuestro lado: los necesitamos para reintentar las entregas a tu webhook, no procesar dos veces el mismo mensaje y servirte el historial. Con los pagos, la fuente de verdad sigue siendo MercadoPago; nosotros guardamos lo necesario para auditoría y conciliación.
Autenticación
Cada request va con el header Authorization: Bearer TU_API_KEY.
El secret completo se muestra una sola vez al emitir la credencial.
Authorization: Bearer gwk_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890
Si perdiste el secret, emití uno nuevo, actualizá tu sistema y revocá el anterior. No mantenemos copia del secret, solo un hash con sal.
Scopes
Cada API key tiene una lista de scopes. Cada endpoint requiere uno
específico — si tu key no lo tiene, recibís 403 insufficient_scope.
Los scopes disponibles hoy:
| Scope | Habilita |
|---|---|
tenants.read | Listar / ver negocios. |
tenants.write | Crear y desconectar negocios. |
messages.send | Enviar mensajes (WhatsApp, Instagram y Messenger), marcar como leído y "escribiendo…". |
messages.read | Consultar estado de un mensaje, leer el historial de coexistencia y descargar media recibida. |
business.read | Perfil del negocio, estado del número y estadísticas. |
business.write | Editar el perfil del negocio y re-registrar el número. |
social.read | Estado de conexión de Instagram y Messenger. |
social.write | Desconectar Instagram o Messenger. |
templates.read | Listar / ver plantillas. |
templates.write | Crear y borrar plantillas. |
mercadopago.read | Consultar estado de conexión de MercadoPago. |
mercadopago.write | Iniciar conexión MP, crear preferencias de cobro, hacer reembolsos. |
mail.read | Listar dominios / casillas / alias y leer mensajes. |
mail.write | Crear/borrar dominios, casillas y alias; enviar y borrar mensajes. |
arca.read | Estado de facturación, último número y comprobantes emitidos. |
arca.write | Emitir comprobantes electrónicos (facturas C / A / B). |
calendar.read | Estado de Google Calendar, calendarios, eventos y horarios ocupados. |
calendar.write | Conectar / desconectar Google Calendar; crear, cambiar y borrar eventos. |
* | Wildcard — habilita todos los scopes anteriores. |
Rate limit
60 requests por minuto por API key. El contador es de la
key, no del tenant ni del número: dos keys de la misma cuenta tienen 60 cada
una, y un tenant no tiene límite propio. Si lo superás, devolvemos
429 Too Many Requests con el header Retry-After
en segundos y {"error": "rate_limited"} en el body.
Negocios (tenants)
Cada negocio que operás es un tenant de tu cuenta, identificado
por un external_ref que elegís vos (ej.
pizzeria-don-mario) y que después usás como
tenant_ref en el resto de la API. Los podés crear desde el
panel o por API.
GET /v1/tenants
Los negocios de tu cuenta. Scope tenants.read.
GET /v1/tenants
Authorization: Bearer TU_API_KEY
{
"data": [
{
"external_ref": "pizzeria-don-mario",
"name": "Pizzería Don Mario",
"contact_name": "Mario",
"contact_email": "mario@donmario.com.ar",
"contact_phone": null,
"connected": true,
"whatsapp": {
"display_phone": "+54 9 11 5555-1234",
"verified_name": "Pizzería Don Mario",
"waba_id": "1234567890",
"phone_number_id": "9876543210",
"connected_at": "2026-05-27T19:34:15+00:00"
},
"onboarding_url": "https://waba.galgo.io/connect/tu-cuenta/pizzeria-don-mario",
"created_at": "2026-05-20T16:26:37+00:00"
}
]
}
connected dice si el negocio tiene WhatsApp conectado;
whatsapp es null si no. onboarding_url
es el link que le pasás al negocio para que conecte (o reconecte) su número.
GET /v1/tenants/{external_ref}
Un negocio, con la misma forma que cada item de la lista. Scope tenants.read.
GET /v1/tenants/pizzeria-don-mario
POST /v1/tenants
Registrar un negocio nuevo. Scope tenants.write.
POST /v1/tenants
{
"external_ref": "pizzeria-don-mario",
"name": "Pizzería Don Mario",
"contact_name": "Mario",
"contact_email": "mario@donmario.com.ar",
"contact_phone": "5491155551234",
"notes": "Cliente de la zona norte"
}
Obligatorios: external_ref y name. Devuelve
201 con el negocio creado (incluido su
onboarding_url). Si el external_ref ya existe en tu
cuenta, 409 duplicate_external_ref; si tu plan no tiene cupo
para otro negocio, 422 quota_exceeded.
POST /v1/tenants/{external_ref}/disconnect
Desconecta el WhatsApp del negocio: le decimos a Meta que deje de mandarnos
sus mensajes y recién ahí lo marcamos como desconectado. Scope
tenants.write.
POST /v1/tenants/pizzeria-don-mario/disconnect
{
"ok": true,
"tenant_ref": "pizzeria-don-mario",
"status": "disconnected",
"disconnected_at": "2026-09-16T04:00:00+00:00"
}
Si Meta rechaza la desconexión, 502 meta_disconnect_failed y
no marcamos nada: el negocio sigue conectado y podés
reintentar. Si no tenía nada conectado, 409 not_connected.
Errores
Las respuestas de error tienen este formato:
{
"ok": false,
"error": "meta_recipient_unreachable",
"message": "El número de destino no está en el allowlist de testers.",
"meta_code": 131030
}
La excepción son los errores de validación (falta un campo, o tiene un
formato que no corresponde): vienen con 422 y otra forma,
con el detalle por campo:
{
"message": "The tenant ref field is required.",
"errors": {
"tenant_ref": ["The tenant ref field is required."]
}
}
Algunos errores que vienen de Meta (por ejemplo en
plantillas) suman
meta_subcode y meta_detail con el motivo exacto
cuando el message de Meta es genérico. Si están presentes,
son la pista más útil para corregir el request.
| HTTP | Error | Qué pasó |
|---|---|---|
| 401 | missing_api_key | Falta el header Authorization: Bearer …. |
| 401 | invalid_api_key | La API key no existe o fue revocada. |
| 403 | insufficient_scope | La API key no tiene el scope que pide el endpoint. Ver Scopes. |
| 403 | project_not_active | La cuenta de esa API key está desactivada. |
| 403 | plan_not_included | El plan de tu cuenta no incluye ese servicio (WhatsApp, correo, facturación, cobros MP o Google Calendar). Pasate a un plan que lo incluya desde el panel. |
| 403 | meta_permission_denied | Instagram o Messenger: Meta rechazó el envío por permisos de la página. |
| 402 | subscription_suspended | La suscripción de la cuenta está suspendida (cancelada o con el cobro pausado). Aplica solo a planes pagos; se reactiva desde el panel. |
| 402 | subscription_required | La operación (conectar WhatsApp, conectar dominio de correo) requiere la suscripción activa de un plan pago. |
| 404 | tenant_not_found | El tenant_ref no existe en la cuenta de esa API key. Cada key ve solo los negocios de su cuenta. |
| 404 | message_not_found / template_not_found / voucher_not_found | El mensaje, la plantilla o el comprobante no existen para ese negocio. |
| 404 | payment_not_found | El pago de Mercado Pago no existe o no es de ese comercio. |
| 404 | domain_not_found / account_not_found | El dominio o la casilla de correo no pertenecen a ese negocio. |
| 409 | tenant_not_connected | El negocio existe pero no tiene WhatsApp conectado. Completá el onboarding primero. |
| 409 | meta_outside_session_window | Pasaron más de 24 horas desde el último mensaje del contacto: para escribirle hay que usar una plantilla aprobada. |
| 409 | duplicate_external_ref | Ya hay un negocio con ese external_ref en tu cuenta. |
| 409 | not_connected | Pediste desconectar un negocio que no tiene nada conectado. |
| 409 | channel_not_connected / outside_messaging_window | Instagram o Messenger: el canal no está conectado, o se cerró la ventana de 24 horas. Ver Instagram y Messenger. |
| 409 | mp_not_connected | El negocio no tiene MercadoPago conectado (no completó OAuth o el token fue revocado). Mandale el connect_url. |
| 409 | payment_not_refundable | El pago no se puede devolver: no está aprobado, pasaron 180 días, ya tiene una devolución parcial o un contracargo. El motivo viene en reason. Ver Cancelar / reembolsar. |
| 409 | arca_not_connected / delegation_pending | El negocio no cargó sus datos fiscales, o falta confirmar la delegación en su Clave Fiscal. |
| 422 | (validación) | Falta un campo o tiene un formato inválido. Forma distinta al resto: ver arriba. |
| 422 | invalid_payload | Algún campo no cumple las reglas de Meta (vertical inválido, websites > 2, etc). |
| 422 | invalid_idempotency_key | El header Idempotency-Key vino vacío o con más de 255 caracteres. |
| 422 | meta_recipient_unreachable | Meta rechazó el destino: número sin WhatsApp, contacto que bloqueó, número fuera del allowlist de una cuenta de prueba, o la cuenta del negocio bloqueada (131031). |
| 422 | meta_template_invalid | Meta rechazó la plantilla del envío (nombre, idioma o parámetros que no coinciden). Ver message. |
| 422 | quota_exceeded | Se alcanzó un cupo del plan de tu cuenta (negocios, números de WhatsApp, dominios de correo o casillas). Los cupos son por cuenta, sumando todos tus negocios. Ver message. |
| 422 | cae_rejected | ARCA rechazó el comprobante. El detalle de las observaciones va en message. |
| 423 | meta_account_locked | Solo en /v1/phone-number/register: la cuenta sigue bloqueada (131031) después del intento. |
| 429 | rate_limited | Pasaste 60 req/min con esa API key. Esperá lo que diga Retry-After y reintentá. |
| 429 | meta_rate_limited | El límite es de Meta, no nuestro: el número está mandando demasiado rápido. Esperá unos segundos. |
| 502 | meta_other | Meta devolvió un error que no mapeamos a un código específico. Mirá meta_code en la respuesta. |
| 502 | meta_disconnect_failed | Meta rechazó la desconexión. No marcamos nada de nuestro lado: el negocio sigue conectado. Reintentá. |
| 502 | refund_failed | MercadoPago rechazó el reembolso (pago no reembolsable, ya reembolsado, etc.). Ver message. |
| 502 | imap_error / smtp_error | Falló la lectura (IMAP) o el envío (SMTP) de un correo. Ver message. |
| 503 | meta_token_invalid | El acceso al WhatsApp del negocio se perdió. Tiene que reconectar el número. |
| 503 | network_error | No pudimos hablar con el proveedor (Meta, MercadoPago, ARCA, el servidor de correo). Reintentá con backoff. |
| 503 | not_configured | El servicio (correo / facturación / cobros) no está habilitado todavía. Escribinos. |
| 500 | internal_error | Algo se rompió de nuestro lado. Reintentá con backoff. |
Idempotencia
Para evitar enviar el mismo mensaje dos veces si tu sistema reintentó
un POST que ya había salido, agregá el header
Idempotency-Key con un UUID o string único de tu sistema:
curl -X POST "https://waba.galgo.io/v1/messages" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Idempotency-Key: pedido-12345-confirmacion" \
-H "Content-Type: application/json" \
-d '{ ... }'
Si ya existe un mensaje enviado con esa key en tu cuenta, no se manda de
nuevo: te devolvemos ese mensaje con 200 (en vez del
201 de un envío nuevo). Dos cosas a tener en cuenta:
- La key no vence. Queda atada a ese mensaje para siempre: no la reuses para un mensaje distinto.
- No comparamos el body. Si mandás la misma key con otro contenido, te devolvemos el mensaje original y el nuevo no sale.
Vacía o con más de 255 caracteres devuelve
422 invalid_idempotency_key.
Para reembolsos de MercadoPago hay idempotencia interna por
payment_id — reintentar el mismo refund no genera un
segundo reembolso. Ver Cancelar / reembolsar.
Crear un evento de Google Calendar también acepta
Idempotency-Key, con una diferencia: la key vale por
negocio (dos negocios pueden usar el mismo código). Ver
Crear un evento.
Soporte
¿Algo no anda como esperabas? Escribinos a contacto@sabado.cloud. Somos pocos y respondemos rápido — sobre todo si nos das el ID de la request o del evento que falló.