Saltar al contenido principal

Resumen de la API

La API REST de Joryio ofrece acceso mediante programación a todas las funciones de la plataforma.

Base URL​

https://api-eu1.joryio.com/api

Actualmente, todos los espacios de trabajo se sirven desde una única región; los endpoints específicos por región se documentarán cuando se habiliten regiones adicionales.

Autenticación​

Todas las solicitudes de la API requieren autenticación mediante una clave de API. Las claves se limitan a un único espacio de trabajo, incluyen un conjunto explícito de permisos y pueden restringirse a una lista de IP. Consulta la referencia de Claves de API para ver el catálogo completo de permisos y el comportamiento de la lista de IP permitidas.

GET /api/users/by-user-id/user_123
Host: api-eu1.joryio.com
Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

Envía la clave como token Bearer en el encabezado Authorization de cada solicitud. Las claves siempre empiezan por jry_live_ (producción) o jry_test_ (pruebas). El prefijo visible de la clave (por ejemplo, jry_live_98f31a72) se puede registrar de forma segura; el resto es secreto.

Obtén tu clave de API​

  1. Inicia sesión en el dashboard de Joryio.
  2. Ve a Configuración → Claves de API.
  3. Haz clic en Crear clave de API, elige los permisos que necesita la integración y copia el valor que se muestra una única vez.
Mantén las claves de API en secreto

No incluyas nunca claves de API en el control de versiones ni las expongas en código del lado cliente. El valor completo se muestra una sola vez después de crearlo; guárdalo inmediatamente en tu gestor de secretos.

Colección de Postman​

La forma más rápida de explorar la API es importar la colección oficial en Postman. Incluye todos los endpoints públicos con un cuerpo de ejemplo, ya configurados con una variable {{baseUrl}} y autenticación mediante token Bearer.

  1. Descarga la colección.
  2. En Postman, elige Importar y suelta el archivo.
  3. Configura las variables de la colección: baseUrl = https://api-eu1.joryio.com/api y token = tu clave de API (jry_live_...).

Formato de las solicitudes​

Todas las solicitudes y respuestas usan JSON:

POST /users/track
Content-Type: application/json

{
"attributes": {
"externalId": "user_123",
"email": "[email protected]",
"attributes": {
"plan": "premium"
}
}
}

Formato de las respuestas​

Los endpoints devuelven directamente el JSON del recurso; no existe un envoltorio como { "success": true, "data": ... }.

Respuesta correcta​

Por ejemplo, GET /users/by-user-id/user_123 devuelve el propio objeto de usuario:

{
"id": "665f1e2a9b3c4d5e6f7a8b9c",
"userId": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"email": "[email protected]",
"phone": "+14155550123",
"attributes": { "plan": "premium" },
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z"
}

id / userId son el identificador interno de Joryio; el identificador que proporcionaste se devuelve como externalId.

Respuesta de error​

Todos los errores comparten una misma estructura, generada por un filtro global de excepciones:

{
"statusCode": 400,
"message": "Cannot create user without a valid identifier (userId, externalId, or email)",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/users"
}

Los errores de validación de solicitudes (400) incluyen además una matriz errors con un mensaje por cada campo que no supera la validación:

{
"statusCode": 400,
"message": "Bad Request Exception",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/api/users/track",
"errors": [
"eventName must be shorter than or equal to 500 characters"
]
}

Errores en el cuerpo de la solicitud​

Un cuerpo que el servidor no puede leer se rechaza antes de llegar al endpoint, con un message que indica el problema. El cuerpo que enviaste nunca se devuelve en la respuesta.

EstadomessageCausa
400Request body is not valid JSON.El JSON tiene un error de sintaxis.
400Request body must be a JSON object or array - a bare string, number, boolean or null is not accepted.El nivel superior no es un objeto {...} ni un array [...].
413Request body is too large - the limit is 1 MB.El cuerpo supera 1 MB.
415Request body charset is not supported - send UTF-8.El Content-Type indica un charset distinto de UTF-8.

Códigos de estado HTTP​

CódigoSignificadoDescripción
200OKLa solicitud se realizó correctamente
201CreatedEl recurso se creó correctamente
204No ContentLa eliminación se realizó correctamente (cuerpo de respuesta vacío)
400Bad RequestParámetros de solicitud no válidos
401UnauthorizedClave de API no válida o ausente
403ForbiddenLa clave de API no tiene los permisos necesarios
404Not FoundNo se encontró el recurso
409ConflictEl recurso ya existe
413Payload Too LargeCuerpo de la solicitud mayor de 1 MB
415Unsupported Media TypeCharset o codificación del cuerpo no compatible
429Too Many RequestsSe superó el límite de velocidad
500Internal Server ErrorSe produjo un error de servidor
503Service UnavailableEl servicio no está disponible temporalmente

Límites de velocidad​

Los endpoints autenticados de la API aplican un límite por organización. Son un techo contra el abuso, no un presupuesto de rendimiento: están muy por encima del uso normal, y la capacidad la gestiona nuestra flota de workers, no el rechazo de peticiones en el borde.

SuperficieLímitePor
Peticiones a la API1.200/mintu organización
Ingesta de contactos y eventos (POST /users/track)6.000/mintu organización
Inicio de sesión y restablecimiento5-10/mindirección IP

Los límites autenticados se aplican por organización, no por IP: así una flota de servidores comparte un único presupuesto en lugar de que cada servidor tenga el suyo, y dos clientes tras la misma red nunca se afectan entre sí.

Los límites actuales de tu cuenta se muestran en Configuración -> Uso y pueden ampliarse. Si una importación masiva o un envío intenso se acerca a uno, escribe a [email protected].

Los receptores de webhooks entrantes - eventos de entrega, respuestas, callbacks de plataformas de comercio - no tienen límite, deliberadamente. Un webhook rechazado es una pérdida de datos, así que esos endpoints se protegen con verificación de firma en lugar de un contador.

X-RateLimit-Limit: 1200
X-RateLimit-Remaining: 1188
X-RateLimit-Reset: 60
HTTP/1.1 429 Too Many Requests
Retry-After: 42
{
"statusCode": 429,
"message": "Too Many Requests",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/auth/login"
}

Gestionar los límites de velocidad​

Los límites pueden introducirse o hacerse más estrictos con el tiempo. Trata siempre 429 como reintentable, respeta Retry-After e implementa un retroceso exponencial:

async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await sleep(retryAfter * 1000);
continue;
}

return response;
}
}

Paginación​

Los endpoints de lista se paginan con los parámetros de consulta limit / offset:

GET /users?limit=50&offset=100

Parámetros:

  • limit: resultados por página (los valores predeterminados y máximos varían por endpoint: usuarios, predeterminado 50 y máximo 200; segmentos, predeterminado y máximo 100; consulta de eventos, predeterminado 100 y máximo 1000).
  • offset: número de elementos que se omiten (predeterminado: 0).

Respuesta:

Las respuestas de lista paginadas incluyen la página en una matriz data y un objeto pagination:

{
"data": [...],
"pagination": {
"total": 1234,
"limit": 50,
"offset": 100,
"hasMore": true
}
}

Algunos endpoints incluyen campos de paginación adicionales (como page / totalPages) y algunas listas pequeñas devuelven una matriz JSON sin envoltorio. La página de cada endpoint documenta su estructura exacta.

Filtrado​

No hay una sintaxis de consulta genérica filter[field] o sort. En su lugar, los endpoints de lista exponen parámetros de filtro específicos para cada endpoint, por ejemplo:

GET /events/query?eventName=Order+Completed&startDate=2026-01-01&endDate=2026-01-31
GET /segments?q=vip&status=active&tags=onboarding
GET /users/search?query=jane

Los resultados se devuelven en un orden fijo, del más reciente al más antiguo.

Idempotencia​

No existe un encabezado de solicitud Idempotency-Key genérico. La seguridad de los reintentos se proporciona en cada endpoint:

  • POST /users/track es un upsert basado en tu externalId - reintentar la misma solicitud actualiza el mismo perfil en vez de crear un duplicado.
  • Cada elemento de events acepta un clientEventId opcional; se utiliza como ID del evento almacenado, por lo que una solicitud reintentada con el mismo clientEventId se deduplica.
  • POST /campaigns/transactional/send acepta una idempotencyKey opcional en el cuerpo; un reintento con la misma clave no realizará un envío duplicado.

Marcas de tiempo​

Todas las marcas de tiempo están en formato ISO 8601 y usan la zona horaria UTC:

{
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T14:45:30.000Z"
}

Endpoints de la API​

API de usuarios​

MétodoEndpointDescripción
POST/users/trackCrea o actualiza personas y registra sus eventos, compras y dispositivos push: cada campo acepta un objeto o una matriz (máximo 1000 attributes por solicitud)
GET/usersEnumera usuarios (limit / offset)
GET/users/searchBusca usuarios por email, nombre, teléfono o ID
GET/users/:userIdObtiene un usuario por ID interno de Joryio
GET/users/by-user-id/:userIdObtiene un usuario por tu userId
PUT/users/:userIdActualiza un usuario por ID interno
PUT/users/by-user-id/:userIdActualiza un usuario por tu userId
DELETE/users/:userIdElimina un usuario (devuelve 204)

API de eventos​

MétodoEndpointDescripción
POST/users/trackRegistra uno o varios eventos: events acepta un objeto o una matriz (máximo 500 por solicitud)
GET/events/queryConsulta eventos con filtros
POST/events/aggregateAgrega métricas de eventos a lo largo del tiempo

API de campañas​

MétodoEndpointDescripción
POST/campaignsCrea una campaña
GET/campaigns/:idObtiene una campaña
PUT/campaigns/:idActualiza una campaña
DELETE/campaigns/:idElimina una campaña
POST/campaigns/:id/sendEnvía una campaña
GET/campaigns/:id/statsObtiene las estadísticas de una campaña

API de segmentos​

MétodoEndpointDescripción
POST/segmentsCrea un segmento
GET/segmentsEnumera segmentos
GET/segments/:idObtiene un segmento
PUT/segments/:idActualiza un segmento
POST/segments/:id/archiveArchiva un segmento (los segmentos no se pueden eliminar de forma definitiva)
GET/segments/:id/usersObtiene los usuarios de un segmento
GET/segments/:id/sizeObtiene el tamaño de un segmento

API de aplicaciones​

MétodoEndpointDescripción
POST/appsCrea una aplicación
GET/apps/:idObtiene una aplicación
PUT/apps/:idActualiza una aplicación
DELETE/apps/:idElimina una aplicación
POST/apps/:id/regenerate-keyRegenera la clave de SDK
GET/apps/:id/statsObtiene las estadísticas de una aplicación

SDK​

Para integrarte más fácilmente, usa nuestros SDK oficiales:

Ejemplos​

Crear un usuario​

curl -X POST https://api-eu1.joryio.com/api/users/track \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"attributes": {
"externalId": "user_123",
"email": "[email protected]",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium"
}
}
}'

Registrar un evento​

curl -X POST https://api-eu1.joryio.com/api/users/track \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"events": {
"externalId": "user_123",
"name": "Order Completed",
"properties": { "orderId": "order_456", "total": 99.99 }
}
}'

Crear un segmento​

curl -X POST https://api-eu1.joryio.com/api/segments \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Users",
"description": "Users on premium plan",
"filterGroups": [{
"filters": [{
"type": "attribute",
"field": "plan",
"operator": "equals",
"value": "premium"
}],
"operator": "AND"
}],
"groupOperator": "AND"
}'

Enviar una campaña​

El endpoint de envío no acepta un cuerpo de solicitud: la configuración guardada de la campaña determina qué se envía.

curl -X POST https://api-eu1.joryio.com/api/campaigns/:id/send \
-H "Authorization: Bearer jry_live_your_api_key"

Errores​

No existe un vocabulario de códigos de error independiente y legible por máquinas. Usa el código de estado HTTP junto con el campo message del cuerpo de error estándar (consulta Formato de las respuestas):

{
"statusCode": 404,
"message": "Segment with ID 3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d not found",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d"
}

Pruebas​

Las claves pueden crearse con una etiqueta test (jry_test_...) para distinguir de un vistazo las claves de integración de las claves de producción; la etiqueta no cambia lo que puede hacer la clave. Para experimentar de forma segura, crea un espacio de trabajo independiente para las pruebas: los espacios de trabajo aíslan por completo perfiles, eventos y campañas, de modo que nada de lo que pruebes afecte a los datos ni a los destinatarios de producción. Los editores de campañas incluyen envíos de prueba por canal (emails de prueba y mensajes SMS de prueba).

Soporte​

¿Necesitas ayuda?