KOP
Acceso anticipado

Conectar un sistema propio con KOP

Tu sistema —la planificación, el ERP, un flujo de n8n o Make— puede crear órdenes de trabajo en KOP con sus documentos y recibir lo que pasa en ellas. Esta página cuenta lo necesario para empezar; el contrato completo está en openapi.yaml.

1. La clave

Todas las llamadas llevan una clave de API de tu organización:

Authorization: Bearer kop_…

La crea un administrador en la app, en Organización › Integraciones › Acceso por API. Se ve una sola vez: guárdala donde guardas tus secretos. Si se pierde, se revoca y se crea otra.

Sin copiar nada desde el móvil

Si tu herramienta puede esperar, pide ella la clave (es el device authorization grant, RFC 8628):

curl -s https://kopproject.com/api/v1/auth/device \
  -H 'Content-Type: application/json' \
  -d '{"clientName": "Planificación de Aeromedia"}'

La respuesta trae un userCode (BCDF-GHJK) y una verificationUriComplete. Enséñalos —el código o un QR de la URL—, y un administrador los escanea o los teclea en Autorizar una herramienta. Mientras tanto, pregunta cada interval segundos con el deviceCode:

curl -s https://kopproject.com/api/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"deviceCode": "…"}'

Hasta que contesten, 400 con authorization_pending; si preguntas más deprisa, slow_down. Aprobada, la respuesta trae la clave una sola vez. El código caduca a los diez minutos.

2. Qué plantillas hay

Cada orden sale de una plantilla de la organización, que dice qué datos pide:

curl -s https://kopproject.com/api/v1/templates -H "Authorization: Bearer $KOP_KEY"

3. Crear una orden

curl -s https://kopproject.com/api/v1/workOrders \
  -H "Authorization: Bearer $KOP_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "requestId": "8f14e45f-ceea-467f-a9f3-6b1f0c2a9d10",
    "template": {
      "id": "vuelo",
      "parameters": {
        "matricula": "EC-DRN",
        "ubicacion": { "lat": 42.4336, "lng": -8.6475, "address": "Diana 3" }
      }
    },
    "description": "Fotogrametría de la parcela",
    "assignees": ["+34600111222"],
    "documents": [{ "name": "restricciones.pdf", "url": "https://…/restricciones.pdf" }]
  }'
  • requestId es un UUID tuyo, y es el id de la orden. Si repites la llamada con el mismo —tras un corte, un reintento—, KOP devuelve la misma orden con 200 en vez de crear otra.
  • assignees: los teléfonos de quienes la harán, que tienen que estar en el equipo. Sin assignees, la orden queda para quien la reparta.
  • Ubicaciones: una dirección ("address": "Rúa da Ponte 4, Pontevedra"), que KOP comprueba en el callejero, o un punto (lat y lng) para un sitio sin calle. Si la dirección admite varias lecturas, 422 con los candidatos: elige uno y vuelve a mandarla.
  • documents: PDFs que KOP descarga de su URL (https, pública) antes de crear la orden. El técnico los abre desde la orden y KOP los lee al acompañarle en el trabajo. Si uno no se puede descargar, la orden no se crea.

Un documento más, después:

curl -s "https://kopproject.com/api/v1/workOrders/$ORDER/documents?name=plano.pdf" \
  -H "Authorization: Bearer $KOP_KEY" \
  -H 'Content-Type: application/pdf' \
  --data-binary @plano.pdf

Una orden lleva como mucho 20 documentos, de hasta 15 MB.

4. Recibir lo que pasa: el webhook

En Integraciones › Webhook, un administrador pone la URL donde quieres recibir los eventos. Al conectar, KOP manda un ping y enseña una sola vez el secreto de firma (whsec_…).

Cada entrega es un POST con el evento en JSON —hoy, workorder.completed, con los datos de la orden y, si tiene parte aprobado, workReport.url: un enlace a su PDF que vale siete días, así que descárgalo al recibirlo— y dos cabeceras:

  • KOP-Event-Id: el mismo en cada reintento. Puede llegar más de una vez: ignora el que ya tengas.
  • KOP-Signature: t=<segundos>,v1=<hex>: el HMAC-SHA256 de <t>.<cuerpo> con el secreto.

Compruébala sobre el cuerpo tal cual llega, antes de parsearlo, y descarta un t de hace más de cinco minutos:

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

function signedByKop(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(',').map((part) => part.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = Buffer.from(
    createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
  );
  const given = Buffer.from(v1 ?? '');
  return given.length === expected.length && timingSafeEqual(given, expected);
}

Contesta con un 2xx. Un 408, un 429 o un 5xx se reintentan; cualquier otra respuesta da la entrega por fallida.

Límites y errores

  • 600 llamadas por hora por clave. Pasado el límite, 429 con Retry-After.
  • Los errores llegan como { "error": { "code", "message" } }. El code es estable (invalid_request, unauthorized, not_found, conflict, too_large, unprocessable, rate_limited, unavailable, internal); el message explica el caso, en inglés.
  • Una clave revocada, mal escrita o ausente es siempre 401.
KOP © KOP — Partes de trabajo sin papeleo.
Privacidad Términos Cookies Eliminar cuenta Contacto