Desarrolladores

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.

Base https://parcid.com/api/v1

Pantalla oscura con líneas de código desenfocadas y un código cuadrado de luz dorada.

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.

Medidas (mm, opcional)
Peso (g, opcional)
Evidencias (opcional)

Se calcula la huella en tu navegador. No se sube ningún archivo.

    API v1

    Endpoints

    https://parcid.com/api/v1 · JSON UTF-8 · sin cuenta para registrar y resolver

    Método y rutaAuthQué hace
    Registrar y resolver
    GET /verify/{PID}Sin autenticaciónValida 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.
    GET /parcels/{PID}Sin autenticaciónResolución pública: lo que cualquiera puede ver (SPEC §3.4), incluido el perfil de unidad y el anclaje del alta.
    POST /parcelsSin 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.
    GET /00/{SSCC} · fuera de /api/v1Sin autenticaciónGS1 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.
    Con la llave de la unidad
    GET /parcels/{PID}Llave de la unidadResolución completa para el titular: acta de alta, firma física, evidencias con URL firmadas de corta vida, enlaces privados, avistamientos con detalle.
    POST /parcels/{PID}/linksLlave de la unidadAñade referencias externas (seguimiento, SSCC, pedido, contenedor BIC, precinto, GRAI, etiqueta de equipaje) con visibilidad privada o pública.
    POST /parcels/{PID}/lineageLlave de los padresDeclara apertura, consolidación, división o reembalaje y crea el hijo.
    POST /parcels/{PID}/statusLlave de la unidadCambia el estado a retired (entregado y cerrado) o lost.
    POST /parcels/{PID}/rotate-keyLlave de la unidadEmite una llave nueva y anula la anterior.
    POST /parcels/{PID}/sightingsClave de operador + llave de la unidadAvistamiento 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.
    POST /reservationsDispositivo homologado o clave de desarrolladorReserva de bloques de PID para estaciones sin red, firmada por el dispositivo. Caducan a los 90 días y nunca se reemiten.
    Pruebas y anclas
    GET /parcels/{PID}/proofSin autenticaciónPrueba de inclusión de cada acta de la unidad: ruta Merkle RFC 6962, declaración diaria firmada y prueba OpenTimestamps.
    GET /anchorsSin autenticaciónCadena de declaraciones diarias: raíz Merkle, firma Ed25519, encadenado y estado en Bitcoin.
    GET /anchors/{día}Sin autenticaciónDeclaración de un día y su prueba OpenTimestamps; con .ots, el fichero binario para ots verify.
    Datos abiertos y estado
    GET /exportSin autenticaciónÍndice de exportaciones diarias: día, URL, tamaño, huella, unidades y manifiesto firmado. CC0.
    GET /export/parcid-export-{AAAAMMDD}.jsonl.gzSin autenticaciónExportació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.
    GET /.well-known/parcid · fuera de /api/v1Sin autenticaciónMetadatos del registro: versión, claves públicas (kid), formato del ID, transparencia, exportación y límites.
    GET /statsSin autenticaciónCifras agregadas: unidades por perfil, nivel y estado, actas por tipo, última ancla y exportación, peticiones de 24 h.
    GET /healthSin autenticaciónSalud del servicio: ok, degraded o down (503), con las comprobaciones y las tareas diarias.
    POST /beaconSin autenticaciónContador 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.

    curl https://parcid.com/api/v1/verify/pid-1-7qc3-z79d-g6rz-8e

    GET /parcels/{PID}

    Sin autenticación

    Resolución pública: lo que cualquiera puede ver (SPEC §3.4), incluido el perfil de unidad y el anclaje del alta.

    curl -H 'Accept: application/json' https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E

    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.

    curl -X POST https://parcid.com/api/v1/parcels \
      -H 'Content-Type: application/json' \
      -d '{
        "capture_class": "api",
        "unit_profile": "parcel",
        "captured_at": "2026-11-18T09:40:58Z",
        "dimensions_mm": { "l": 412, "w": 306, "h": 218, "tolerance_mm": 3 },
        "weight_g": { "value": 3840, "tolerance_g": 5, "scale_class": "consumer" },
        "evidence": [ { "role": "top", "sha256": "sha256:0c7e…", "mime": "image/jpeg", "bytes": 2418833 } ],
        "links": [ { "kind": "sscc", "value": "003412345678901238", "visibility": "public" } ],
        "consent": { "no_personal_data": true, "terms_version": "2026-10" }
      }'

    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.

    curl -H 'Accept: application/json' https://parcid.com/00/003412345678901238

    GET /parcels/{PID}

    Llave de la unidad

    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 -H "Authorization: Bearer $PIDK" https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E

    POST /parcels/{PID}/lineage

    Llave de los padres

    Declara apertura, consolidación, división o reembalaje y crea el hijo.

    curl -X POST https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/lineage \
      -H "Authorization: Bearer $PIDK" -H 'Content-Type: application/json' \
      -d '{ "operation": "repack", "consent": { "no_personal_data": true, "terms_version": "2026-10" } }'
    # consolidate: "parents": [ { "pid": "PID-…", "owner_key": "pidk_…" } ]

    POST /parcels/{PID}/status

    Llave de la unidad

    Cambia el estado a retired (entregado y cerrado) o lost.

    curl -X POST https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/status \
      -H "Authorization: Bearer $PIDK" -H 'Content-Type: application/json' \
      -d '{ "status": "retired", "reason_code": "delivered" }'

    POST /parcels/{PID}/rotate-key

    Llave de la unidad

    Emite una llave nueva y anula la anterior.

    curl -X POST -H "Authorization: Bearer $PIDK" https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/rotate-key

    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"}

    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.

    curl -X POST https://parcid.com/api/v1/reservations -H 'Content-Type: application/json' -d '{
      "device": { "public_key": "ed25519:…" },
      "count": 500, "requested_at": "2026-11-18T09:40:00Z", "nonce": "r4nd0m-n0nce",
      "device_signature": "…"
    }'
    # device_signature: Ed25519 over sha256(JCS({schema:"parcid.reservation-request/1", public_key, count, requested_at, nonce}))

    GET /parcels/{PID}/proof

    Sin autenticación

    Prueba de inclusión de cada acta de la unidad: ruta Merkle RFC 6962, declaración diaria firmada y prueba OpenTimestamps.

    curl https://parcid.com/api/v1/parcels/PID-1-7QC3-Z79D-G6RZ-8E/proof
    # verify it without us: node cli.mjs proof PID-1-7QC3-Z79D-G6RZ-8E

    GET /anchors

    Sin autenticación

    Cadena de declaraciones diarias: raíz Merkle, firma Ed25519, encadenado y estado en Bitcoin.

    curl "https://parcid.com/api/v1/anchors?from=2026-11-01&limit=30"

    GET /anchors/{día}

    Sin autenticación

    Declaración de un día y su prueba OpenTimestamps; con .ots, el fichero binario para ots verify.

    curl https://parcid.com/api/v1/anchors/2026-11-18
    curl -o 2026-11-18.ots https://parcid.com/api/v1/anchors/2026-11-18.ots
    # ots verify 2026-11-18.ots, or: node cli.mjs ots 2026-11-18.ots --bitcoin

    GET /export

    Sin autenticación

    Índice de exportaciones diarias: día, URL, tamaño, huella, unidades y manifiesto firmado. CC0.

    curl https://parcid.com/api/v1/export
    # { license: "CC0-1.0", exports: [ { day, url, bytes, sha256, units, manifest, signature } ] }

    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.

    curl -O https://parcid.com/api/v1/export/parcid-export-20261118.jsonl.gz
    node cli.mjs export parcid-export-20261118.jsonl.gz --pid PID-1-7QC3-Z79D-G6RZ-8E

    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.

    curl https://parcid.com/.well-known/parcid

    GET /stats

    Sin autenticación

    Cifras agregadas: unidades por perfil, nivel y estado, actas por tipo, última ancla y exportación, peticiones de 24 h.

    curl https://parcid.com/api/v1/stats

    GET /health

    Sin autenticación

    Salud del servicio: ok, degraded o down (503), con las comprobaciones y las tareas diarias.

    curl https://parcid.com/api/v1/health

    POST /beacon

    Sin autenticación

    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

    La llave de la unidad

    Control total sobre una unidad. Y nada más.

    • Formato pidk_ + 52 símbolos Crockford (260 bits). Se devuelve una sola vez, en la respuesta del alta.
    • El registro guarda solo SHA-256(llave). Quien la pierde no puede recuperarla: no hay datos personales a los que atar una recuperación.
    • Permite leer la unidad entera, enlazar referencias, declarar linaje, cambiar el estado y rotar la llave.
    • Se envía en la cabecera Authorization: Bearer pidk_…, nunca en la URL.
    • En linaje, el hijo nace con llave propia y se devuelve a quien declaró la operación.
    • Guárdala en tu sistema junto al PID y al acta de alta, que podrás verificar cuando quieras en /verificar.

    Errores

    Respuestas previsibles.

    {"error":"código","message":"texto","request_id":"…"}.

    HTTPSignificado
    200Existe (cualquier estado, incluido revoked)
    301Forma no canónica → canónica
    404Formato válido, no registrado
    422Formato o control inválidos
    429Límite de consultas
    errorCuándo
    invalid_idformato o control inválidos
    not_foundno registrado
    unauthorizedllave incorrecta
    forbiddenel estado no lo permite
    payload_too_largearchivo demasiado grande
    unsupported_mediatipo no admitido
    rate_limitedlímite alcanzado
    consent_requiredfalta el consentimiento
    lineage_conflictoperación de linaje incoherente
    paid_serviceservicio del operador no contratado

    Nivel gratuito

    Límites Propuesta v0.1 · pendiente de decisión

    ConceptoPropuesta
    Altas sin clave de desarrollador100 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ública60 por minuto por IP; 600 por minuto con clave
    GET /verify600 por minuto por IP
    Evidencias en bruto del nivel gratuito30 días cifradas; después solo huellas
    Firma física y actaSe conservan indefinidamente
    Tamaño por alta25 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.