Saltar al contenido

API REST

Los SDKs son capas finas sobre esta API. Úsala directamente desde cualquier lenguaje.

Elemento Valor
URL base https://api.notific.me (la pantalla SDKs de app.notific.me muestra la dirección de tu cuenta)
Versión Todas las rutas empiezan con /v0
Autenticación Authorization: Bearer nm_svc_… (token de servicio)
Formato JSON de entrada y salida, UTF-8, campos en snake_case, fechas RFC 3339
Id de petición Envía X-Request-Id para correlacionar; toda respuesta devuelve uno

Todos los errores tienen el mismo sobre, con un code estable en el que puedes confiar:

{
"error": {
"code": "validation_failed",
"message": "evento inválido",
"details": { "schema": "event", "errors": [{ "path": "/severity", "message": "…" }] }
},
"request_id": "019a…"
}
Estado Códigos comunes
400 bad_request
401 unauthorized (token ausente, no válido, revocado o vencido; servicio desactivado)
403 forbidden (falta un alcance), approval_required
404 not_found, hook_not_found
409 idempotency_conflict, conflict
413 payload_too_large
422 validation_failed (con details), idempotency_key_reused
429 rate_limited (con Retry-After)
503 unavailable

El message es para los logs; muestra a tus usuarios un texto basado en el code.

Alcance events:write. Cuerpo: un evento.

POST /v0/events HTTP/1.1
Authorization: Bearer nm_svc_...
Content-Type: application/json
{
"id": "inv-42-failed",
"source": "billing",
"type": "invoice.failed",
"severity": "high",
"occurred_at": "2026-11-05T12:00:00Z",
"to": ["jimmy"],
"payload": { "invoice": 42 },
"content": { "summary": "Invoice #42 failed" }
}
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"id": "019a4f2e-…",
"status": "queued",
"sender_id": "inv-42-failed",
"received_at": "2026-11-05T12:00:00.120Z"
}
  • status es queued, o duplicate (con duplicate_of) cuando se une por dedup_key.
  • Enviar el mismo id de nuevo devuelve la respuesta guardada con Idempotent-Replayed: true. El mismo id con otro cuerpo devuelve 409 idempotency_conflict.
  • Un destinatario desconocido en to devuelve 422.
  • Límites: 1 MiB por cuerpo; 600 eventos por minuto por token (ráfaga de 100).

Alcance asks:write. Cuerpo: un grupo de preguntas. Envía la cabecera Idempotency-Key (hasta 200 caracteres) para que un reintento nunca cree dos grupos.

POST /v0/asks HTTP/1.1
Authorization: Bearer nm_svc_...
Content-Type: application/json
Idempotency-Key: refund-881
{
"to": ["jimmy"],
"title": "Refund order #881 (USD 240)?",
"context": "The customer reported a duplicate charge.",
"questions": [
{ "id": "decision", "type": "single", "text": "What should we do?", "options": ["Refund", "Partial refund", "Deny"] },
{ "id": "note", "type": "text", "text": "Note for the customer", "optional": true }
],
"level": 2,
"timeout": "30m",
"on_timeout": { "decision": "Deny" },
"callback_url": "https://crm.example.com/hooks/notificme"
}
HTTP/1.1 201 Created
Content-Type: application/json
{
"id": "019a4f30-…",
"status": "open",
"version": 1,
"level": 2,
"title": "Refund order #881 (USD 240)?",
"created_at": "2026-11-05T12:00:00Z",
"timeout_at": "2026-11-05T12:30:00Z",
"recipients": ["[email protected]"],
"notification_id": "019a4f30-…",
"content_hash": "…",
"poll_url": "/v0/asks/019a4f30-…"
}
  • Cuerpo de hasta 256 KiB. Grupo no válido: 422 validation_failed.
  • La misma Idempotency-Key con otro cuerpo: 422 idempotency_key_reused. Una petición simultánea con la misma clave: 409 conflict.

Alcance asks:read. Devuelve la misma vista. Con wait (segundos, o una duración como 30s, hasta 60), la llamada hace long-poll: vuelve en cuanto el grupo sale de open, o cuando termina la espera.

HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "019a4f30-…",
"status": "answered",
"version": 1,
"level": 2,
"title": "Refund order #881 (USD 240)?",
"created_at": "2026-11-05T12:00:00Z",
"timeout_at": "2026-11-05T12:30:00Z",
"content_hash": "…",
"poll_url": "/v0/asks/019a4f30-…",
"reply": {
"question_set_id": "019a4f30-…",
"version": 1,
"status": "answered",
"answers": [
{ "question_id": "decision", "question_text": "What should we do?", "value": "Refund" },
{ "question_id": "note", "question_text": "Note for the customer", "free_text": "Sorry for the trouble!" }
],
"as_text": "…",
"answered_by": { "identity": "[email protected]", "device_id": "019a…", "level_used": 2, "auth_method": "totp" },
"answered_at": "2026-11-05T12:03:10Z",
"content_hash": "…",
"signature": { "alg": "Ed25519", "key_id": "…", "value": "…" }
}
}

status es open, answered, timeout, expired o cancelled. reply aparece en answered y timeout.

Alcance events:write. Cualquier cuerpo (JSON, formulario o texto) de otro sistema, convertido en evento por el mapeo del hook. El token puede ir en ?token= para sistemas que solo aceptan una URL.

Ventana de terminal
curl -sS -X POST "https://api.notific.me/v0/hooks/dokploy?token=$NOTIFICME_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type": "build-success", "applicationName": "api", "projectName": "idie"}'
{
"status": "queued",
"rule": "deploy-ok",
"event": { "id": "019a…", "status": "queued", "received_at": "2026-11-05T12:00:00Z" }
}
  • status es queued, duplicate o ignored (ninguna regla coincidió, 200).
  • ?dry_run=1 devuelve {"status": "dry_run", "rule", "event"} con el evento generado, sin guardarlo.
  • Firma HMAC incorrecta: 401 invalid_signature. Sin mapeo ni preset para el slug: 404 hook_not_found.

Con un token (events:write):

Ruta Descripción
GET /v0/hooks Lista los hooks del workspace (guardados y presets).
GET /v0/hooks/{slug}/mapping El mapeo YAML, con el secreto HMAC enmascarado.
PUT /v0/hooks/{slug}/mapping Guarda un mapeo (YAML o JSON).
DELETE /v0/hooks/{slug}/mapping Lo borra; un preset con el mismo slug vuelve a aplicarse.

La app usa las rutas del workspace (/v0/workspaces/{handle}/hooks…, incluido un dry-run con cuerpo, cabeceras y query de ejemplo); también aceptan tokens con workspace:read y hooks:write.

Pública. Las claves Ed25519 (JWKS) que firman webhooks y respuestas. El SDK las descarga y las guarda en caché.

Ventana de terminal
curl -sS "https://api.notific.me/.well-known/notificme-keys.json"
Ruta Descripción
POST /v0/approvals Pide a una persona que apruebe una escritura bloqueada (method, path, body, reason).
GET /v0/approvals/{id}?wait=60 Estado de la aprobación (long-poll hasta 60 s).

Luego repite la petición original con Notificme-Approval: <id>. Mira Agentes de IA y MCP.

Todo lo que hace la app también es API en /v0/workspaces/{handle}/…: servicios, tokens, reglas y el simulador, hooks, webhooks (listar y reenviar), eventos, notificaciones, preguntas, uso, miembros y auditoría. Estas rutas aceptan la sesión de una persona o un token con el alcance correspondiente (workspace:read, services:write, tokens:write, rules:write, hooks:write, webhooks:write, audit:read). La forma más fácil de usarlas desde un agente de IA es el servidor MCP.