API REST
Los SDKs son capas finas sobre esta API. Úsala directamente desde cualquier lenguaje.
Lo básico
Sección titulada «Lo básico»| 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 |
Errores
Sección titulada «Errores»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.
Eventos
Sección titulada «Eventos»POST /v0/events
Sección titulada «POST /v0/events»Alcance events:write. Cuerpo: un evento.
POST /v0/events HTTP/1.1Authorization: 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 AcceptedContent-Type: application/json
{ "id": "019a4f2e-…", "status": "queued", "sender_id": "inv-42-failed", "received_at": "2026-11-05T12:00:00.120Z"}statusesqueued, oduplicate(conduplicate_of) cuando se une pordedup_key.- Enviar el mismo
idde nuevo devuelve la respuesta guardada conIdempotent-Replayed: true. El mismoidcon otro cuerpo devuelve409 idempotency_conflict. - Un destinatario desconocido en
todevuelve422. - Límites: 1 MiB por cuerpo; 600 eventos por minuto por token (ráfaga de 100).
Preguntas (asks)
Sección titulada «Preguntas (asks)»POST /v0/asks
Sección titulada «POST /v0/asks»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.1Authorization: Bearer nm_svc_...Content-Type: application/jsonIdempotency-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 CreatedContent-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", "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-Keycon otro cuerpo:422 idempotency_key_reused. Una petición simultánea con la misma clave:409 conflict.
GET /v0/asks/{id}?wait=60
Sección titulada «GET /v0/asks/{id}?wait=60»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 OKContent-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.
POST /v0/hooks/{slug}
Sección titulada «POST /v0/hooks/{slug}»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.
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" }}statusesqueued,duplicateoignored(ninguna regla coincidió,200).?dry_run=1devuelve{"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.
Gestionar mapeos
Sección titulada «Gestionar mapeos»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.
Claves de webhook
Sección titulada «Claves de webhook»GET /.well-known/notificme-keys.json
Sección titulada «GET /.well-known/notificme-keys.json»Pública. Las claves Ed25519 (JWKS) que firman webhooks y respuestas. El SDK las descarga y las guarda en caché.
curl -sS "https://api.notific.me/.well-known/notificme-keys.json"Aprobaciones (agentes de IA)
Sección titulada «Aprobaciones (agentes de IA)»| 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.
Administración del workspace
Sección titulada «Administración del workspace»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.