Documentación de la API

Referencia completa: rutas, autenticación, CORS, ejemplos y qué probar en cada endpoint.

Introducción

Jobcelis es una plataforma de eventos y webhooks 100% configurable. Envía cualquier JSON desde tu código; nosotros enrutamos, filtramos, transformamos y entregamos a tus URLs. Sin esquemas fijos: tú defines topics, payloads y reglas.

Qué puedes hacer:

  • Eventos: envía JSON con topic opcional vía POST. Sin esquemas fijos.
  • Webhooks: configura URLs de destino, filtros (topic, amount > 100, status in ["paid"]), body_config (full, pick, rename, extra).
  • Entregas: cada evento activo crea deliveries; reintentos automáticos con backoff 1 min → 5 min → 15 min → 1 h.
  • Jobs programados: daily, weekly, monthly o cron. Acción: emitir evento interno o POST a una URL.
  • Topics: lista de topics usados por tu proyecto para ayudar a configurar filtros.

La API expone dos grupos de rutas:

  • Rutas públicas (auth): registro, login y refresh de JWT. No requieren API Key.
  • Rutas con API Key: eventos, webhooks, deliveries, jobs y proyecto. Requieren el token (Dashboard → API Token).

Todas las respuestas son JSON. CORS habilitado. Payload máximo 256 KB.

Conceptos básicos

Estos son los conceptos que necesitas para usar Jobcelis. No hace falta ser experto: con entender qué es cada cosa puedes configurar eventos, webhooks y jobs en pocos minutos.

¿Qué es un evento?

Un evento es un mensaje que tú envías a Jobcelis desde tu aplicación (con un POST). Puede ser cualquier JSON: un pedido, un pago, un clic, un registro, etc. Opcionalmente le pones un "topic" (etiqueta) para clasificarlo, por ejemplo "order.created" o "payment.completed". Jobcelis guarda el evento y, según los webhooks que tengas configurados, envía esa información a las URLs que tú indiques.

Ejemplo: tu tienda hace POST con { "topic": "order.created", "order_id": 123, "total": 99.99 }. Eso es un evento.

¿Qué es un webhook?

Un webhook es una URL de destino que tú configuras. Cuando llega un evento que cumple las condiciones (topic, filtros), Jobcelis hace un POST a esa URL con los datos que tú eliges (completos, solo ciertos campos, renombrados, etc.). Así tu servidor, tu otro sistema o un servicio externo recibe la información en tiempo real sin que tengas que consultar nada.

Ejemplo: webhook a https://mi-app.com/recibir-pedidos solo cuando topic sea "order.created" y amount sea mayor que 50.

¿Qué es una entrega (delivery)?

Cada vez que Jobcelis intenta enviar un evento a una URL de webhook, se crea una "entrega" (delivery). Esa entrega tiene un estado: pendiente, éxito o fallo. Si falla (por ejemplo la URL no responde), Jobcelis reintenta automáticamente varias veces con pausas (1 min, 5 min, 15 min, 1 h). En el dashboard puedes ver el historial de entregas y reintentar manualmente una que haya fallado.

Resumen: 1 evento puede generar varias entregas (una por webhook que coincida); cada entrega es un intento de POST a una URL.

¿Qué es un job (tarea programada)?

Un job es una tarea que se ejecuta automáticamente en un horario que tú defines: cada día a una hora, cada semana un día concreto, cada mes, o con una expresión cron (por ejemplo "cada 15 minutos" o "todos los lunes a las 9:00"). Cuando se ejecuta, el job puede hacer una de dos cosas: emitir un evento interno (que luego pasa por tus webhooks) o hacer un POST a una URL que tú indiques. Así no necesitas tener un cron en tu servidor: Jobcelis hace la llamada por ti.

Ejemplo: job "Resumen diario" que cada día a las 00:00 emite un evento con topic "report.daily"; tus webhooks lo reciben y tu sistema genera el informe.

¿Qué es un topic?

El topic es una etiqueta opcional que pones al enviar un evento (por ejemplo "order.created", "payment.completed"). Sirve para filtrar: en un webhook puedes decir "solo quiero recibir eventos con topic X" o combinar topic con filtros (por ejemplo amount mayor que 100). Tú inventas los nombres; no hay lista fija.

Primeros pasos

Sigue estos pasos para tener todo funcionando en pocos minutos.

  1. Regístrate e inicia sesión — En la web, regístrate con tu email y contraseña. Entra al Dashboard.
  2. Copia tu API Token — En el Dashboard, sección API Token, verás el token (o prefix). Si acabas de registrarte, el token se habrá mostrado al crear el proyecto. Guárdalo; lo usarás en todas las peticiones con header Authorization: Bearer TU_TOKEN o X-Api-Key: TU_TOKEN.
  3. Envía tu primer evento — Desde tu código o con curl: POST /api/v1/events con body JSON (por ejemplo {"topic":"test","message":"Hola"}). En el Dashboard podrás ver el evento en la lista.
  4. Crea un webhook — En el Dashboard, Webhooks → Crear. Pon una URL que pueda recibir POST (puedes usar webhook.site). Opcional: elige un topic (ej. test) para que solo los eventos con ese topic lleguen a esa URL. Guarda y envía otro evento de prueba.
  5. Crea un job (opcional) — En el Dashboard, Jobs → Crear. Elige programación (por ejemplo Diario a las 12:00) y acción (emitir evento o POST a URL). Guarda; el job se ejecutará a la hora indicada. En "Configurar jobs y cron" más abajo tienes la guía de cron y ejemplos.

Si algo falla, revisa que el token esté bien en el header y que la URL del webhook sea accesible (HTTPS en producción). Las entregas fallidas se pueden reintentar desde el Dashboard.

Base URL

Todos los ejemplos de esta documentación usan la base URL actual (dinámica):

https://jobcelis.com

En producción la base URL será tu dominio (ej. https://api.tudominio.com). Los ejemplos curl que ves en cada ruta ya incluyen esta base.

Autenticación

Rutas con API Key (Jobcelis)

Puedes enviar el token de dos maneras (una por petición):

  1. Header Authorization: Bearer <tu_token>
  2. Header X-Api-Key: <tu_token>

El token se obtiene en el Dashboard (sección API Token), al crear o regenerar. El valor completo solo se muestra una vez; guárdalo. Si regeneras, el token anterior deja de funcionar.

Rutas públicas (Auth)

No envíes API Key. Registro y login devuelven un token (JWT) para usar en tu app web; el refresh renueva ese JWT.

CORS

La API tiene CORS habilitado para cualquier origen (Access-Control-Allow-Origin: *). Así, cualquier frontend (tu SPA, otra web, móvil con WebView, etc.) puede consumir la API desde su propia URL sin bloqueos del navegador.

Headers permitidos en peticiones cross-origin:

  • Authorization (Bearer token)
  • X-Api-Key
  • Content-Type, Accept

Métodos: GET, POST, PUT, PATCH, DELETE, OPTIONS. Las peticiones preflight (OPTIONS) reciben 200 con los headers CORS.

Rutas públicas (sin API Key)

Registro, login y refresh de JWT. Body y respuesta en JSON.

POST /api/v1/auth/register

Registra un usuario. Body: email (requerido), password (requerido), name (opcional).

Respuesta 201: user (id, email, name), token (JWT).

curl -X POST "https://jobcelis.com/api/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"secret123","name":"User"}'

POST /api/v1/auth/login

Inicia sesión. Body: email, password.

Respuesta 200: user, token (JWT). 401 si credenciales incorrectas.

curl -X POST "https://jobcelis.com/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"secret123"}'

POST /api/v1/auth/refresh

Refresca el JWT. Body: token (JWT actual).

Respuesta 200: token (nuevo JWT). 401 si token inválido o expirado.

curl -X POST "https://jobcelis.com/api/v1/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{"token":"TU_JWT_AQUI"}'

Eventos

Todas las rutas requieren API Key. Sustituye YOUR_API_KEY y EVENT_ID por valores reales.

POST /api/v1/send

Alias para enviar un evento. Mismo body que POST /events. Respuesta 202: event_id.

curl -X POST "https://jobcelis.com/api/v1/send" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"topic":"payment.completed","amount":99}'

POST /api/v1/events

Envía un evento. Body: cualquier JSON; opcional topic. Respuesta 202: event_id.

curl -X POST "https://jobcelis.com/api/v1/events" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"topic":"order.created","order_id":123,"customer":"acme"}'

GET /api/v1/events

Lista eventos. Query: topic, limit (1-100), include=inactive. Respuesta: events (array).

curl -X GET "https://jobcelis.com/api/v1/events?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl -X GET "https://jobcelis.com/api/v1/events?topic=order.created&limit=20" \
  -H "X-Api-Key: YOUR_API_KEY"

GET /api/v1/events/:id

Detalle de un evento y sus deliveries. Sustituye EVENT_ID por el id del evento.

curl -X GET "https://jobcelis.com/api/v1/events/EVENT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

DELETE /api/v1/events/:id

Desactiva el evento (soft delete). Respuesta 200: status: "inactive".

curl -X DELETE "https://jobcelis.com/api/v1/events/EVENT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

Webhooks

Configura URLs de destino. Opcional: topics (array), filters (path, op, value), body_config (body_mode, body_pick, body_rename, body_extra), headers.

Filtros: op: eq, neq, gte, lte, gt, lt, in, not_in, exists, contains. Ejemplo:

{"filters":[{"path":"topic","op":"eq","value":"orders"},{"path":"payload.amount","op":"gte","value":100}]}

body_config: body_mode: full o pick. body_pick: array de campos. body_rename: {old: new}. body_extra: campos añadidos.

Sustituye WEBHOOK_ID por el id del webhook.

GET /api/v1/webhooks

Lista webhooks del proyecto. Query: include=inactive. Respuesta: webhooks (array).

curl -X GET "https://jobcelis.com/api/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl -X GET "https://jobcelis.com/api/v1/webhooks?include=inactive" \
  -H "X-Api-Key: YOUR_API_KEY"

POST /api/v1/webhooks

Crea un webhook. Body: url (requerido), opcional secret, topics, filters, body_config, headers. Respuesta 201: objeto webhook.

curl -X POST "https://jobcelis.com/api/v1/webhooks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"url":"https://your-server.com/webhook","topics":["order.created","payment.completed"]}'
curl -X POST "https://jobcelis.com/api/v1/webhooks" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -d '{"url":"https://example.com/hook","secret":"my_secret","topics":["*"]}'

GET /api/v1/webhooks/:id

Detalle de un webhook (id, url, status, topics, filters, etc.).

curl -X GET "https://jobcelis.com/api/v1/webhooks/WEBHOOK_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

PATCH /api/v1/webhooks/:id

Actualiza un webhook. Body: cualquiera de url, secret, topics, filters, body_config, headers, status.

curl -X PATCH "https://jobcelis.com/api/v1/webhooks/WEBHOOK_ID" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"url":"https://new-url.com/webhook","status":"active"}'

DELETE /api/v1/webhooks/:id

Desactiva el webhook. Respuesta 200: status: "inactive".

curl -X DELETE "https://jobcelis.com/api/v1/webhooks/WEBHOOK_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

Entregas

Envíos de eventos a webhooks. Sustituye DELIVERY_ID por el id del delivery.

GET /api/v1/deliveries

Lista deliveries. Query: event_id, webhook_id, status, limit (1-100). Respuesta: deliveries (array).

curl -X GET "https://jobcelis.com/api/v1/deliveries" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl -X GET "https://jobcelis.com/api/v1/deliveries?event_id=EVENT_ID&status=failed&limit=20" \
  -H "X-Api-Key: YOUR_API_KEY"

POST /api/v1/deliveries/:id/retry

Reencola un envío fallido. Respuesta 200: status: "retry_queued".

curl -X POST "https://jobcelis.com/api/v1/deliveries/DELIVERY_ID/retry" \
  -H "Authorization: Bearer YOUR_API_KEY"

Jobs (tareas programadas)

Tareas que se ejecutan según una programación: daily, weekly, monthly o cron. Acción: emitir evento interno o POST a una URL.

schedule_type + schedule_config:

  • daily: {"hour": 14, "minute": 30}
  • weekly: {"day_of_week": 1, "hour": 9, "minute": 0} (1=Lun, 7=Dom)
  • monthly: {"day_of_month": 1, "hour": 0, "minute": 0}
  • cron: {"expr": "0 0 * * *"} (min hour day month dow)

action_type + action_config:

  • emit_event: {"topic": "report.daily", "payload": {}}
  • post_url: {"url": "https://...", "method": "POST"}

GET /api/v1/jobs

Lista jobs del proyecto. Query: include=inactive. Respuesta: jobs (array).

curl -X GET "https://jobcelis.com/api/v1/jobs" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl -X GET "https://jobcelis.com/api/v1/jobs?include=inactive" \
  -H "X-Api-Key: YOUR_API_KEY"

POST /api/v1/jobs

Crea un job. Body: name, schedule_type, schedule_config, action_type, action_config. Respuesta 201: objeto job.

curl -X POST "https://jobcelis.com/api/v1/jobs" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"name":"Daily report","schedule_type":"daily","schedule_config":{"hour":14,"minute":30},"action_type":"emit_event","action_config":{"topic":"report.daily","payload":{}}}'
curl -X POST "https://jobcelis.com/api/v1/jobs" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"name":"Weekly sync","schedule_type":"weekly","schedule_config":{"day_of_week":1,"hour":9,"minute":0},"action_type":"post_url","action_config":{"url":"https://api.example.com/sync","method":"POST"}}'
curl -X POST "https://jobcelis.com/api/v1/jobs" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"name":"Cron job","schedule_type":"cron","schedule_config":{"expr":"0 0 * * *"},"action_type":"emit_event","action_config":{"topic":"daily.cleanup"}}'

GET /api/v1/jobs/:id

Detalle del job y runs recientes. Respuesta incluye recent_runs.

curl -X GET "https://jobcelis.com/api/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

PATCH /api/v1/jobs/:id

Actualiza un job. Body: name, schedule_type, schedule_config, action_type, action_config, status.

curl -X PATCH "https://jobcelis.com/api/v1/jobs/JOB_ID" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"name":"Updated job name","status":"active"}'

DELETE /api/v1/jobs/:id

Desactiva el job. Respuesta 200: status: "inactive".

curl -X DELETE "https://jobcelis.com/api/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /api/v1/jobs/:id/runs

Lista ejecuciones del job. Query: limit (1-100). Respuesta: runs (array).

curl -X GET "https://jobcelis.com/api/v1/jobs/JOB_ID/runs" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl -X GET "https://jobcelis.com/api/v1/jobs/JOB_ID/runs?limit=50" \
  -H "X-Api-Key: YOUR_API_KEY"

Configurar jobs y cron

Los jobs se programan de cuatro formas: diario, semanal, mensual o con una expresión cron. Aquí te explicamos cada una y cómo escribir expresiones cron si eliges esa opción.

Tipos de programación (schedule_type)

  • daily — Cada día a la misma hora. Configuración: hour (0-23), minute (0-59). Ejemplo: 14:30 → {"hour": 14, "minute": 30}.
  • weekly — Un día de la semana a una hora. day_of_week: 1 = Lunes, 7 = Domingo. Ejemplo: Lunes 09:00 → {"day_of_week": 1, "hour": 9, "minute": 0}.
  • monthly — Un día del mes a una hora. day_of_month: 1-31. Ejemplo: Día 1 a las 00:00 → {"day_of_month": 1, "hour": 0, "minute": 0}.
  • cron — Expresión de 5 campos para máxima flexibilidad. Formato: minuto hora día_mes mes día_semana. Ver tabla abajo.

Expresiones cron: qué significa cada campo

Una expresión cron tiene 5 campos separados por espacio, en este orden:

Campo Significado Valores
Minuto0-59
Hora0-23
Día del mes1-31
Mes1-12
Día de la semana1-7 (1=Lun, 7=Dom)

Puedes usar un número concreto, un asterisco (*) para "cualquier valor", o rangos (ej. 1-5 para lunes a viernes). Ejemplos:

  • 0 0 * * * — Todos los días a medianoche (00:00).
  • 0 9 * * * — Todos los días a las 09:00.
  • 0 9 * * 1 — Solo los lunes a las 09:00.
  • 0 9 * * 1-5 — Días laborables (Lun–Vie) a las 09:00.
  • */15 * * * * — Cada 15 minutos.
  • 0 0 1 * * — El día 1 de cada mes a las 00:00.

En el Dashboard, al crear o editar un job, elige "Cron" como tipo y escribe la expresión en el campo (ej. 0 0 * * *). La hora se interpreta en el servidor; si necesitas otra zona horaria, configúrala en tu proyecto cuando esté disponible.

Proyecto, topics y token

Consulta y actualiza el proyecto; gestiona el API Key. Todas las rutas requieren API Key.

GET /api/v1/project

Devuelve el proyecto: id, name, status, settings.

curl -X GET "https://jobcelis.com/api/v1/project" \
  -H "Authorization: Bearer YOUR_API_KEY"

PATCH /api/v1/project

Actualiza el proyecto. Body: name, settings (objeto). Respuesta: id, name, status.

curl -X PATCH "https://jobcelis.com/api/v1/project" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"name":"Mi Proyecto","settings":{"timezone":"Europe/Madrid"}}'

GET /api/v1/topics

Lista los topics usados por tu proyecto (eventos activos). Útil para configurar filtros de webhooks. Respuesta: topics (array).

curl -X GET "https://jobcelis.com/api/v1/topics" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /api/v1/token

Devuelve el prefix del token actual (no el valor completo) y un mensaje de uso.

curl -X GET "https://jobcelis.com/api/v1/token" \
  -H "Authorization: Bearer YOUR_API_KEY"

POST /api/v1/token/regenerate

Regenera el API Key. El token anterior deja de funcionar. Respuesta incluye token (valor completo) y message. Guarda el token; no se vuelve a mostrar.

curl -X POST "https://jobcelis.com/api/v1/token/regenerate" \
  -H "Authorization: Bearer YOUR_API_KEY"

Tras regenerar, usa el nuevo token en las siguientes peticiones.

Formas de usar la aplicación

  • Web: registro e inicio de sesión; Dashboard para proyecto, token, eventos y webhooks; enviar eventos de prueba desde el dashboard.
  • API con API Key: desde cualquier backend o frontend (SPA, móvil, otro dominio gracias a CORS) usa la API Key para enviar eventos, gestionar webhooks, listar deliveries y jobs.
  • API de auth (JWT): para tu app propia (móvil o SPA), usa /auth/register, /auth/login y /auth/refresh para mantener sesión con JWT.

Códigos de respuesta

  • 200 OK
  • 201 Created (recurso creado)
  • 202 Accepted (evento aceptado)
  • 401 No autorizado (API Key o JWT inválido o faltante)
  • 404 Recurso no encontrado
  • 422 Validación fallida (body o parámetros incorrectos)