Una API libre. Sin cuenta para registrar ni para resolver.
JSON UTF-8 sobre HTTPS. La identidad la controla una llave por unidad, no una cuenta. Toda llamada queda en el registro de API del operador, con las claves enmascaradas.
Basehttps://parcid.com/api/v1
Pruébalo
Crea tu primer PID.
Alta de clase api, nivel 0 (registrado sin verificar). Elige el perfil de unidad; medidas y peso son opcionales. Si eliges fotos, tu navegador calcula su huella SHA-256 y solo se envían las huellas: los archivos no salen de tu equipo.
Especificación v0.1 · borrador: rutas y semántica pueden cambiar antes del lanzamiento.
API v1
Endpoints
https://parcid.com/api/v1 · JSON UTF-8 · sin cuenta para registrar y resolver
Valida formato y control, normaliza y dice si existe y su estado. Para lectores de etiqueta, formularios y agentes: barato y sin contar como resolución.
Alta: crea el PID y devuelve la llave una sola vez, junto al acta sellada. JSON si solo envías huellas; multipart si subes archivos. Un SSCC entra como enlace.
GS1 Digital Link: un SSCC enlazado en público resuelve a sus PID. Cada uno indica claim: «operator» (lo enlazó un operador identificado) o «self_declared» (sin verificar: cualquiera puede enlazar un SSCC público). El PID no es una clave GS1.
Resolución completa para el titular: acta de alta, firma física, evidencias con URL firmadas de corta vida, enlaces privados, avistamientos con detalle.
Avistamiento con comparación 1:1 (SPEC §8). Lo hace un operador: su clave pidd_ con el servicio contratado va en Authorization y la llave de la unidad en X-Parcid-Owner-Key.
Exportación completa del día en JSON Lines + gzip: unidades (por una huella con sal por unidad, pid_tag + pid_salt; nunca el PID en claro), actas del libro, anclas y manifiesto firmado.
Contador de visitas de esta web: ruta, procedencia e idioma. Sin cookies ni identificadores; la IP no se guarda. Responde 204.
GET /verify/{PID}
Sin autenticación
Valida formato y control, normaliza y dice si existe y su estado. Para lectores de etiqueta, formularios y agentes: barato y sin contar como resolución.
const r = await fetch('https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E');
if (r.status === 404) console.log('valid format, not registered');
const unit = await r.json();
// status, unit_profile, assurance_level, lineage, enrolment.anchor…
POST /parcels
Sin cuenta (clave de desarrollador opcional)
Alta: crea el PID y devuelve la llave una sola vez, junto al acta sellada. JSON si solo envías huellas; multipart si subes archivos. Un SSCC entra como enlace.
const r = await fetch('https://parcid.com/api/v1/parcels', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
capture_class: 'api',
unit_profile: 'pallet_load', // parcel | pallet_load | container_load | tote | bag | crate
captured_at: new Date().toISOString(),
consent: { no_personal_data: true, terms_version: '2026-10' },
}),
});
const { pid, owner_key, enrolment_record } = await r.json();
// 201 · store owner_key and enrolment_record now: the key is shown only once
GET /00/{SSCC}
Sin autenticaciónfuera de /api/v1
GS1 Digital Link: un SSCC enlazado en público resuelve a sus PID. Cada uno indica claim: «operator» (lo enlazó un operador identificado) o «self_declared» (sin verificar: cualquiera puede enlazar un SSCC público). El PID no es una clave GS1.
Resolución completa para el titular: acta de alta, firma física, evidencias con URL firmadas de corta vida, enlaces privados, avistamientos con detalle.
curl -X POST -H "Authorization: Bearer $PIDK" https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/rotate-key
const r = await fetch('https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/rotate-key', {
method: 'POST', headers: { Authorization: 'Bearer ' + ownerKey },
});
const { owner_key } = await r.json(); // the previous key is revoked
POST /parcels/{PID}/sightings
Clave de operador + llave de la unidad
Avistamiento con comparación 1:1 (SPEC §8). Lo hace un operador: su clave pidd_ con el servicio contratado va en Authorization y la llave de la unidad en X-Parcid-Owner-Key.
curl -X POST https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/sightings \
-H "Authorization: Bearer $PIDD" -H "X-Parcid-Owner-Key: $PIDK" -F capture_class=station \
-F 'evidence[top]=@top.jpg' -F 'evidence[perspective]=@perspective.jpg'
# $PIDD: operator key with the contracted service · without it: 402 {"error":"paid_service"}
const form = new FormData();
form.append('capture_class', 'mobile_sdk');
form.append('evidence[top]', file);
const r = await fetch('https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/sightings', {
method: 'POST',
headers: { Authorization: 'Bearer ' + operatorKey, 'X-Parcid-Owner-Key': ownerKey },
body: form,
});
// match.decision: 'match' | 'review' | 'no_match', with an explanation
POST /reservations
Dispositivo homologado o clave de desarrollador
Reserva de bloques de PID para estaciones sin red, firmada por el dispositivo. Caducan a los 90 días y nunca se reemiten.
const { exports } = await (await fetch('https://parcid.com/api/v1/export')).json();
const latest = exports.at(-1); // daily, CC0, units identified by a per-unit salted tag (pid_tag + pid_salt)
GET /export/parcid-export-{AAAAMMDD}.jsonl.gz
Sin autenticación
Exportación completa del día en JSON Lines + gzip: unidades (por una huella con sal por unidad, pid_tag + pid_salt; nunca el PID en claro), actas del libro, anclas y manifiesto firmado.
const gz = await fetch(latest.url);
const text = await new Response(gz.body.pipeThrough(new DecompressionStream('gzip'))).text();
const res = await verifyExport(text.split('\n')); // from parcid-verify.js
GET /.well-known/parcid
Sin autenticaciónfuera de /api/v1
Metadatos del registro: versión, claves públicas (kid), formato del ID, transparencia, exportación y límites.
Contador de visitas de esta web: ruta, procedencia e idioma. Sin cookies ni identificadores; la IP no se guarda. Responde 204.
curl -X POST https://parcid.com/api/v1/beacon -H 'Content-Type: application/json' \
-d '{ "p": "/como-funciona/", "r": "", "l": "es" }'
# 204 · no cookies, no identifiers, IP never stored
navigator.sendBeacon('/api/v1/beacon', new Blob([JSON.stringify({
p: location.pathname, r: document.referrer, l: 'es',
})], { type: 'application/json' })); // only the path, referrer host and language are counted
100 al mes por dirección IP y por clave de dispositivo
Altas con clave de desarrollador gratuita (correo verificado)
1.000 al mes
Resolución pública
60 por minuto por IP; 600 por minuto con clave
GET /verify
600 por minuto por IP
Evidencias en bruto del nivel gratuito
30 días cifradas; después solo huellas
Firma física y acta
Se conservan indefinidamente
Tamaño por alta
25 MB por imagen, 200 MB vídeo, 50 MB nube de puntos; 300 MB en total
Las altas sin firma de dispositivo quedan en nivel 0 y cuentan contra límites más estrictos.
Cada fuente (clave de dispositivo, de desarrollador, IP) acumula reputación: muchas altas huérfanas o incoherentes bajan el nivel máximo que puede obtener. Se publica en agregado, no por fuente.
Descargas
Código de referencia en dominio público.
Generar, normalizar y validar un PID, y verificar actas, pruebas y exportaciones, sin dependencias. Comprobado: 0 sustituciones y 0 transposiciones adyacentes sin detectar.