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

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

  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 y token = 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ó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
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

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 /users es un upsert basado en tu userId: reintentar la misma solicitud actualiza el mismo perfil en vez de crear un duplicado.
  • POST /events/track acepta un clientEventId opcional. Se utiliza como ID del evento almacenado, por lo que se deduplica una solicitud reintentada con el mismo clientEventId.
  • 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/usersCrea o actualiza un usuario (cuerpo como objeto) o varios (cuerpo como matriz sin envoltorio, máximo 1000)
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/events/trackRegistra un evento (cuerpo como objeto) o varios (cuerpo como matriz sin envoltorio, máximo 500)
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/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?