Identify & translate
One capability, four faces, one contract: EPCIS 1.1, 1.2 or 2.0 XML in — EPCIS 2.0 JSON-LD out, with a per-job round-trip fidelity report that names every lossy path or certifies there were none. The hosted door, the CLI verb, the MCP tool and the library function run the same engine; pick the face your integration already speaks.
POST /translate
| contract | value |
|---|---|
| Method, path | POST https://epcis.dev/translate |
| Auth | none — this door answers with no key and no account |
| Price class | free |
| Request | application/xml or text/xml: an EPCIS 1.1, 1.2 or 2.0 XML document |
| 200 response | application/json: { document, fidelityReport, meteredEvents, sourceSchemaVersion } |
| Response headers | GS1-EPCIS-Version, GS1-CBV-Version, GS1-Extensions, Spine-Translation-Fidelity, Spine-Translation-Lossy-Paths |
| CLI twin | npx epcis.dev translate <file.xml> [--out f.json] |
| MCP twin | tool translate — answers with no key on the apex POST /mcp door and locally over stdio |
| Library twin | import { translate, TranslationError } from "epcis.dev" |
Typed refusals
Errors are RFC 7807 application/problem+json carrying the standard's own epcisException:* types. Match on type, never on prose.
| status | type | meaning |
|---|---|---|
| 400 | epcisException:ValidationException | translation failed; the fidelity report and per-path schema errors ride the problem body |
| 413 | epcisException:CaptureLimitExceededException | payload exceeds the file-size limit |
| 415 | epcisException:UnsupportedMediaTypeException | this door accepts application/xml or text/xml; POST JSON to /validate or /hash |
Proof — run it against the live door
The fixture is EPCIS 1.1 XML, shipped in the npm tarball (node_modules/epcis.dev/golden-corpus/xml-translation/). Executed against the production door:
$ curl -sS -D - -X POST https://epcis.dev/translate \
-H 'content-type: application/xml' \
--data-binary @golden-corpus/xml-translation/aggregation-event-1.1.xml \
-o out.json
HTTP/2 200
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
And the body's receipt:
{
"sourceSchemaVersion": "1.1",
"meteredEvents": 1,
"fidelityReport": {
"roundTripClean": true,
"lossyPaths": [],
"notes": "Clean round-trip: every source value maps to a standard EPCIS 2.0 field."
}
}
The fidelity report is the door's own honesty mechanism: when a source construct has no clean 2.0 home, roundTripClean goes false and lossyPaths names each path — the door never silently drops data. The expected-output pair for every shipped XML fixture sits beside it as *.expected.json, so you can diff the door against the corpus yourself.
Where the rest of the family is
The dated launch ledger at /what-ships-today/ is authoritative for every door beyond this page. This reference lists exactly the rows that answer, and nothing else.
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.