Saltar al contenido

API REST

Integrá Demult con tus sistemas.

Creá pedidos de documentos y traé su estado y los datos que la IA extrae, desde tu backend. Autenticación con API key, una por workspace.

Base de la API

https://demult.com/api/v1

Autenticación

Cada llamada lleva una API key del workspace en el header Authorization:

Authorization: Bearer demult_sk_xxxxxxxx...

Las keys se crean y revocan desde Configuración → API (Owner/Admin), disponible desde el plan Estudio. El secreto se muestra una sola vez al crearla — guardalo seguro; en la base solo queda su hash. Una key opera siempre acotada a su workspace. Rate-limit: 120 solicitudes/minuto por key.

POST/requests

Crea y envía un pedido: genera el link, manda el email al destinatario y programa los recordatorios. Respeta el cupo de pedidos del plan (402 si lo superás).

Body

{
  "template_id": "uuid de una plantilla (ver GET /templates)",
  "recipient": { "name": "Juan Pérez", "email": "juan@ejemplo.com" },
  "expires_in_days": 30,
  "message": "Texto opcional para el cliente"
}

Respuesta 201

{
  "id": "uuid del pedido",
  "status": "sent",
  "recipient": { "name": "Juan Pérez", "email": "juan@ejemplo.com" },
  "link": "https://demult.com/p/<token>",
  "expires_at": "2026-08-01T00:00:00.000Z"
}
GET/requests

Lista los pedidos del workspace (más nuevos primero). Query: status, limit (1–100, default 20), offset.

{
  "data": [
    {
      "id": "uuid",
      "status": "in_progress",
      "recipient": { "name": "Juan Pérez", "email": "juan@ejemplo.com" },
      "template_name": "Ganancias 2026",
      "progress": { "validated": 2, "total": 4 },
      "created_at": "2026-07-01T12:00:00.000Z",
      "expires_at": "2026-08-01T00:00:00.000Z",
      "completed_at": null
    }
  ],
  "limit": 20,
  "offset": 0
}
GET/requests/{id}

Detalle de un pedido: cada casillero con su estado y, si la IA lo procesó, los datos extraídos.

{
  "id": "uuid",
  "status": "in_progress",
  "recipient": { "name": "Juan Pérez", "email": "juan@ejemplo.com" },
  "template_name": "Ganancias 2026",
  "documents": [
    {
      "label": "Recibo de sueldo",
      "document_type": "payslip",
      "status": "validated",
      "confidence": 0.96,
      "filename": "recibo.pdf",
      "extracted_fields": { "cuit": "20-12345678-9", "neto": "845200" }
    }
  ]
}
GET/templates

Lista las plantillas activas (para conocer los template_id que usás al crear pedidos).

{ "data": [ { "id": "uuid", "name": "Ganancias 2026", "document_count": 4 } ] }

Errores

Los errores vienen como { "error": "mensaje" } con el status correspondiente:

  • 401 — sin header o API key inválida/revocada.
  • 403 — tu plan no incluye API (disponible desde Estudio).
  • 402 — superaste el cupo de pedidos del plan.
  • 404 — el recurso no existe o no es de tu workspace.
  • 429 — demasiadas solicitudes (120/min por key).

Ejemplo completo

# 1) Conocer las plantillas
curl https://demult.com/api/v1/templates \
  -H "Authorization: Bearer demult_sk_..."

# 2) Crear y enviar un pedido
curl -X POST https://demult.com/api/v1/requests \
  -H "Authorization: Bearer demult_sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "template_id": "<id>", "recipient": { "name": "Juan", "email": "juan@ejemplo.com" } }'

# 3) Traer el estado + datos extraídos
curl https://demult.com/api/v1/requests/<id> \
  -H "Authorization: Bearer demult_sk_..."

Todo sobre HTTPS. Nunca pongas la API key en una URL ni en el front: usala servidor-a-servidor.

Webhooks

En lugar de hacer polling, Demult le avisa a tu sistema cuando pasan cosas. Registrá un endpoint (URL https) en Configuración → Webhooks (Owner/Admin, desde Estudio) y elegí a qué eventos suscribirte. Cada evento se entrega con un POST y se reintenta si falla.

Eventos

  • request.created — se envió un pedido a un cliente.
  • request.completed — un pedido quedó completo.
  • document.received — un cliente subió un documento.
  • document.validated — un documento fue validado.
  • document.rejected — un documento fue rechazado.

Cada entrega es un JSON con esta forma:

{
  "event": "document.validated",
  "occurred_at": "2026-07-05T18:30:00.000Z",
  "workspace_id": "uuid",
  "data": {
    "request_id": "uuid",
    "recipient_name": "Juan Pérez",
    "slot_id": "uuid",
    "label": "DNI (frente)",
    "document_type": "id_front"
  }
}

Y trae estas cabeceras (la firma protege integridad y evita replays):

X-Demult-Event: document.validated
X-Demult-Delivery: <id de la entrega>
X-Demult-Timestamp: <epoch en segundos>
X-Demult-Signature: sha256=<hmac hex>

Verificá la firma recomputando el HMAC-SHA256 de timestamp + "." + body con el secreto que te mostramos una vez al crear el endpoint:

import { createHmac, timingSafeEqual } from 'node:crypto'

function verify(secret, req, rawBody) {
  const ts = req.headers['x-demult-timestamp']
  const sig = (req.headers['x-demult-signature'] || '').replace('sha256=', '')
  const expected = createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex')
  const a = Buffer.from(expected), b = Buffer.from(sig)
  return a.length === b.length && timingSafeEqual(a, b)
}

Respondé 2xx para confirmar la recepción. Si respondés otra cosa (o no respondés), reintentamos con backoff; tras muchas fallas seguidas, el endpoint se pausa solo. Usá el timestamp para rechazar entregas viejas.