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
Cuenta y 2FA
Entras y activas el segundo factor. Para propietarios y administradores es obligatorio.
- 2
Tu clave de test
El asistente de claves, en tres pasos. Las claves de test no consumen cuota.
- 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
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
Mira el registro
La llamada que acabas de hacer ya aparece en el registro de API de tu cuenta.
- 6
Recibe un webhook
En la bandeja de pruebas del panel o en tu propia URL. Con reenvío manual.
- 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){
"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-000123const 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 3161Claves y tokens
Claves en tres pasos.
- 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.
- 02
Ámbitos, en lenguaje llano
Plantillas listas: solo lectura, integración de almacén, verificación pública, dispositivo. O ámbito a ámbito.
- 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.
{
"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…"
}
]
}{
"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.
{
"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.
{
"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.
{
"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.
{
"filename": "top.jpg",
"mime": "image/jpeg",
"bytes": 4182231,
"sha256": "…3b9e"
}{
"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.
{
"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.
multipart/form-data file=@KYP-2026-000123.pdf{
"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.
{
"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.
{
"a": "KYP-2026-000123",
"b": "KYP-2026-000481"
}{
"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.
{
"reference": "ORD-88213",
"declared": {
"weight_kg": 1.2,
"dims_cm": [
30,
20,
10
],
"items": 1
}
}{
"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.
{
"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.
{
"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.
{
"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.
{
"records": [
"KYP-2026-000123"
],
"claim": {
"type": "damage",
"counterparty": "carrier",
"reference": "1Z…"
},
"lang": "en"
}{
"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.
{
"from": "2026-10-01",
"to": "2026-10-31",
"format": "zip"
}{
"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.
{
"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.
{
"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.
{
"transactions": [
"trx_01J…"
],
"expires_in_hours": 72,
"password": true,
"label": "claim-4471"
}{
"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.
{
"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.
{
"subject": {
"type": "parcel",
"id": "prc_01J…"
},
"template": "passport",
"visibility": "link",
"expires_at": "2026-12-31",
"lang": "auto"
}{
"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.
{
"password": "set",
"expires_at": "2027-01-31"
}{
"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.
{
"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.
{
"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.
{
"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.
{
"label": "warehouse-desk-2"
}{
"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.
{
"platform": "android",
"attestation": "eyJ…",
"public_key": "MCow…",
"flow": "return"
}{
"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.
{
"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.
{
"url": "https://example.com/webhooks/kyp",
"events": [
"record.sealed",
"alert.raised"
],
"environment": "test"
}{
"id": "whk_01J…",
"secret": "whsec_…",
"status": "active"
}POST/v1/webhooks/{id}/testEnvía un evento de prueba y te enseña la 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.
{
"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.
{
"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.
{
"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: 41POST /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/sdkCliente tipado para Node y navegador: reintentos, idempotencia automática, iteradores de paginación y verificación de firma de webhooks.
SDK Python
knowyourparcelSíncrono y asíncrono, con modelos tipados y verificación local de actas sin llamar a la API.
CLI
kypInicia sesión, busca y verifica actas, escucha webhooks en local, levanta el sandbox y simula una estación.
Sandbox local
kyp sandbox upLa 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.
Playground
app.knowyourparcel.com/playgroundEditor de peticiones con autocompletado del contrato, historial y variables, y conversión a curl, TypeScript, Python, PHP y Go.
Portal de documentación
docs.knowyourparcel.comReferencia 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áquinas
openapi.json · llms.txtContrato 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/kypLos SDK se descargan desde el panel; la publicación en npm y PyPI llega después.