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
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 /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
- Inicia sesión en el dashboard de Joryio.
- Ve a Configuración → Claves de API.
- 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.
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.
- Descarga la colección.
- En Postman, elige Importar y suelta el archivo.
- Configura las variables de la colección:
baseUrl=https://api-eu1.joryio.comytoken= tu clave de API (jry_live_...).
Formato de las solicitudes
Todas las solicitudes y respuestas usan JSON:
POST /users
Content-Type: application/json
{
"userId": "user_123",
"email": "user@example.com",
"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": "user@example.com",
"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": "/events/track",
"errors": [
"eventName must be shorter than or equal to 500 characters"
]
}
Códigos de estado HTTP
| Código | Significado | Descripción |
|---|---|---|
200 | OK | La solicitud se realizó correctamente |
201 | Created | El recurso se creó correctamente |
204 | No Content | La eliminación se realizó correctamente (cuerpo de respuesta vacío) |
400 | Bad Request | Parámetros de solicitud no válidos |
401 | Unauthorized | Clave de API no válida o ausente |
403 | Forbidden | La clave de API no tiene los permisos necesarios |
404 | Not Found | No se encontró el recurso |
409 | Conflict | El recurso ya existe |
429 | Too Many Requests | Se superó el límite de velocidad |
500 | Internal Server Error | Se produjo un error de servidor |
503 | Service Unavailable | El servicio no está disponible temporalmente |
Límites de velocidad
Actualmente, los endpoints principales de la API (usuarios, eventos, segmentos y campañas) no aplican límites de velocidad fijos por endpoint. La limitación se aplica a las superficies propensas a abusos - endpoints de autenticación y receptores de webhooks entrantes - mediante ventanas fijas por minuto.
Cuando una solicitud se limita, la API responde 429 Too Many Requests con un encabezado Retry-After (los segundos hasta que se reinicia la ventana):
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 /userses un upsert basado en tuuserId: reintentar la misma solicitud actualiza el mismo perfil en vez de crear un duplicado.POST /events/trackacepta unclientEventIdopcional. Se utiliza como ID del evento almacenado, por lo que se deduplica una solicitud reintentada con el mismoclientEventId.POST /campaigns/transactional/sendacepta unaidempotencyKeyopcional 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étodo | Endpoint | Descripción |
|---|---|---|
| POST | /users | Crea o actualiza un usuario (cuerpo como objeto) o varios (cuerpo como matriz sin envoltorio, máximo 1000) |
| GET | /users | Enumera usuarios (limit / offset) |
| GET | /users/search | Busca usuarios por email, nombre, teléfono o ID |
| GET | /users/:userId | Obtiene un usuario por ID interno de Joryio |
| GET | /users/by-user-id/:userId | Obtiene un usuario por tu userId |
| PUT | /users/:userId | Actualiza un usuario por ID interno |
| PUT | /users/by-user-id/:userId | Actualiza un usuario por tu userId |
| DELETE | /users/:userId | Elimina un usuario (devuelve 204) |
API de eventos
| Método | Endpoint | Descripción |
|---|---|---|
| POST | /events/track | Registra un evento (cuerpo como objeto) o varios (cuerpo como matriz sin envoltorio, máximo 500) |
| GET | /events/query | Consulta eventos con filtros |
| POST | /events/aggregate | Agrega métricas de eventos a lo largo del tiempo |
API de campañas
| Método | Endpoint | Descripción |
|---|---|---|
| POST | /campaigns | Crea una campaña |
| GET | /campaigns/:id | Obtiene una campaña |
| PUT | /campaigns/:id | Actualiza una campaña |
| DELETE | /campaigns/:id | Elimina una campaña |
| POST | /campaigns/:id/send | Envía una campaña |
| GET | /campaigns/:id/stats | Obtiene las estadísticas de una campaña |
API de segmentos
| Método | Endpoint | Descripción |
|---|---|---|
| POST | /segments | Crea un segmento |
| GET | /segments | Enumera segmentos |
| GET | /segments/:id | Obtiene un segmento |
| PUT | /segments/:id | Actualiza un segmento |
| POST | /segments/:id/archive | Archiva un segmento (los segmentos no se pueden eliminar de forma definitiva) |
| GET | /segments/:id/users | Obtiene los usuarios de un segmento |
| GET | /segments/:id/size | Obtiene el tamaño de un segmento |
API de aplicaciones
| Método | Endpoint | Descripción |
|---|---|---|
| POST | /apps | Crea una aplicación |
| GET | /apps/:id | Obtiene una aplicación |
| PUT | /apps/:id | Actualiza una aplicación |
| DELETE | /apps/:id | Elimina una aplicación |
| POST | /apps/:id/regenerate-key | Regenera la clave de SDK |
| GET | /apps/:id/stats | Obtiene las estadísticas de una aplicación |
SDK
Para integrarte más fácilmente, usa nuestros SDK oficiales:
- SDK web: npm install @joryio/web-sdk
- SDK para iOS: Swift Package / CocoaPods
- SDK para Android: Gradle
- SDK para React Native: npm install @joryio/react-native-sdk
Ejemplos
Crear un usuario
curl -X POST https://api-eu1.joryio.com/users \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_123",
"email": "user@example.com",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium"
}
}'
Registrar un evento
curl -X POST https://api-eu1.joryio.com/events/track \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_123",
"eventName": "Order Completed",
"properties": {
"orderId": "order_456",
"total": 99.99,
"currency": "USD"
}
}'
Crear un segmento
curl -X POST https://api-eu1.joryio.com/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/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?