Saltar al contenido

Desarrolladores Contrato v1 en diseño

Tu primera acta, en diez minutos.

Una API con contrato OpenAPI, SDK en TypeScript y Python, un CLI, un sandbox local con una estación simulada y documentación que también leen las IA. De la clave de test al acta sellada y verificada, sin escribir a nadie.

Al entrar por primera vez en el panel

Siete pasos. Diez minutos.

Una guía interactiva que guarda tu progreso. Te la puedes saltar y retomarla cuando quieras.

  1. 1

    Cuenta y 2FA

    Entras y activas el segundo factor. Para propietarios y administradores es obligatorio.

  2. 2

    Tu clave de test

    El asistente de claves, en tres pasos. Las claves de test no consumen cuota.

  3. 3

    Sella tu primera acta sin escribir código

    El navegador monta la petición con una captura de ejemplo o con una foto tuya y la envía. Ves el acta avanzar en directo.

  4. 4

    Verifícala

    Abres su página pública y el comprobador de archivos. Te explicamos qué es la huella, la hora y la firma.

  5. 5

    Mira el registro

    La llamada que acabas de hacer ya aparece en el registro de API de tu cuenta.

  6. 6

    Recibe un webhook

    En la bandeja de pruebas del panel o en tu propia URL. Con reenvío manual.

  7. 7

    Elige tu camino

    Descargar el SDK, conectar una IA, levantar el sandbox local o dar de alta una estación PackNSign con el simulador.

La misma guía existe en texto en la documentación y como playground permanente en el panel.

Sellar

Una llamada. Un acta sellada.

Creas el acta desde tu WMS, tu tienda o tu plataforma de reclamaciones. Responde al momento y te avisa por webhook cuando queda sellada.

curl https://api.knowyourparcel.com/v1/records \
  -H "Authorization: Bearer $KYP_API_KEY" \
  -H "KYP-Version: 2026-10-16" \
  -H "Idempotency-Key: 6f1c2a90-8d1e-4b7a-9c3f-2b51e0d4a713" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "outbound",
    "references": [{ "kind": "order", "value": "ORD-88213" }],
    "payload": { "weight_kg": 2.34, "dims_cm": [32, 24.5, 18] },
    "assets": [{ "role": "top", "upload": "upl_01J…" }]
  }'
import { KYP } from '@knowyourparcel/sdk';

const kyp = new KYP({ apiKey: process.env.KYP_API_KEY });

const record = await kyp.records.create({
  kind: 'outbound',
  references: [{ kind: 'order', value: 'ORD-88213' }],
  payload: { weight_kg: 2.34, dims_cm: [32, 24.5, 18] },
  assets: [{ role: 'top', file: './top.jpg' }],
});

const sealed = await kyp.records.waitFor(record.id, 'sealed');
console.log(sealed.verify_url);
import os
from knowyourparcel import KYP

kyp = KYP(api_key=os.environ["KYP_API_KEY"])

record = kyp.records.create(
    kind="outbound",
    references=[{"kind": "order", "value": "ORD-88213"}],
    payload={"weight_kg": 2.34, "dims_cm": [32, 24.5, 18]},
    assets=[{"role": "top", "file": "top.jpg"}],
)

sealed = kyp.records.wait_for(record.id, "sealed")
print(sealed.verify_url)
Respuesta · 202
{
  "id": "KYP-2026-000123",
  "status": "sealing",
  "kind": "outbound",
  "received_at": "2026-10-16T09:41:18.204Z",
  "payload_hash": "sha256:…a91f",
  "verify_url": "https://verify.knowyourparcel.com/v/KYP-2026-000123",
  "request_id": "req_01J…"
}

Y cualquiera la comprueba.

La verificación es pública y no necesita clave. Con el SDK de Python puedes comprobar un acta sin conexión: huella, firma Ed25519 y sello RFC 3161, sin preguntarnos.

curl https://api.knowyourparcel.com/v1/verify/KYP-2026-000123
const result = await kyp.verify('KYP-2026-000123');

result.intact;              // true
result.checks.timestamp;    // 'valid'
result.capture_trust;       // 'attested'
from knowyourparcel.offline import verify_record

result = verify_record("KYP-2026-000123.json")

result.fingerprint   # "match"
result.signature     # "valid"   Ed25519
result.timestamp     # "valid"   RFC 3161

Claves y tokens

Claves en tres pasos.

  1. 01

    Nombre y entorno

    Test o live. Las de test apuntan a un entorno de pruebas alojado, con datos aislados y sello simulado marcado como tal.

  2. 02

    Ámbitos, en lenguaje llano

    Plantillas listas: solo lectura, integración de almacén, verificación pública, dispositivo. O ámbito a ámbito.

  3. 03

    Restricciones

    IPs permitidas, caducidad y límite por minuto.

  • Rotación con solape: la clave anterior sigue viva 24 h.
  • Revocación inmediata y «última vez usada», con la IP.
  • Aviso si una clave live se usa desde una IP nueva.
  • CLI con kyp login: se abre el navegador, sin pegar claves en la terminal.
  • Estaciones con código de alta de un solo uso y QR.

API v1

Todo es una llamada.

REST y JSON, versionada por ruta y por fecha. Autenticación con Bearer, idempotencia en cada POST que crea y un registro de cada llamada que ves tú también. Abre un endpoint para ver la forma de la respuesta.

Actas

POST/v1/recordsCrea un acta a partir de una captura y la sella. Devuelve 202 y avisa por webhook al quedar sellada.
Petición
{
  "kind": "outbound",
  "references": [
    {
      "kind": "order",
      "value": "ORD-88213"
    },
    {
      "kind": "tracking",
      "value": "1Z…"
    }
  ],
  "payload": {
    "weight_kg": 2.34,
    "dims_cm": [
      32,
      24.5,
      18
    ]
  },
  "assets": [
    {
      "role": "top",
      "upload": "upl_01J…"
    },
    {
      "role": "perspective",
      "upload": "upl_01J…"
    }
  ]
}
Respuesta
{
  "id": "KYP-2026-000123",
  "status": "sealing",
  "kind": "outbound",
  "received_at": "2026-10-16T09:41:18.204Z",
  "payload_hash": "sha256:…a91f",
  "verify_url": "https://verify.knowyourparcel.com/v/KYP-2026-000123",
  "request_id": "req_01J…"
}
GET/v1/records/{id}El acta completa: medidas, peso, referencias, firma del dispositivo, nivel de confianza de la captura y sello.
Respuesta
{
  "id": "KYP-2026-000123",
  "status": "sealed",
  "kind": "outbound",
  "references": [
    {
      "kind": "order",
      "value": "ORD-88213"
    }
  ],
  "payload": {
    "weight_kg": 2.34,
    "dims_cm": [
      32,
      24.5,
      18
    ],
    "label": {
      "tracking": "1Z…"
    }
  },
  "device": {
    "id": "dev_01J…",
    "model": "PackNSign 60",
    "signature": "valid"
  },
  "capture_trust": "attested",
  "seal": {
    "payload_hash": "sha256:…a91f",
    "timestamp": "RFC 3161",
    "sealed_at": "2026-10-16T09:41:19Z",
    "prev_record_hash": "sha256:…07c4"
  },
  "assets": [
    {
      "role": "top",
      "sha256": "…3b9e"
    },
    {
      "role": "perspective",
      "sha256": "…c1d0"
    }
  ]
}
GET/v1/records?reference=ORD-88213Busca por pedido, tracking, SKU, cliente, estación o fechas. Paginación por cursor.
Respuesta
{
  "data": [
    {
      "id": "KYP-2026-000123",
      "kind": "outbound",
      "sealed_at": "2026-10-16T09:41:19Z"
    },
    {
      "id": "KYP-2026-000481",
      "kind": "return",
      "sealed_at": "2026-10-28T15:02:44Z"
    }
  ],
  "next": "cur_01J…"
}
GET/v1/records/{id}/assets/{assetId}Una imagen, vídeo o nube de puntos, por URL firmada de corta duración.
Respuesta
{
  "role": "top",
  "mime": "image/jpeg",
  "sha256": "…3b9e",
  "url": "https://api.knowyourparcel.com/v1/files/…?sig=…",
  "expires_in": 300
}
POST/v1/uploadsURL firmada para subir archivos grandes directamente al almacén.
Petición
{
  "filename": "top.jpg",
  "mime": "image/jpeg",
  "bytes": 4182231,
  "sha256": "…3b9e"
}
Respuesta
{
  "id": "upl_01J…",
  "put_url": "https://api.knowyourparcel.com/v1/uploads/upl_01J…?sig=…",
  "expires_in": 900
}

Verificación · pública, sin clave

GET/v1/verify/{ref}Comprueba huella, sello de tiempo, firma del dispositivo y cadena.
Respuesta
{
  "id": "KYP-2026-000123",
  "intact": true,
  "sealed_at": "2026-10-16T09:41:19Z",
  "checks": {
    "fingerprint": "match",
    "timestamp": "valid",
    "device_signature": "valid",
    "chain": "linked",
    "anchor": "2026-10-16"
  },
  "capture_trust": "attested"
}
POST/v1/verify/fileSube un PDF, un JSON o una imagen y te dice si es un acta intacta.
Petición
multipart/form-data   file=@KYP-2026-000123.pdf
Respuesta
{
  "is_kyp_record": true,
  "id": "KYP-2026-000123",
  "intact": false,
  "reason": "fingerprint_mismatch"
}
GET/v1/anchors/{date}El ancla diaria: raíz de la cadena de toda la plataforma, sellada y publicada.
Respuesta
{
  "date": "2026-10-16",
  "merkle_root": "sha256:…e2a7",
  "records": "n",
  "timestamp": {
    "standard": "RFC 3161",
    "token": "MIIG…"
  },
  "published": "https://verify.knowyourparcel.com/anchors/2026-10-16"
}

Análisis

POST/v1/compareEnfrenta dos actas. Devuelve diferencias, no veredictos.
Petición
{
  "a": "KYP-2026-000123",
  "b": "KYP-2026-000481"
}
Respuesta
{
  "weight_kg": {
    "a": 2.34,
    "b": 0.41,
    "delta": -1.93
  },
  "dims_cm": {
    "a": [
      32,
      24.5,
      18
    ],
    "b": [
      32,
      24.5,
      18
    ],
    "delta": [
      0,
      0,
      0
    ]
  },
  "differences": [
    "weight",
    "packaging"
  ],
  "verdict": null
}
POST/v1/declarations/checkCruza lo declarado con lo medido, incluido el peso volumétrico.
Petición
{
  "reference": "ORD-88213",
  "declared": {
    "weight_kg": 1.2,
    "dims_cm": [
      30,
      20,
      10
    ],
    "items": 1
  }
}
Respuesta
{
  "record": "KYP-2026-000123",
  "mismatches": [
    {
      "field": "weight_kg",
      "declared": 1.2,
      "measured": 2.34
    },
    {
      "field": "dims_cm",
      "declared": [
        30,
        20,
        10
      ],
      "measured": [
        32,
        24.5,
        18
      ]
    }
  ],
  "dim_weight_kg": {
    "declared": 1.2,
    "measured": 2.82
  }
}

Paquetes y Smart Track

GET/v1/parcels/{id}/timelineEl pasaporte: tramos de custodia, eventos de transportista, actas y huecos.
Respuesta
{
  "parcel": "prc_01J…",
  "legs": [
    {
      "holder": "seller",
      "record": "KYP-2026-000123"
    },
    {
      "holder": "carrier_a",
      "events": 6,
      "gap_hours": 41
    },
    {
      "holder": "forwarder",
      "record": "KYP-2026-000207"
    }
  ],
  "snapshots": {
    "count": 14,
    "last_sha256": "…7be2"
  }
}
GET/v1/parcels/{id}/riskPuntuación de 0 a 100 con cada señal y la regla que la dispara.
Respuesta
{
  "parcel": "prc_01J…",
  "score": 72,
  "level": "high",
  "signals": [
    {
      "code": "stalled",
      "hours": 41,
      "route_p90_hours": 18
    },
    {
      "code": "weight_mismatch",
      "sealed_kg": 2.34,
      "carrier_kg": 3.1
    }
  ],
  "rules_version": "acc_rules@7"
}
GET/v1/insights/transit-times?from=ES-V&to=FR-75Tiempos reales por transportista y ruta, con su muestra.
Respuesta
{
  "carrier": "carrier_a",
  "route": "ES-V → FR-75",
  "sample": "…",
  "median_days": 3,
  "p10_p90_days": [
    2,
    6
  ],
  "confidence": "high"
}

Expedientes y exportaciones

POST/v1/dossiersArma el expediente: actas, cronología, sellos y enlace público.
Petición
{
  "records": [
    "KYP-2026-000123"
  ],
  "claim": {
    "type": "damage",
    "counterparty": "carrier",
    "reference": "1Z…"
  },
  "lang": "en"
}
Respuesta
{
  "id": "dos_01J…",
  "status": "ready",
  "pdf_sha256": "…19aa",
  "share_url": "https://verify.knowyourparcel.com/d/dos_01J…"
}
POST/v1/exportsExporta actas y evidencias para auditoría. Avisa con export.ready.
Petición
{
  "from": "2026-10-01",
  "to": "2026-10-31",
  "format": "zip"
}
Respuesta
{
  "id": "exp_01J…",
  "status": "processing",
  "format": "zip",
  "notify": "export.ready"
}

Bóveda

GET/v1/vault/transactions/{id}Todas las evidencias de una transacción, su retención y su bloqueo legal.
Respuesta
{
  "id": "trx_01J…",
  "records": [
    "KYP-2026-000123",
    "KYP-2026-000481"
  ],
  "assets": 14,
  "attestations": [],
  "legal_hold": true,
  "retention_until": "2031-10-16",
  "integrity": {
    "last_check": "2026-10-15",
    "status": "intact"
  }
}
GET/v1/vault/transactions/{id}/manifestEl manifiesto de integridad: cada archivo con su huella, sellado.
Respuesta
{
  "transaction": "trx_01J…",
  "files": [
    {
      "path": "records/KYP-2026-000123.json",
      "sha256": "…a91f"
    },
    {
      "path": "assets/top.jpg",
      "sha256": "…3b9e"
    },
    "…"
  ],
  "manifest_sha256": "…5f02",
  "timestamp": "RFC 3161"
}
POST/v1/vault/transactions/{id}/access-linksEnlace de auditor para un perito, una aseguradora o un abogado: acotado, con caducidad y registrado.
Petición
{
  "transactions": [
    "trx_01J…"
  ],
  "expires_in_hours": 72,
  "password": true,
  "label": "claim-4471"
}
Respuesta
{
  "id": "val_01J…",
  "url": "https://verify.knowyourparcel.com/a/val_01J…",
  "expires_at": "2026-10-19T09:00:00Z",
  "logged": true
}
GET/v1/vault/access-logQuién vio o descargó qué, cuándo y desde dónde.
Respuesta
{
  "data": [
    {
      "at": "2026-10-16T14:02:11Z",
      "actor": "user:auditor",
      "action": "manifest.downloaded",
      "target": "trx_01J…",
      "ip_country": "ES"
    },
    {
      "at": "2026-10-16T14:05:40Z",
      "actor": "access_link:val_01J…",
      "action": "asset.viewed",
      "target": "assets/top.jpg",
      "ip_country": "ES"
    }
  ],
  "next": null
}

Journeys

POST/v1/journeysPublica la página de un paquete o un acta con tu marca: pasaporte, recibo, devolución o custodia.
Petición
{
  "subject": {
    "type": "parcel",
    "id": "prc_01J…"
  },
  "template": "passport",
  "visibility": "link",
  "expires_at": "2026-12-31",
  "lang": "auto"
}
Respuesta
{
  "id": "jrn_01J…",
  "url": "https://verify.knowyourparcel.com/j/4kP9…",
  "template": "passport",
  "branding": "account_default"
}
PATCH/v1/journeys/{id}Cambia caducidad, contraseña, plantilla o marca.
Petición
{
  "password": "set",
  "expires_at": "2027-01-31"
}
Respuesta
{
  "id": "jrn_01J…",
  "password": true,
  "expires_at": "2027-01-31"
}

Analítica Próximamente

GET/v1/analytics/journeys?template=returnVisitas, eventos de conversión y tiempos por plantilla.
Respuesta
{
  "from": "2026-10-01",
  "to": "2026-10-31",
  "template": "return",
  "views": "…",
  "events": {
    "return.capture_started": "…",
    "return.capture_completed": "…"
  },
  "median_seconds_to_complete": "…"
}
GET/v1/analytics/funnels/{template}El embudo de cada plantilla, con el paso donde se abandona.
Respuesta
{
  "template": "return",
  "steps": [
    {
      "event": "journey.viewed"
    },
    {
      "event": "return.capture_started",
      "rate": "…"
    },
    {
      "event": "return.capture_completed",
      "rate": "…"
    }
  ],
  "drop_off_step": "…"
}

Dispositivos

GET/v1/devices/{id}/healthEstado de cada estación: cámaras, báscula, calibración y cola sin conexión.
Respuesta
{
  "id": "dev_01J…",
  "model": "PackNSign 60",
  "online": true,
  "last_seen_at": "2026-10-16T09:40:02Z",
  "calibration": {
    "status": "valid",
    "next_due": "2026-11-01"
  },
  "cameras": "ok",
  "scale": "ok",
  "offline_queue": 0
}
POST/v1/devices/enrollment-codesCódigo de alta de un solo uso y QR que la estación escanea.
Petición
{
  "label": "warehouse-desk-2"
}
Respuesta
{
  "code": "48 21 90 17",
  "qr": "data:image/png;base64,…",
  "expires_in": 900
}

Sesiones de captura · SDK Próximamente

POST/v1/capture/sessionsAbre una sesión de captura solo si la atestación del móvil o el navegador pasa.
Petición
{
  "platform": "android",
  "attestation": "eyJ…",
  "public_key": "MCow…",
  "flow": "return"
}
Respuesta
{
  "session": "cap_01J…",
  "trust": "attested",
  "challenge": {
    "kind": "light_pattern",
    "nonce": "…"
  },
  "expires_in": 600
}
POST/v1/capture/sessions/{id}/completeCierra la sesión: firmas y procedencia comprobadas, acta creada.
Respuesta
{
  "session": "cap_01J…",
  "record": "KYP-2026-000481",
  "capture_trust": "attested",
  "c2pa": "valid"
}

Webhooks y registro

POST/v1/webhooksSuscribe una URL a eventos. Firma HMAC-SHA256 y reintentos durante 72 h.
Petición
{
  "url": "https://example.com/webhooks/kyp",
  "events": [
    "record.sealed",
    "alert.raised"
  ],
  "environment": "test"
}
Respuesta
{
  "id": "whk_01J…",
  "secret": "whsec_…",
  "status": "active"
}
POST/v1/webhooks/{id}/testEnvía un evento de prueba y te enseña la respuesta.
Respuesta
{
  "delivery": "dlv_01J…",
  "event": "record.sealed",
  "http_status": 200,
  "duration_ms": 182
}
GET/v1/api-log?from=2026-10-16Tu propio registro de llamadas, incluidas las de tus agentes de IA.
Respuesta
{
  "data": [
    {
      "at": "2026-10-16T09:41:18Z",
      "request_id": "req_01J…",
      "actor": "api_key:key_01J…",
      "route": "POST /v1/records",
      "status": 202,
      "duration_ms": 143
    },
    {
      "at": "2026-10-16T09:52:03Z",
      "request_id": "req_01J…",
      "actor": "ai_agent:claims-assistant",
      "route": "kyp_find_records",
      "status": 200,
      "duration_ms": 61
    }
  ],
  "next": "cur_01J…"
}

Cuenta y uso

GET/v1/account/usage?month=2026-10Consumo del mes frente a lo incluido, por tipo, en tiempo real.
Respuesta
{
  "month": "2026-10",
  "license": "active",
  "included": "…",
  "used": "…",
  "projected_extra": "…",
  "by_kind": {
    "record_sealed": "…",
    "verify_public": "…",
    "track_subscription": "…"
  }
}
GET/v1/account/licenseTu licencia: estado, plazas y funciones activas.
Respuesta
{
  "plan": "…",
  "status": "active",
  "billing_day": 5,
  "seats": {
    "users": "…",
    "devices": "…"
  },
  "entitlements": [
    "api",
    "webhooks",
    "mcp",
    "journeys_hosting",
    "smart_track"
  ]
}

Webhooks firmados

record.sealedrecord.failedrecord.supersededparcel.handoverparcel.deliveredalert.raisedalert.resolveddevice.enrolleddevice.offlinedevice.calibration_duedossier.readyexport.readylicense.changedusage.threshold

Contrato v1 en diseño con los socios del piloto. Rutas y campos ilustrativos; «…» marca valores omitidos.

Convenciones

Lo aburrido, bien hecho.

  • Idempotencia

    Cada POST que crea admite Idempotency-Key. Repetir la llamada devuelve la misma respuesta durante 24 h, sin duplicar el acta.

  • Errores RFC 9457

    application/problem+json con un request_id que encuentras en tu registro. El detalle llega en tu idioma.

  • Versiones

    Ruta /v1 y cabecera KYP-Version con fecha. Los cambios incompatibles se anuncian con fecha y cabecera Sunset.

  • Paginación y límites

    Cursores en vez de páginas. Límites por clave y por cuenta, con cabeceras RateLimit estándar.

  • Webhooks

    Firma HMAC-SHA256 con marca de tiempo, 8 reintentos con espera creciente durante 72 h y reenvío manual desde el panel.

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
Content-Language: es

{
  "type": "https://docs.knowyourparcel.com/errors/invalid-dimensions",
  "title": "Medidas no válidas",
  "status": 422,
  "detail": "dims_cm[2] debe ser mayor que 0.",
  "request_id": "req_01J…"
}
POST /v1/records
Idempotency-Key: 6f1c2a90-8d1e-4b7a-9c3f-2b51e0d4a713

HTTP/1.1 202 Accepted
Idempotent-Replayed: true
RateLimit-Limit: 600
RateLimit-Remaining: 597
RateLimit-Reset: 41
POST /webhooks/kyp HTTP/1.1
Host: example.com
Content-Type: application/json
KYP-Signature: t=1760607679,v1=5d1f0c…e9

{ "type": "record.sealed", "data": { "id": "KYP-2026-000123" } }
const event = kyp.webhooks.verify(
  rawBody,
  req.headers['kyp-signature'],
  process.env.KYP_WEBHOOK_SECRET,
);

if (event.type === 'record.sealed') {
  await orders.attachProof(event.data.id);
}
event = kyp.webhooks.verify(
    body,
    headers["KYP-Signature"],
    os.environ["KYP_WEBHOOK_SECRET"],
)

if event.type == "record.sealed":
    orders.attach_proof(event.data.id)

Herramientas En desarrollo

Todo lo que te llevas a tu máquina.

  • SDK TypeScript@knowyourparcel/sdk

    Cliente tipado para Node y navegador: reintentos, idempotencia automática, iteradores de paginación y verificación de firma de webhooks.

  • SDK Pythonknowyourparcel

    Síncrono y asíncrono, con modelos tipados y verificación local de actas sin llamar a la API.

  • CLIkyp

    Inicia sesión, busca y verifica actas, escucha webhooks en local, levanta el sandbox y simula una estación.

  • Sandbox localkyp sandbox up

    La API en modo test, base de datos efímera, datos de ejemplo, el panel y un simulador de estación PackNSign que envía actas firmadas. Integras sin tocar producción ni consumir cuota.

  • Playgroundapp.knowyourparcel.com/playground

    Editor de peticiones con autocompletado del contrato, historial y variables, y conversión a curl, TypeScript, Python, PHP y Go.

  • Portal de documentacióndocs.knowyourparcel.com

    Referencia generada del contrato con «Pruébalo» (solo con tu clave de test), guías en español e inglés, recetas por caso de uso, changelog y estado del servicio.

  • Para máquinasopenapi.json · llms.txt

    Contrato OpenAPI 3.1 público, llms.txt y llms-full.txt para agentes, y colección de Postman y Bruno lista para importar.

$ kyp login
$ kyp sandbox up
$ kyp device simulate --model packnsign-60
$ kyp records list --reference ORD-88213
$ kyp verify KYP-2026-000123
$ kyp webhooks listen --forward http://localhost:3000/webhooks/kyp

Los SDK se descargan desde el panel; la publicación en npm y PyPI llega después.

Pide la documentación técnica y una clave de test.

Quiero la documentación