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.

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

ConceptoQué 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:

ScopeHabilita
tenants.readListar / ver negocios.
tenants.writeCrear y desconectar negocios.
messages.sendEnviar mensajes (WhatsApp, Instagram y Messenger), marcar como leído y "escribiendo…".
messages.readConsultar estado de un mensaje, leer el historial de coexistencia y descargar media recibida.
business.readPerfil del negocio, estado del número y estadísticas.
business.writeEditar el perfil del negocio y re-registrar el número.
social.readEstado de conexión de Instagram y Messenger.
social.writeDesconectar Instagram o Messenger.
templates.readListar / ver plantillas.
templates.writeCrear y borrar plantillas.
mercadopago.readConsultar estado de conexión de MercadoPago.
mercadopago.writeIniciar conexión MP, crear preferencias de cobro, hacer reembolsos.
mail.readListar dominios / casillas / alias y leer mensajes.
mail.writeCrear/borrar dominios, casillas y alias; enviar y borrar mensajes.
arca.readEstado de facturación, último número y comprobantes emitidos.
arca.writeEmitir comprobantes electrónicos (facturas C / A / B).
calendar.readEstado de Google Calendar, calendarios, eventos y horarios ocupados.
calendar.writeConectar / 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.

HTTPErrorQué pasó
401missing_api_keyFalta el header Authorization: Bearer ….
401invalid_api_keyLa API key no existe o fue revocada.
403insufficient_scopeLa API key no tiene el scope que pide el endpoint. Ver Scopes.
403project_not_activeLa cuenta de esa API key está desactivada.
403plan_not_includedEl 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.
403meta_permission_deniedInstagram o Messenger: Meta rechazó el envío por permisos de la página.
402subscription_suspendedLa suscripción de la cuenta está suspendida (cancelada o con el cobro pausado). Aplica solo a planes pagos; se reactiva desde el panel.
402subscription_requiredLa operación (conectar WhatsApp, conectar dominio de correo) requiere la suscripción activa de un plan pago.
404tenant_not_foundEl tenant_ref no existe en la cuenta de esa API key. Cada key ve solo los negocios de su cuenta.
404message_not_found / template_not_found / voucher_not_foundEl mensaje, la plantilla o el comprobante no existen para ese negocio.
404payment_not_foundEl pago de Mercado Pago no existe o no es de ese comercio.
404domain_not_found / account_not_foundEl dominio o la casilla de correo no pertenecen a ese negocio.
409tenant_not_connectedEl negocio existe pero no tiene WhatsApp conectado. Completá el onboarding primero.
409meta_outside_session_windowPasaron más de 24 horas desde el último mensaje del contacto: para escribirle hay que usar una plantilla aprobada.
409duplicate_external_refYa hay un negocio con ese external_ref en tu cuenta.
409not_connectedPediste desconectar un negocio que no tiene nada conectado.
409channel_not_connected / outside_messaging_windowInstagram o Messenger: el canal no está conectado, o se cerró la ventana de 24 horas. Ver Instagram y Messenger.
409mp_not_connectedEl negocio no tiene MercadoPago conectado (no completó OAuth o el token fue revocado). Mandale el connect_url.
409payment_not_refundableEl 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.
409arca_not_connected / delegation_pendingEl 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.
422invalid_payloadAlgún campo no cumple las reglas de Meta (vertical inválido, websites > 2, etc).
422invalid_idempotency_keyEl header Idempotency-Key vino vacío o con más de 255 caracteres.
422meta_recipient_unreachableMeta 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).
422meta_template_invalidMeta rechazó la plantilla del envío (nombre, idioma o parámetros que no coinciden). Ver message.
422quota_exceededSe 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.
422cae_rejectedARCA rechazó el comprobante. El detalle de las observaciones va en message.
423meta_account_lockedSolo en /v1/phone-number/register: la cuenta sigue bloqueada (131031) después del intento.
429rate_limitedPasaste 60 req/min con esa API key. Esperá lo que diga Retry-After y reintentá.
429meta_rate_limitedEl límite es de Meta, no nuestro: el número está mandando demasiado rápido. Esperá unos segundos.
502meta_otherMeta devolvió un error que no mapeamos a un código específico. Mirá meta_code en la respuesta.
502meta_disconnect_failedMeta rechazó la desconexión. No marcamos nada de nuestro lado: el negocio sigue conectado. Reintentá.
502refund_failedMercadoPago rechazó el reembolso (pago no reembolsable, ya reembolsado, etc.). Ver message.
502imap_error / smtp_errorFalló la lectura (IMAP) o el envío (SMTP) de un correo. Ver message.
503meta_token_invalidEl acceso al WhatsApp del negocio se perdió. Tiene que reconectar el número.
503network_errorNo pudimos hablar con el proveedor (Meta, MercadoPago, ARCA, el servidor de correo). Reintentá con backoff.
503not_configuredEl servicio (correo / facturación / cobros) no está habilitado todavía. Escribinos.
500internal_errorAlgo 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:

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ó.