EPCIS Profile Checker

OpenEPCIS tool to define EPCIS event profiles as JSON Schema and validate EPCIS documents or events against them.

Please find below the links to the application, its source code and the shared profile library referenced on this documentation page. We recommend using the web application and trying the examples as you read:

• Profile Checker web application : https://profile-checker.openepcis.io

• Web application source code : https://github.com/openepcis/openepcis-snippet-web

• Event Sentry SDK and profile library : https://github.com/openepcis/openepcis-event-sentry

• Example profiles with matching events : https://github.com/openepcis/openepcis-event-sentry/tree/main/examples

• Reusable JSON Schema snippets : https://github.com/openepcis/openepcis-event-sentry/tree/main/json-schema-epcis-snippets

• Container image : ghcr.io/openepcis/openepcis-snippet-web:latest

Introduction

The GS1 EPCIS standard was intentionally designed to be highly flexible. It tells you how to express the WHAT, WHEN, WHERE, WHY and HOW dimension of a critical business operation, and it leaves most of the detail to the implementer. That flexibility is what makes EPCIS usable across industries. But there is a downside. Two companies can both follow the standard correctly and yet still not be able to use each other's data. For example, if Company-A sends a shipping event without the read point, a partner Company-B that needs that field to know which warehouse the goods left from cannot use the data, even though no rule was broken.

Trading companies solve this by agreeing on stricter rules on their own: which event type to use for a shipment, which identifier must appear in epcList, whether a readPoint needs to be a plain GLN. These agreements are usually written down in a specification document, and somebody then manually validates incoming data against specification. That work is slow, requires manual efforts and prone to errors.

An event profile turns such an agreement into something a machine can check. A profile is a JSON Schema document that references the official GS1 EPCIS JSON Schema and adds the constraints the users have agreed on. Once the rules exist in that form, every partner can verify their own events before sending them, and the receiving side can reject bad data at the entry point instead of fixing them later.

The EPCIS Profile Checker covers both halves of that workflow. It gives you an editor for writing profiles and a validator for testing real events against them, with a library of pre-written schema fragments so you rarely have to start from an empty file.

What a profile defines

Consider an industry wants every shipping event exchanged between its members to follow the same shape. The agreement might read:

  • type must be ObjectEvent
  • bizStep must be either shipping or departing
  • epcList must contain at least one SSCC
  • readPoint must be a GLN without an extension
  • every GS1 identifier must be expressed as a GS1 Digital Link URI
  • the extension field for estimated time of arrival must contain a valid date and time

Each line becomes a constraint in the profile: an enum for the allowed business steps, a regular expression for the SSCC and GLN patterns, a format check for the timestamp, and a required list for the fields that may not be missing. Because the profile also references epcis-json-schema.json from GS1, an event still has to satisfy the base standard before the extra rules are even considered.

Usage

Profile Builder

The builder is a form-driven editor for profiles. You pick the event type, choose the business step and disposition values you want to allow, mark which identifiers and locations are mandatory, and add your own extension fields where the agreement calls for them. The resulting JSON Schema is shown next to the form and updates as you go, so you can see exactly which rule produced which constraint. Existing profiles from the Event Sentry repository can be loaded as a starting point and edited into a variant of your own. You also have an option to export/import the generated profile and configuration for future use.

Figure 1: EPCIS Profile Builder.

Event Validator

Here you select/paste a profile, paste an EPCIS document or a bare event into the editor, and run the check. A conforming event is reported as valid. A failing one is reported field by field, with the JSON path of the offending value and the reason it was rejected, which is usually enough to fix the source system without further investigation. All errors are collected in a single pass, so a document with several problems does not have to be validated multiple times.

Figure 2: EPCIS Profile validation success.

Figure 3: EPCIS Profile validation failure.

Profiles share a lot of building blocks. The patterns for an SGTIN, an SSCC or a GLN are the same wherever they appear, and rewriting those regular expressions manually is an easy way to introduce a bug. Snippet Search lets you look up ready-made JSON Schema fragments from the snippet library and drop them into a profile. The fragments are plain JSON Schema, so they are equally usable in projects that have nothing to do with EPCIS.

A worked example

A company publishes the shipping profile described above. A member company has just implemented its warehouse integration and wants to confirm the output before connecting to a partner. They generate a sample event with the Test Data Generator, open the Event Validator, select the published profile and paste the document:

{
  "@context": [
    { "example": "http://example.com/" },
    "https://ref.gs1.org/standards/epcis/epcis-context.jsonld"
  ],
  "type": "EPCISDocument",
  "schemaVersion": "2.0",
  "creationDate": "2026-04-02T12:43:58.63Z",
  "epcisBody": {
    "eventList": [
      {
        "type": "ObjectEvent",
        "eventTime": "2026-04-02T14:42:36+02:00",
        "eventTimeZoneOffset": "+02:00",
        "epcList": ["https://id.gs1.org/00/092567800000000018"],
        "action": "OBSERVE",
        "bizStep": "shipping",
        "readPoint": { "id": "https://id.gs1.org/414/9520123456788" },
        "example:estimatedTimeOfArrival": "2026-04-02T14:30:00Z"
      }
    ]
  }
}

This document passes. If the same integration had written bizStep as departing_from_dock and left the arrival time out, the validator would answer with the two reasons instead of a plain rejection:

{
  "success": false,
  "message": "Invalid Event",
  "errors": [
    {
      "field": "/epcisBody/eventList/0/bizStep",
      "message": "must be equal to one of the allowed values"
    },
    {
      "field": "/epcisBody/eventList/0",
      "message": "must have required property 'example:estimatedTimeOfArrival'",
      "params": { "missingProperty": "example:estimatedTimeOfArrival" }
    }
  ]
}

The same profile now serves three purposes: the association maintains one machine-readable definition, the sender checks its own data before transmission, and the receiver applies identical rules on arrival. Nobody compares events against a PDF.

Where this is useful

  • Onboarding a new trading partner. Hand over a profile instead of a specification chapter. The partner tests against it on their own schedule and only asks for help when a check fails.
  • Regulatory reporting. Food traceability under FSMA 204, deforestation reporting under the EUDR and product passport schemes all prescribe specific data points. Encoding those requirements as a profile makes the gap between what a regulation asks for and what a system actually sends visible immediately. The Event Sentry repository ships FSMA 204 test schemas as a reference.
  • Continuous checks in a pipeline. Because validation is ordinary JSON Schema work, the same profile can run in a build job or an integration test and fail the build when an event drifts out of shape.
  • Reviewing supplier data quality. Running a batch of received events through a profile gives you a concrete list of what each supplier gets wrong, which is a far better basis for a conversation than a general complaint about data quality.

Where the API sits

Validation itself runs in the browser. The web application compiles the selected profile with AJV on the client and supports JSON Schema draft-06, draft-07, draft 2019-09 and draft 2020-12, so the draft your profile declares is the draft that gets applied. Event data you paste into the validator stays on your machine, which matters when the events contain production identifiers.

Two remote sources are involved. Example profiles and the identifier snippets used by the builder are read directly from the public openepcis-event-sentry repository through the GitHub contents API. Snippet Search queries a backend endpoint, GET {SNIPPET_API_URL}/snippet?searchText=..., which the published container image points at https://api.epcis.cloud. Both the hosted application and your own instance can be repointed with the NUXT_PUBLIC_SNIPPET_API_URL environment variable. There is no server-side validation endpoint at present: profile checking happens in the browser or in your own code through the SDK.

Running your own instance

The container image is the quickest route:

docker pull ghcr.io/openepcis/openepcis-snippet-web:latest
docker run -p 3000:3000 ghcr.io/openepcis/openepcis-snippet-web:latest

The application is then available at http://localhost:3000. Podman works the same way, and the Docker guide in the repository covers compose files and the available environment variables.

To run from source you need Node.js 18 or later and pnpm:

git clone https://github.com/openepcis/openepcis-snippet-web.git
cd openepcis-snippet-web
pnpm install
pnpm dev

Application code

The tool is split across two repositories, both under the Apache 2.0 licence.

openepcis-snippet-web is the web application, built with Nuxt 4 and Nuxt UI, with CodeMirror 6 as the JSON editor and AJV as the validation engine.

openepcis-event-sentry is the JavaScript SDK together with the shared profile and snippet library. It builds bundles for both Node.js and the browser, and it is the piece to reach for when profile checking has to happen inside your own application. Alongside validate(document, schema) it provides the helpers that surround validation in practice: detectDocumentType to tell an EPCIS document from a query document or a bare event, isValidEpcisEvent, isValidEpcisDocument and isValidEpcisQueryDocument for structural checks, and profileDetectionRulesSchema and profileValidationRulesSchema for describing profile rules themselves.

The validator is imported from its module path, the way the repository's own tests use it:

import { validate } from './src/validation/validator';

const result = validate(epcisDocument, shippingProfile);

if (!result.success) {
  result.errors.forEach((error) => console.error(`${error.field}: ${error.message}`));
}

Further references

Last updated: