Saltar al contenido principal

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

CampoTipoObligatorioDescripción
externalIdcadenaUno de externalId / emailTu identificador único de usuario (máx. 255 caracteres); clave para crear o actualizar.
emailcadenaUno de externalId / emailDirección de email del usuario.
userIdcadenaNoID interno de usuario de Joryio (24 hexadecimales, de las respuestas API): solo actualiza, nunca crea (consulta la nota siguiente). Se excluye mutuamente con externalId.
phonecadenaNoNúmero de teléfono del usuario (máx. 20 caracteres).
attributesobjetoNoAtributos personalizados de usuario (máx. 200 claves, 50 KB y profundidad de anidación 5).
subscriptionsmatrizNoPertenencias a listas de suscripción que se aplicarán en la misma llamada (máx. 100). Consulta suscripciones integradas.
eventsmatrizNoEventos que se ingerirán en la misma llamada (máx. 25). Consulta eventos integrados.
userId es el ID interno de Joryio y solo actualiza

userId 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:

CampoTipoObligatorioDescripción
listIdcadenaID de lista de suscripción.
channelcadenaNoemail, sms, whatsapp, push o viber. Predeterminado: email.
statuscadenaNosubscribed (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 listId desconocido, 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:

CampoTipoObligatorioDescripción
namecadenaNombre del evento (máx. 255 caracteres). Prefiere nombres canónicos como Order Completed.
propertiesobjetoNoPropiedades de evento (mismos límites que el endpoint de seguimiento: máx. de claves, 50 KB y anidación limitada).
timestampcadena o númeroNoCadena 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 null guarda null como valor; no elimina la clave.
  • Email y teléfono se indexan automáticamente para segmentación.
  • Las subscriptions / events integradas 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 (el externalId con el que creaste al usuario). Es la ruta recomendada para integraciones.
  • GET /users/:userId: consulta mediante el ID interno de Joryio (el id de 24 caracteres hexadecimales devuelto en las respuestas).

Endpoint

GET /users/by-user-id/:userId

Parámetros de ruta

ParámetroTipoDescripción
userIdcadenaTu 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ámetroTipoPredeterminadoDescripción
limitnúmero50Resultados por página (máx. 200).
offsetnúmero0Nú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

CampoTipoObligatorioDescripción
emailcadenaNoDirección de email nueva.
phonecadenaNoNúmero de teléfono nuevo.
attributesobjetoNoAtributos 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 / events anidadas.
  • 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 failed detalla 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ámetroTipoPredeterminadoDescripción
limitnúmero50Número de eventos que se devolverán (máx. 1000).
offsetnúmero0Desplazamiento de paginación.
startDatecadena-Filtra eventos posteriores a esta fecha (ISO 8601).
endDatecadena-Filtra eventos anteriores a esta fecha (ISO 8601).
eventNamecadena-Filtra por nombre de evento.
groupBySessionbooleanofalseDevuelve 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:

AtributoTipoDescripción
firstNamecadenaNombre del usuario (se usa en búsqueda y visualización).
lastNamecadenaApellido del usuario (se usa en búsqueda y visualización).
languagecadenaIdioma preferido (los SDK lo establecen automáticamente cuando está disponible).
timezonecadenaZona horaria del usuario en formato IANA (controla las horas tranquilas y las entregas de journeys en hora local).
countrycadenaCó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.


Siguientes pasos