Flujo OAuth (Connect Apps)

Cómo tu app obtiene credenciales para operar en nombre de un workspace de IxiChat. Patrón estándar OAuth 2.0 código de autorización: el dueño del workspace autoriza desde una pantalla de consent, vos recibís un code, lo intercambias por un api_key.

Antes de empezar

Necesitás una Connect App registrada. Hay dos formas:

  • Self-service: registrá tu app vos mismo en /app/developers/new. Queda en draft hasta que un admin de IxiChat la apruebe.
  • Curada por admin: si sos partner formal, contactanos en ventas@ixichat.com y la registramos por vos directo en activo.

El client_secret se ve UNA SOLA VEZ

Cuando creás la app, IxiChat te devuelve el client_secret y solo lo muestra ese momento. Guardalo en una env var del servidor de tu app. Si lo perdés, rotalo (botón "Rotar secret" en la página de la app) y actualizá las apps que dependen.

El flujo paso a paso

1. Redirigí al usuario a la pantalla de consent

Desde tu app, abrí la URL https://ixichat.com/connect/<tu-slug> en una nueva pestaña, popup o redirect full-page. Pasale dos query params obligatorios:

ParamDescripción
redirect_uriURL absoluta de tu app donde IxiChat devuelve al usuario tras autorizar. DEBE estar en la lista de redirect_uris registrados.
stateToken CSRF random que vos generás. IxiChat te lo echa de vuelta — verificá que matchea el de tu sesión antes de seguir.
text
https://ixichat.com/connect/mi-app?redirect_uri=https%3A%2F%2Fmiapp.com%2Fixichat%2Fcallback&state=abc123xyz

2. El usuario autoriza

IxiChat le muestra una pantalla de consent con el nombre de tu app, los scopes que pediste, y un botón "Autorizar". El usuario elige cuál de sus workspaces te conecta (si tiene varios) y un canal default (típicamente WhatsApp).

3. Recibís el code en tu redirect_uri

IxiChat redirige al usuario a tu redirect_uri agregando dos params:

text
GET https://miapp.com/ixichat/callback?code=cnct_<48-chars>&state=abc123xyz

Verificá state contra el que generaste en el paso 1. Si no matchea: rechazá la request (probable CSRF).

4. Intercambiá el code por credenciales

Desde tu backend (NO desde el browser — el client_secret no puede viajar al cliente):

POST/api/connect/exchange
bash
curl -X POST https://ixichat.com/api/connect/exchange \
  -H "Content-Type: application/json" \
  -d '{
    "code": "cnct_<el-code-recibido>",
    "redirect_uri": "https://miapp.com/ixichat/callback",
    "client_id": "cid_<tu-client-id>",
    "client_secret": "ixc_sec_<tu-secret>"
  }'

Respuesta:

json
{
  "tenant_id": "...",
  "tenant_slug": "ganando",
  "tenant_name": "Ganando",
  "api_key": "ixc_live_<...>",
  "webhook_url": "https://miapp.com/api/webhooks/ixichat",
  "webhook_secret": "whsec_<...>",
  "default_channel": {
    "id": "...",
    "name": "Soporte Ganando",
    "phone": "18091234567",
    "type": "whatsapp"
  },
  "scopes": ["read", "messages.send", "contacts.write", "conversations.write"]
}

Guarda esto bien

  • El api_key es lo que usás para todas las llamadas a la API (Authorization: Bearer ixc_live_...). Solo se muestra una vez.
  • El webhook_secret es para verificar que los webhooks que recibís vienen de IxiChat (HMAC SHA-256).
  • Persisten por workspace. Si el mismo cliente te conecta varios workspaces, cada uno tiene su par.

Refresh y revoke

Rotar el api_key (refresh)

Los api_key tienen TTL de 1 año. Para rotarlo antes (mejor práctica: hacerlo cada 60-90 días):

POST/api/connect/refresh
bash
curl -X POST https://ixichat.com/api/connect/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "cid_...",
    "client_secret": "ixc_sec_...",
    "api_key": "ixc_live_<vigente>"
  }'

Respuesta: { api_key: "<nuevo>", expires_at }. El api_key viejo queda revocado al instante.

Uninstall (revoke)

Si tu app necesita "desconectarse" de un workspace (el usuario canceló su subscripción a tu app, etc.):

POST/api/connect/revoke
bash
curl -X POST https://ixichat.com/api/connect/revoke \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "cid_...",
    "client_secret": "ixc_sec_...",
    "api_key": "ixc_live_<a-revocar>"
  }'

Idempotente. Devuelve { revoked: true, already?: true }.

Scopes

ScopePermite
readLeer conversaciones, contactos y meta del workspace.
messages.sendEnviar mensajes salientes en nombre del tenant.
contacts.writeCrear y actualizar contactos.
conversations.writeCambiar estado de conversaciones (asignar, resolver, etc.).
flows.runDisparar flujos automatizados.
campaigns.manageCrear y enviar campañas (broadcasts).
webhooks.manageGestionar webhooks salientes.
*Acceso completo. Solo admin curated puede pedirlo.

Errores comunes

StatusErrorCausa
400invalid_bodyFaltan campos requeridos o tipos incorrectos.
401invalid_clientclient_id no existe.
401invalid_client_secretEl secret no matchea el hash registrado.
403app_not_activeTu app está en draft/suspended/revoked.
403code_app_mismatchEl code fue emitido para otra app (intento de cross-app theft).
404code_not_foundEl code no existe (ya expiró, o nunca lo emitimos).
410code_already_usedEl code ya se intercambió. Cada code es one-time.
410code_expiredEl code expiró (TTL 10 min).