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
drafthasta 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
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:
| Param | Descripción |
|---|---|
redirect_uri | URL absoluta de tu app donde IxiChat devuelve al usuario tras autorizar. DEBE estar en la lista de redirect_uris registrados. |
state | Token CSRF random que vos generás. IxiChat te lo echa de vuelta — verificá que matchea el de tu sesión antes de seguir. |
https://ixichat.com/connect/mi-app?redirect_uri=https%3A%2F%2Fmiapp.com%2Fixichat%2Fcallback&state=abc123xyz2. 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:
GET https://miapp.com/ixichat/callback?code=cnct_<48-chars>&state=abc123xyzVerificá 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):
/api/connect/exchangecurl -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:
{
"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_keyes lo que usás para todas las llamadas a la API (Authorization: Bearer ixc_live_...). Solo se muestra una vez. - El
webhook_secretes 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):
/api/connect/refreshcurl -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.):
/api/connect/revokecurl -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
| Scope | Permite |
|---|---|
read | Leer conversaciones, contactos y meta del workspace. |
messages.send | Enviar mensajes salientes en nombre del tenant. |
contacts.write | Crear y actualizar contactos. |
conversations.write | Cambiar estado de conversaciones (asignar, resolver, etc.). |
flows.run | Disparar flujos automatizados. |
campaigns.manage | Crear y enviar campañas (broadcasts). |
webhooks.manage | Gestionar webhooks salientes. |
* | Acceso completo. Solo admin curated puede pedirlo. |
Errores comunes
| Status | Error | Causa |
|---|---|---|
| 400 | invalid_body | Faltan campos requeridos o tipos incorrectos. |
| 401 | invalid_client | client_id no existe. |
| 401 | invalid_client_secret | El secret no matchea el hash registrado. |
| 403 | app_not_active | Tu app está en draft/suspended/revoked. |
| 403 | code_app_mismatch | El code fue emitido para otra app (intento de cross-app theft). |
| 404 | code_not_found | El code no existe (ya expiró, o nunca lo emitimos). |
| 410 | code_already_used | El code ya se intercambió. Cada code es one-time. |
| 410 | code_expired | El code expiró (TTL 10 min). |