API de usuarios
Crea, actualiza y gestiona perfiles de usuario mediante programación.
Todos los endpoints de esta página son relativos a la URL base: https://api-eu1.joryio.com. Consulta el resumen de la API.
Autenticación
Todas las solicitudes requieren autenticación mediante clave de API:
Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json
Crear o actualizar un usuario
Crea un usuario nuevo o actualiza los atributos de uno existente.
Este endpoint acepta dos formatos de cuerpo: un objeto de usuario único (documentado aquí; devuelve el cuerpo de usuario completo con resúmenes de incorporación detallados) o una matriz JSON de objetos de usuario para operaciones masivas (devuelve un resumen agregado). Consulta operaciones masivas (cuerpo de matriz).
Endpoint
POST /users
Cuerpo de la solicitud
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
externalId | cadena | Uno de externalId / email | Tu identificador único de usuario (máx. 255 caracteres); clave para crear o actualizar. |
email | cadena | Uno de externalId / email | Dirección de email del usuario. |
userId | cadena | No | ID interno de usuario de Joryio (24 hexadecimales, de las respuestas API): solo actualiza, nunca crea (consulta la nota siguiente). Se excluye mutuamente con externalId. |
phone | cadena | No | Número de teléfono del usuario (máx. 20 caracteres). |
attributes | objeto | No | Atributos personalizados de usuario (máx. 200 claves, 50 KB y profundidad de anidación 5). |
subscriptions | matriz | No | Pertenencias a listas de suscripción que se aplicarán en la misma llamada (máx. 100). Consulta suscripciones integradas. |
events | matriz | No | Eventos que se ingerirán en la misma llamada (máx. 25). Consulta eventos integrados. |
userId es el ID interno de Joryio y solo actualizauserId y externalId no son alias. userId es el id interno de 24 caracteres hexadecimales que solo emite Joryio (devuelto como id / userId en las respuestas): al enviarlo, actualiza ese usuario exacto o devuelve 404 si no existe; nunca crea un usuario ni coincide con un externalId. Un userId que no tenga 24 caracteres hexadecimales se rechaza con 400, y enviar userId y externalId en un mismo cuerpo se rechaza con 400. Para crear o actualizar un usuario mediante tu propio identificador, cualquiera que sea su formato, usa externalId.
Suscripciones integradas
Incorporación en una llamada: en vez de hacer una llamada POST /subscriptions/contacts/:userId/lists/:listId independiente por lista, envía las pertenencias directamente. Cada elemento:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
listId | cadena | Sí | ID de lista de suscripción. |
channel | cadena | No | email, sms, whatsapp, push o viber. Predeterminado: email. |
status | cadena | No | subscribed (predeterminado) o unsubscribed. |
Las filas de consentimiento se escriben mediante la misma ruta auditada que el endpoint de suscripción independiente, con fuente api. Hay dos garantías:
- Una exclusión explícita existente para esa lista o canal nunca se restaura de forma silenciosa: se omite el elemento y se informa. Para volver a aceptar un contacto dado de baja se requiere una llamada explícita a
POST /subscriptions/contacts/:userId/lists/:listId. - Los errores por elemento, por ejemplo un
listIddesconocido, se informan en el resumen de respuesta y nunca revierten la actualización del perfil.
Eventos integrados
Cada elemento se ingiere mediante la canalización estándar de eventos; los disparadores de journey, segmentos y analítica funcionan igual que con POST /events/track:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name | cadena | Sí | Nombre del evento (máx. 255 caracteres). Prefiere nombres canónicos como Order Completed. |
properties | objeto | No | Propiedades de evento (mismos límites que el endpoint de seguimiento: máx. de claves, 50 KB y anidación limitada). |
timestamp | cadena o número | No | Cadena ISO 8601 o milisegundos epoch. Predeterminado: ahora. |
Solicitud de ejemplo
curl -X POST https://api-eu1.joryio.com/users \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"externalId": "user_123",
"email": "john.doe@example.com",
"phone": "+1234567890",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium",
"signupDate": "2024-01-15T10:30:00Z",
"customField": "value"
},
"subscriptions": [
{ "listId": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d", "channel": "email" },
{ "listId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "channel": "sms" }
],
"events": [
{
"name": "Order Completed",
"properties": { "orderId": "ord_789", "total": 129.90, "currency": "USD" },
"timestamp": "2024-01-15T10:29:45Z"
},
{ "name": "Product Viewed", "properties": { "productId": "sku_42" } }
]
}'
Respuesta
El objeto de usuario se devuelve directamente, sin envoltorio. id / userId son el identificador interno de Joryio; se devuelve el externalId que enviaste:
{
"id": "665f1e2a9b3c4d5e6f7a8b9c",
"userId": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"email": "john.doe@example.com",
"phone": "+1234567890",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium",
"signupDate": "2024-01-15T10:30:00Z"
},
"segments": [],
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"subscriptions": { "applied": 2, "skipped": [] },
"events": { "accepted": 2, "rejected": [] }
}
Los campos de resumen subscriptions y events aparecen solo si se proporcionaron las entradas correspondientes. Las suscripciones omitidas son objetos { listId, channel, reason }; los eventos rechazados son { name, reason }.
Notas
- Si el usuario existe, se combinan los atributos (se conservan los atributos existentes que no están en la solicitud).
- Establecer un atributo como
nullguardanullcomo valor; no elimina la clave. - Email y teléfono se indexan automáticamente para segmentación.
- Las
subscriptions/eventsintegradas se aplican tras la actualización del perfil; los errores por elemento se informan en los campos de resumen y nunca hacen fallar la llamada ni revierten el usuario.
Obtener un usuario por ID
Recupera el perfil y los atributos de un usuario. Existen dos rutas de consulta:
GET /users/by-user-id/:userId: consulta mediante tu identificador (elexternalIdcon el que creaste al usuario). Es la ruta recomendada para integraciones.GET /users/:userId: consulta mediante el ID interno de Joryio (elidde 24 caracteres hexadecimales devuelto en las respuestas).
Endpoint
GET /users/by-user-id/:userId
Parámetros de ruta
| Parámetro | Tipo | Descripción |
|---|---|---|
userId | cadena | Tu identificador externo (externalId). |
Solicitud de ejemplo
curl -X GET https://api-eu1.joryio.com/users/by-user-id/user_123 \
-H "Authorization: Bearer jry_live_your_api_key"
Respuesta
{
"id": "665f1e2a9b3c4d5e6f7a8b9c",
"userId": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"email": "john.doe@example.com",
"phone": "+1234567890",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium",
"lifetimeValue": 1250.50
},
"segments": [],
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-20T14:20:00.000Z"
}
Listar usuarios
Lista todos los usuarios con paginación. Los resultados se ordenan por última actualización, del más reciente al más antiguo. Este endpoint no admite sintaxis de consulta para filtrar por atributos ni ordenar; usa Segmentos para segmentar por atributos o GET /users/search?query=... para buscar por nombre, email, teléfono o ID.
Endpoint
GET /users
Parámetros de consulta
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
limit | número | 50 | Resultados por página (máx. 200). |
offset | número | 0 | Número de usuarios que se omitirán. |
Solicitud de ejemplo
curl -X GET "https://api-eu1.joryio.com/users?limit=50&offset=0" \
-H "Authorization: Bearer jry_live_your_api_key"
Respuesta
{
"data": [
{
"id": "665f1e2a9b3c4d5e6f7a8b9c",
"userId": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"email": "user1@example.com",
"attributes": {
"plan": "premium"
}
},
{
"id": "665f1e2a9b3c4d5e6f7a8b9d",
"userId": "665f1e2a9b3c4d5e6f7a8b9d",
"externalId": "user_456",
"email": "user2@example.com",
"attributes": {
"plan": "premium"
}
}
],
"pagination": {
"total": 156,
"limit": 50,
"offset": 0,
"hasMore": true
}
}
Actualizar un usuario
Actualiza el email, teléfono o atributos de un usuario sin reemplazar el perfil completo. Los atributos se combinan por clave. Usa PUT (no hay ruta PATCH):
PUT /users/by-user-id/:userId: actualiza mediante tu identificador.PUT /users/:userId: actualiza mediante el ID interno de Joryio.
Endpoint
PUT /users/by-user-id/:userId
Cuerpo de la solicitud
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
email | cadena | No | Dirección de email nueva. |
phone | cadena | No | Número de teléfono nuevo. |
attributes | objeto | No | Atributos que se combinarán (actualización por clave). |
Solicitud de ejemplo
curl -X PUT https://api-eu1.joryio.com/users/by-user-id/user_123 \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"attributes": {
"plan": "enterprise",
"mrr": 499
}
}'
Respuesta
El objeto de usuario actualizado se devuelve directamente:
{
"id": "665f1e2a9b3c4d5e6f7a8b9c",
"userId": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"attributes": {
"firstName": "John",
"plan": "enterprise",
"mrr": 499,
"signupDate": "2024-01-15T10:30:00Z"
},
"updatedAt": "2024-01-20T15:30:00.000Z"
}
Eliminar un usuario
Elimina permanentemente un usuario y todos sus datos asociados.
Endpoint
DELETE /users/:userId
El parámetro de ruta es el ID de usuario interno de Joryio. Si solo tienes tu propio identificador, consúltalo primero mediante GET /users/by-user-id/:userId. Requiere el scope users:delete.
Solicitud de ejemplo
curl -X DELETE https://api-eu1.joryio.com/users/665f1e2a9b3c4d5e6f7a8b9c \
-H "Authorization: Bearer jry_live_your_api_key"
Respuesta
204 No Content: el cuerpo de respuesta está vacío.
Notas
- Esta acción es permanente y no se puede deshacer.
- Elimina el perfil, los eventos y el historial de campañas del usuario.
- El usuario se elimina de todos los segmentos.
- Las campañas activas dejarán de dirigirse a este usuario.
Operaciones masivas (cuerpo de matriz)
No hay un endpoint masivo independiente: POST /users acepta un objeto de usuario único o una matriz JSON de objetos de usuario, sin objeto envoltorio. El formato de matriz crea o actualiza hasta 1000 usuarios en una solicitud.
Endpoint
POST /users
Content-Type: application/json
[ { ...user }, { ...user } ]
Cuerpo de la solicitud
Una matriz JSON de hasta 1000 elementos. Cada elemento sigue el mismo formato que el objeto único, incluidos los campos integrados opcionales subscriptions y events. Los límites se aplican por elemento: máximo 100 suscripciones y 25 eventos en cada uno; una solicitud de 1000 elementos puede llevar como máximo 25 eventos por elemento, el límite no aumenta al agrupar.
Cada elemento recibe una validación completa. Un elemento no válido se informa en failed mediante su índice de matriz, nunca se acepta silenciosamente, y el resto de elementos válidos se procesan de todos modos.
Solicitud de ejemplo
curl -X POST https://api-eu1.joryio.com/users \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '[
{
"externalId": "user_001",
"email": "user1@example.com",
"attributes": { "firstName": "John", "plan": "free" },
"subscriptions": [
{ "listId": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d", "channel": "email" }
],
"events": [
{ "name": "Order Completed", "properties": { "orderId": "ord_789", "total": 129.90 } }
]
},
{
"externalId": "user_002",
"email": "user2@example.com",
"attributes": { "firstName": "Jane", "plan": "premium" }
}
]'
Respuesta
A diferencia del formato de objeto, que devuelve el cuerpo completo de usuario con resúmenes de incorporación detallados, el formato de matriz devuelve un resumen agregado:
{
"processed": 2,
"created": 1,
"updated": 1,
"failed": [],
"subscriptions": { "applied": 1, "skipped": 0 },
"events": { "accepted": 1, "rejected": 0 }
}
Respuesta con errores
{
"processed": 2,
"created": 1,
"updated": 1,
"failed": [
{
"index": 2,
"userId": "user_003",
"reason": "property hacker should not exist"
}
],
"subscriptions": { "applied": 0, "skipped": 0 },
"events": { "accepted": 0, "rejected": 0 }
}
Límites
- Máximo de 1000 usuarios por solicitud.
- Cada elemento recibe la misma validación que el formato de objeto único, incluidas
subscriptions/eventsanidadas. - Límites por elemento: 100 suscripciones y 25 eventos.
- Totales por solicitud: un máximo de 500 eventos integrados y 1000 suscripciones integradas sumados en toda la matriz. Por encima de eso, envía los eventos a
POST /events/track(cuerpo de matriz) y las pertenencias a listas al endpoint de miembros masivos de listas de suscripción. - El procesamiento se realiza en lotes paralelos de 10 para un rendimiento óptimo.
- Se permiten fallos parciales: se procesan los elementos válidos aunque fallen otros, y
faileddetalla cada error mediante el índice de matriz. - Los resultados de incorporación (
subscriptions/events) se agregan como recuentos; usa el formato de objeto único cuando necesites los motivos detallados de omisión o rechazo.
El formato de matriz es para lotes programáticos desde tu backend. Para archivos y migraciones completas, no implementes manualmente bucles de lotes: usa Importación masiva en el dashboard (CSV/JSON con asignación de columnas, deduplicación, reglas de consentimiento e informe de errores) o la sincronización con warehouse para cargas recurrentes.
Eventos de usuario
Obtener eventos de un usuario
Recupera todos los eventos de un usuario concreto.
Endpoint
GET /users/:userId/events
El parámetro de ruta es el ID de usuario interno de Joryio.
Parámetros de consulta
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
limit | número | 50 | Número de eventos que se devolverán (máx. 1000). |
offset | número | 0 | Desplazamiento de paginación. |
startDate | cadena | - | Filtra eventos posteriores a esta fecha (ISO 8601). |
endDate | cadena | - | Filtra eventos anteriores a esta fecha (ISO 8601). |
eventName | cadena | - | Filtra por nombre de evento. |
groupBySession | booleano | false | Devuelve también los eventos agrupados por sesión. |
Solicitud de ejemplo
curl -X GET "https://api-eu1.joryio.com/users/665f1e2a9b3c4d5e6f7a8b9c/events?limit=20" \
-H "Authorization: Bearer jry_live_your_api_key"
Respuesta
Los campos de evento usan snake_case (proceden del almacén de analítica):
{
"data": [
{
"event_id": "9b2f6c1e-4a8d-4f0b-9c3d-2e1f5a6b7c8d",
"event_name": "Order Completed",
"properties": {
"orderId": "order_456",
"total": 99.99
},
"timestamp": "2024-01-20 14:30:00"
},
{
"event_id": "1c3e5a7b-9d2f-4b6c-8e0a-3f5d7b9c1e2a",
"event_name": "Page Viewed",
"properties": {
"page": "/pricing"
},
"timestamp": "2024-01-20 14:25:00"
}
],
"total": 156,
"limit": 20,
"offset": 0
}
Atributos comunes
Campos y atributos especiales
email y phone son campos de perfil de nivel superior, no atributos; envíalos en el nivel superior del cuerpo de la solicitud.
Estos atributos tienen un significado especial en Joryio:
| Atributo | Tipo | Descripción |
|---|---|---|
firstName | cadena | Nombre del usuario (se usa en búsqueda y visualización). |
lastName | cadena | Apellido del usuario (se usa en búsqueda y visualización). |
language | cadena | Idioma preferido (los SDK lo establecen automáticamente cuando está disponible). |
timezone | cadena | Zona horaria del usuario en formato IANA (controla las horas tranquilas y las entregas de journeys en hora local). |
country | cadena | Código de país (indexado para segmentación). |
Atributos personalizados
Puedes añadir atributos personalizados ilimitados:
{
"attributes": {
"plan": "premium",
"mrr": 99,
"signupSource": "google_ads",
"lifetimeValue": 1250.50,
"tags": ["vip", "early-adopter"],
"preferences": {
"emailNotifications": true,
"smsNotifications": false
}
}
}
Tipos de datos compatibles
- Cadena:
"premium". - Número:
99.99. - Booleano:
true/false. - Fecha:
"2024-01-15T10:30:00Z"(ISO 8601). - Matriz:
["tag1", "tag2"]. - Objeto:
{ "nested": "value" }.
Respuestas de error
Todos los errores usan el cuerpo de error estándar. Consulta resumen de la API: respuesta de error.
400 Solicitud incorrecta
{
"statusCode": 400,
"message": "Cannot create or update a user without a valid identifier (externalId or email to create; userId only updates an existing user)",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/users"
}
401 No autorizado
{
"statusCode": 401,
"message": "Invalid or expired API key",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/users"
}
404 No encontrado
{
"statusCode": 404,
"message": "User with userId 'user_123' not found",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/users/by-user-id/user_123"
}
Prácticas recomendadas
1. Los reintentos son seguros: POST /users es un upsert
POST /users usa tu userId como clave: al reintentar la misma solicitud, se actualiza el mismo perfil en vez de crear un duplicado. No hay encabezado Idempotency-Key; vuelve a intentar la solicitud tal cual ante fallos de red:
curl -X POST https://api-eu1.joryio.com/users \
-H "Authorization: Bearer jry_live_your_api_key" \
-d '{...}'
2. Nombres de atributos
Usa nombres de atributos coherentes y descriptivos:
Bien:
{
"signupDate": "2024-01-15",
"lifetimeValue": 1250.50,
"plan": "premium"
}
Mal:
{
"sd": "2024-01-15",
"ltv": 1250.50,
"p": "premium"
}
3. Formato de número de teléfono
Usa siempre el formato E.164 para números de teléfono:
Bien: "+1234567890".
Mal: "(123) 456-7890", "123-456-7890".
Límites de frecuencia
La API de usuarios no tiene hoy límites de frecuencia fijos por endpoint. Consulta resumen de la API: límites de frecuencia para conocer el comportamiento de toda la plataforma y cómo gestionar respuestas 429.