Docs

curl the live doors

One job: prove the doors answer, with nothing installed. Three calculators answer on this origin with no key and no account — POST /translate, POST /validate, POST /hash. The fixtures used below ship in the npm package (node_modules/epcis.dev/golden-corpus), but any EPCIS document of yours works the same way.

/translate — XML in, 2.0 JSON-LD out, fidelity in the headers

Executed 2026-07-31, against a 1.2 XML fixture from the golden corpus (response headers cut to the door's own contract):

$ curl -sS -D - -o out.json -X POST https://epcis.dev/translate \
    -H 'content-type: application/xml' \
    --data-binary @$CORPUS/xml-translation/object-event-1.2.xml
HTTP/2 200
content-type: application/json; charset=utf-8
gs1-cbv-version: 2.0.1
gs1-epcis-version: 2.0.1
gs1-extensions: spine=https://epcis.dev/ns/spine/v1
spine-translation-fidelity: round-trip-clean
spine-translation-lossy-paths: 0

The body is { document, fidelityReport, meteredEvents, sourceSchemaVersion }; this run's report reads "roundTripClean": true, "lossyPaths": []. Loss may exist on a job, but silence about it may not — a lossy path is enumerated, never dropped quietly.

/validate — the verdict against the pinned official schema

$ curl -sS -X POST https://epcis.dev/validate \
    -H 'content-type: application/json' \
    --data-binary @$CORPUS/valid-standard/object-event-shipping.json
{
  "valid": true,
  "schema": {
    "artefact": "epcis-json-schema.json",
    "version": "2.0.1",
    "sha256": "0f46ff694efffd8d8ce840a33dfde84228add11b516b8b258f3200740ae210af"
  },
  "errors": []
}

The verdict names the artefact it judged against and that artefact's sha256 — the same pin published on /conformance/. Recompute it; that is what the pin is for.

/hash — the standard's own identity

$ curl -sS -X POST https://epcis.dev/hash \
    -H 'content-type: application/json' \
    --data-binary @$CORPUS/valid-standard/object-event-shipping.json
{
  "algorithm": "CBV 2.0 §8.9 event hash",
  "count": 1,
  "hashes": [
    "ni:///sha-256;e5624abcce4b2fc226743e8891f69c12a07ad508953749d9b9ede6771424f91e?ver=CBV2.0"
  ]
}

The same fixture through npx epcis.dev hash on your bench produces the same URI, byte for byte — identity is computed, so it cannot depend on which door computed it.

Refusals are typed, not prose

Send the wrong media type and the door answers RFC 7807 application/problem+json carrying the standard's own exception type:

$ curl -sS -w '\nHTTP %{http_code}\n' -X POST https://epcis.dev/validate \
    -H 'content-type: application/xml' \
    --data-binary @$CORPUS/xml-translation/object-event-1.2.xml
{
  "type": "epcisException:UnsupportedMediaTypeException",
  "title": "Unsupported Media Type",
  "status": 415,
  "detail": "/validate accepts application/json or application/ld+json (got \"application/xml\"); POST XML to /translate"
}
HTTP 415

Match on type, never on the detail prose. The machine description of these doors is generated from the same typed catalog as this page: /openapi.json.

We answer in writing. We take at most five conversations a month, only when you ask for one, and only after you already have the written read.