EPCIS 2.0 Repository

📘

Enterprise feature

If you're interested in using this enterprise feature, contact us.

epcis2.js, is our open-source SDK for building EPCIS clients. It eases the interactions with EPCIS repositories and APIs, such as the one provided by the EVRYTHNG Product Cloud.

EPCIS is a GS1 standard for capturing and querying supply chain events. EPCIS is especially valuable to facilitate the seamless exchange of information in supply chains that span multiple organizations. The EPCIS 2.0 standard was ratified in July 2002 by the GS1 working group EVRYTHNG helped drive.

This tutorial teaches you how to use the EPCIS 2.0 APIs to capture supply chain events and leverage them in your EVRYTHNG Product Cloud account for traceability, consumer engagement, or brand integrity applications.

By adding support for EPCIS, your Product Cloud account becomes the platform for a frictionless integration of your business processes in complex supply chain information systems and consumer-facing apps. A related topic is the Digital Link, which turns the QR code on product packages and labels into the bridge between business-facing IT systems and consumer-facing apps.


EPCIS Events and EPCIS Repository

EPCIS systems communicate by sending events. EPCIS supports five event types, namely ObjectEvent, AggregationEvent, AssociationEvent, TransformationEvent and TransactionEvent. But you can also specify your own type. EPCIS events are snapshots of supply chain transactions, describing:35 secs

  • What: One or more items (pallet, individual products, and so on) that are of concern
  • When: At what time this event occurred
  • Where: The place where items are being shipped, received, and expected
  • Why: The business context that describes the process-related information
  • How: This dimension was added in 2.0 and captures IoT data (sensor information) from and about events.

An EPCIS repository is an append-only database because events are snapshots of the state of a supply chain. This is important to ensure transparency, accountability, and traceability. If, for example, a supplier ships ten pallets to a manufacturer and that shipment only contains five pallets on arrival, the manufacturer doesn't ask the supplier to change the event. Instead, the manufacturer creates a new EPCIS event that captures the discrepancy.

Unlike previous versions which were XML based, by default EPCIS 2.0 encodes EPCIS events as JSON (JSON-LD) objects. A JSON-Schema is available to formalize the EPCIS data definition.

{
  // Event Type
  "type": "ObjectEvent",

  // When
  "eventTime": "2005-04-03T20:33:31.116-06:00",
  "eventTimeZoneOffset": "-06:00",

  // What
  "epcList": [
    "urn:epc:id:sgtin:0614141.107346.2017",
    "urn:epc:id:sgtin:0614141.107346.2018"
  ],

  // Where
  "readPoint": "urn:epc:id:sgln:0614141.07346.1234",

  // Why
  "action": "OBSERVE",
  "bizStep": "shipping",
  "disposition": "in_transit",
  "bizTransactionList": [
    {
      "type": "po",
      "bizTransaction": "http://transaction.acme.com/po/12345678"
    }
  ]
}

Using EPCIS 2.0 with the Product Cloud

The Product Cloud features EPCIS 2.0, which stores raw EPCIS events and a way to map these events to Product Cloud data through the Reactor (for example, mapping events to Actions).
This means you can keep using the Product Cloud to build consumer-facing applications and seamlessly leverage the EPCIS 2.0 standard.

2300

Capturing EPCIS Events

To create your first ObjectEvent, take one of the official examples from The GS1 Github and try:

curl --location --request POST 'https://api.evrythng.io/v2/epcis/capture' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
   "@context":[
      "https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld",
      {
         "example":"http://ns.example.com/epcis/"
      }
   ],
   "id":"https://id.example.org/document1",
   "type":"EPCISDocument",
   "schemaVersion":"2.0",
   "creationDate":"2005-07-11T11:30:47.0Z",
   "epcisBody":{
      "eventList":[
         {
            "eventID":"ni:///sha-256;df7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69?ver=CBV2.0",
            "type":"ObjectEvent",
            "action":"OBSERVE",
            "bizStep":"shipping",
            "disposition":"in_transit",
            "epcList":[
               "urn:epc:id:sgtin:0614141.107346.2017",
               "urn:epc:id:sgtin:0614141.107346.2018"
            ],
            "eventTime":"2005-04-03T20:33:31.116000-06:00",
            "eventTimeZoneOffset":"-06:00",
            "readPoint":{
               "id":"urn:epc:id:sgln:0614141.07346.1234"
            },
            "bizTransactionList":[
               {
                  "type":"po",
                  "bizTransaction":"http://transaction.acme.com/po/12345678"
               }
            ]
         },
         {
            "eventID":"ni:///sha-256;00e1e6eba3a7cc6125be4793a631f0af50f8322e0ab5f2c0bab994a11cec1d79?ver=CBV2.0",
            "type":"ObjectEvent",
            "action":"OBSERVE",
            "bizStep":"receiving",
            "disposition":"in_progress",
            "epcList":[
               "urn:epc:id:sgtin:0614141.107346.2018"
            ],
            "eventTime":"2005-04-04T20:33:31.116-06:00",
            "eventTimeZoneOffset":"-06:00",
            "readPoint":{
               "id":"urn:epc:id:sgln:0012345.11111.400"
            },
            "bizLocation":{
               "id":"urn:epc:id:sgln:0012345.11111.0"
            },
            "bizTransactionList":[
               {
                  "type":"po",
                  "bizTransaction":"http://transaction.acme.com/po/12345678"
               },
               {
                  "type":"desadv",
                  "bizTransaction":"urn:epcglobal:cbv:bt:0614141073467:1152"
               }
            ],
            "example:myField":"Example of a vendor/user extension"
         }
      ]
   }
}'
setup({
  apiUrl: 'https://api.evrythng.io/v2/epcis/',
  EPCISDocumentSchemaVersion: '2.0',
  headers: {
    'content-type': 'application/json',
    authorization: 'API_KEY',
  },
});


const sendACaptureRequestExample = async () => {

  const epcisDocument = new EPCISDocument();
  const objectEvent1 = new ObjectEvent();
  const objectEvent2 = new ObjectEvent();
  
  objectEvent1
    .setEventID('ni:///sha-256;df7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69?ver=CBV2.0')
    .setAction(cbv.actionTypes.observe)
    .addEPC('urn:epc:id:sgtin:0614141.107346.2017')
    .addEPC('urn:epc:id:sgtin:0614141.107346.2018')
    .setEventTime('2005-04-03T20:33:31.116000-06:00')
    .setEventTimeZoneOffset('-06:00')
    .setBizStep(cbv.bizSteps.shipping)
    .setDisposition(cbv.dispositions.in_transit)
    .setReadPoint( new ReadPoint().setId('urn:epc:id:sgln:0614141.07346.1234') ) 
    .addBizTransactionList([
      new BizTransactionElement ({
        "type": "po",
        "bizTransaction": "http://transaction.acme.com/po/12345678"
      }),
    ]);

  objectEvent2
  .setEventID('ni:///sha-256;00e1e6eba3a7cc6125be4793a631f0af50f8322e0ab5f2c0bab994a11cec1d79?ver=CBV2.0')
  .setAction(cbv.actionTypes.observe)
  .addEPC('urn:epc:id:sgtin:0614141.107346.2018')
  .setEventTime('2005-04-04T20:33:31.116-06:00')
  .setEventTimeZoneOffset('-06:00')
  .setBizStep(cbv.bizSteps.shipping)
  .setDisposition(cbv.dispositions.in_transit)
  .setReadPoint( new ReadPoint().setId('urn:epc:id:sgln:0012345.11111.400') )
  .setBizLocation({
    "id":"urn:epc:id:sgln:0012345.11111.0"
  })
  .addBizTransactionList([
    new BizTransactionElement ({
      "type": "po",
      "bizTransaction": "http://transaction.acme.com/po/12345678"
    }),
    new BizTransactionElement ({
      "type": "desadv",
      "bizTransaction": "urn:epcglobal:cbv:bt:0614141073467:1152"
    })
  ])
  .addExtension('example:myField','Example of a vendor/user extension');
      
  epcisDocument
    .setContext([
      "https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld",
      {
         "example":"http://ns.example.com/epcis/"
      }
   ])
    .setId('https://id.example.org/document1')
    .setCreationDate('2005-07-11T11:30:47.0Z')
    .addEvent(objectEvent1)
    .addEvent(objectEvent2);
  
  const res = await capture(epcisDocument);
  const text = await res.text();
  console.log(`Request status: ${res.status}`);
  console.log(`Request response: ${text}`);
};

sendACaptureRequestExample();
HTTP/2 202 ACCEPTED

Capturing EPCIS Event Containing GS1 Digital Links Identifiers

Unlike previous versions of the standard, EPCIS 2.0 supports not only EPC identifiers as URNs but also identifiers supported by the GS1 Digital Link standard. Here is an example of a valid EPCIS capture request using GS1 Digital Links and EPC URNs:

curl --location --request POST 'https://api.evrythng.io/v2/epcis/capture' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
   "@context":[
      "https://ref.gs1.org/standards/epcis/2.0/epcis-context.jsonld",
      {
         "example":"http://ns.example.com/epcis/"
      }
   ],
   "id":"https://id.example.org/document1",
   "type":"EPCISDocument",
   "schemaVersion":"2.0",
   "creationDate":"2005-07-11T11:30:47.0Z",
   "epcisBody":{
      "eventList":[
         {
            "type":"ObjectEvent",
            "action":"OBSERVE",
            "bizStep":"shipping",
            "disposition":"in_transit",
            "epcList":[
               "https://dlnkd.tn.gg/01/9780345418913/21/123458",
               "urn:epc:id:sgtin:4000001.065432.99886655"
            ],
            "eventTime":"2005-04-03T20:33:31.116000-06:00",
            "eventTimeZoneOffset":"-06:00",
            "readPoint":{
               "id":"https://dlnkd.tn.gg/414/9780345418913"
            },
            "bizTransactionList":[
               {
                  "type":"po",
                  "bizTransaction":"http://transaction.acme.com/po/12345678"
               }
            ]
         },
      ]
   }
}'
setup({
  apiUrl: 'https://api.evrythng.io/v2/epcis/',
  EPCISDocumentContext: 'https://ref.gs1.org/standards/epcis/2.0/epcis-context.jsonld',
  EPCISDocumentSchemaVersion: '2.0',
  headers: {
    'content-type': 'application/json',
    authorization: 'MY_API_KEY',
  },
});


const sendACaptureRequestExample = async () => {

  const epcisDocument = new EPCISDocument();
  const objectEvent = new ObjectEvent();
  
  objectEvent
    .addEPC('https://dlnkd.tn.gg/01/9780345418913/21/123458')
    .addEPC('urn:epc:id:sgtin:4000001.065432.99886655')
    .setEventTime('2005-04-03T20:33:31.116000-06:00')
    .setEventTimeZoneOffset('-06:00')
    .setBizStep(cbv.bizSteps.shipping)
    .setDisposition(cbv.dispositions.in_transit)
    .setReadPoint( new ReadPoint().setId('https://dlnkd.tn.gg/414/9780345418913') ) 
    .addBizTransactionList([
      new BizTransactionElement ({
        "type": "po",
        "bizTransaction": "http://transaction.acme.com/po/12345678"
      }),
    ]);
      
  epcisDocument
    .setContext([
      "https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld",
      {
         "example":"http://ns.example.com/epcis/"
      }
   ])
    .setId('https://id.example.org/document1')
    .setCreationDate('2005-07-11T11:30:47.0Z')
    .addEvent(objectEvent);

  const res = await capture(epcisDocument);
  const text = await res.text();
  console.log(`Request status: ${res.status}`);
  console.log(`Request response: ${text}`);
};

sendACaptureRequestExample();
HTTP/2 202 ACCEPTED

Capturing EPCIS Event Containing IoT Sensor Data

One of the innovations EPCIS 2.0 brings is the support for IoT sensor data. This is well aligned with the growing numbers of product tags that also have sensing capabilities.
Here is a capture example that leverages this feature to record temperature data as part of an inspection step:

curl --location --request POST 'https://api.evrythng.io/v2/epcis/capture' \
--header 'Authorization: API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
   "@context":[
      "https://ref.gs1.org/standards/epcis/2.0/epcis-context.jsonld",
      {
         "example":"http://ns.example.com/epcis/"
      }
   ],
   "id":"https://id.example.org/document1",
   "type":"EPCISDocument",
   "schemaVersion":"2.0",
   "creationDate":"2005-07-11T11:30:47.0Z",
   "epcisBody":{
      "eventList":[
         {
            "type":"ObjectEvent",
            "action":"OBSERVE",
            "bizStep":"inspecting",
            "epcList":[
               "urn:epc:id:sgtin:4012345.011111.9876"
            ],
            "eventTime":"2019-04-02T15:00:00.000+01:00",
            "eventTimeZoneOffset":"+01:00",
            "readPoint":{
               "id":"urn:epc:id:sgln:4012345.00005.0"
            },
            "sensorElementList":[
               {
                  "sensorMetadata":{
                     "startTime":"2019-04-01T15:00:00.000+01:00",
                     "endTime":"2019-04-02T14:59:59.999+01:00"
                  },
                  "sensorReport":[
                     {
                        "type":"Temperature",
                        "minValue":12.4,
                        "maxValue":13.8,
                        "uom":"CEL"
                     }
                  ]
               }
            ]
         }
      ]
   }
}'
setup({
  apiUrl: 'https://api.evrythng.io/v2/epcis/',
  EPCISDocumentContext: 'https://ref.gs1.org/standards/epcis/2.0/epcis-context.jsonld',
  EPCISDocumentSchemaVersion: '2.0',
  headers: {
    'content-type': 'application/json',
    authorization: 'MY_API_KEY',
  },
});


const sendACaptureRequestExample = async () => {

  const epcisDocument = new EPCISDocument();
  const objectEvent = new ObjectEvent();
  
  objectEvent
    .setAction(cbv.actionTypes.observe)
    .addEPC('urn:epc:id:sgtin:4012345.011111.9876')
    .setEventTime('2019-04-02T15:00:00.000+01:00')
    .setEventTimeZoneOffset('+01:00')
    .setBizStep(cbv.bizSteps.inspecting)
    .setReadPoint( new ReadPoint().setId('urn:epc:id:sgln:4012345.00005.0') ) 
    .addSensorElement(
      new SensorElement()
      .setSensorMetadata(
        new SensorMetadata()
          .setStartTime("2019-04-01T15:00:00.000+01:00")
          .setEndTime("2019-04-02T14:59:59.999+01:00")
        )
      .addSensorReport(
        new SensorReportElement()
          .setType(cbv.sensorMeasurementTypes.temperature)
          .setMinValue(12.4)
          .setMaxValue(13.8)
          .setUom('CEL')
      )
    );
      
  epcisDocument
    .setContext([
      "https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld",
      {
         "example":"http://ns.example.com/epcis/"
      }
   ])
    .setId('https://id.example.org/document1')
    .setCreationDate('2005-07-11T11:30:47.0Z')
    .addEvent(objectEvent);

  const res = await capture(epcisDocument);
  const text = await res.text();
  console.log(`Request status: ${res.status}`);
  console.log(`Request response: ${text}`);

  console.log(`EPCISDocument is valid ? ${epcisDocument.isValid()}`);
  console.log(`Event is valid ? ${epcisDocument.eventList[0].isValid()}`);
};

sendACaptureRequestExample();
HTTP/2 202 ACCEPTED

Return events of any type

The following request enables you to get a list of all events sent to the repository (and linked with your account):

curl --location --request GET 'https://api.evrythng.io/v2/epcis/eventTypes/all/events' \
--header 'Authorization: API_KEY'
HTTP/2 200 OK
Content-Type: application/json

{
   "type":"EPCISDocument",
   "@context":"https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld",
   "schemaVersion":"2.0",
   "creationDate":"2022-07-01T14:26:21.317Z",
   "epcisBody":{
      "eventList":[
         {
            "eventID":"ni:///sha-256;df7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69?ver=CBV2.0",
            "type":"ObjectEvent",
            "action":"OBSERVE",
            "bizStep":"shipping",
            "disposition":"in_transit",
            "epcList":[
               "urn:epc:id:sgtin:0614141.107346.2017",
               "urn:epc:id:sgtin:0614141.107346.2018"
            ],
            "eventTime":"2005-04-03T20:33:31.116000-06:00",
            "eventTimeZoneOffset":"-06:00",
            "readPoint":{
               "id":"urn:epc:id:sgln:0614141.07346.1234"
            },
            "bizTransactionList":[
               {
                  "type":"po",
                  "bizTransaction":"http://transaction.acme.com/po/12345678"
               }
            ]
         },
         
         // ... other events
      ]
   }
}

Return all object events

The following request enables you to get a list of all ObjectEvents sent to the repository (and linked with your account). You can replace ObjectEvent with any supported event type.

curl --location --request GET 'https://api.evrythng.io/v2/epcis/eventTypes/ObjectEvent/events' \
--header 'Authorization: API_KEY'
HTTP/2 200 OK
Content-Type:application/json

{
   "type":"EPCISDocument",
   "@context":"https://ref.gs1.org/standards/epcis/2.0.0/epcis-context.jsonld",
   "schemaVersion":"2.0",
   "creationDate":"2022-07-01T14:26:21.317Z",
   "epcisBody":{
      "eventList":[
         {
            "eventID":"ni:///sha-256;df7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69?ver=CBV2.0",
            "type":"ObjectEvent",
            "action":"OBSERVE",
            "bizStep":"shipping",
            "disposition":"in_transit",
            "epcList":[
               "urn:epc:id:sgtin:0614141.107346.2017",
               "urn:epc:id:sgtin:0614141.107346.2018"
            ],
            "eventTime":"2005-04-03T20:33:31.116000-06:00",
            "eventTimeZoneOffset":"-06:00",
            "readPoint":{
               "id":"urn:epc:id:sgln:0614141.07346.1234"
            },
            "bizTransactionList":[
               {
                  "type":"po",
                  "bizTransaction":"http://transaction.acme.com/po/12345678"
               }
            ]
         },
         
         // ... other events
      ]
   }
}

Retrieve a Single Event

Now, let’s retrieve the event we previously captured. The unique event ID is ni:///sha-256;df7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69?ver=CBV2.0. To use it in a URL, we must encode it. You can use a tool like https://www.urlencoder.org/ to do so. The result is ni%3A%2F%2F%2Fsha-256%3Bdf7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69%3Fver%3DCBV2.0

curl --location --request GET 'https://api.evrythng.io/v2/epcis/eventTypes/ObjectEvent/events/ni%3A%2F%2F%2Fsha-256%3Bdf7bb3c352fef055578554f09f5e2aa41782150ced7bd0b8af24dd3ccb30ba69%3Fver%3DCBV2.0' \
--header 'Authorization: API_KEY'

In Summary

In this tutorial, we introduced the EPCIS 2.0 standard for the exchange of messages in a supply chain environment. We described how EPCIS events can be translated into Product Cloud events back and forth. This lets your business create product experiences that can talk to all stakeholders in a supply chain: suppliers, manufacturers, logistics companies, and consumers using the tools you already know.

To learn more about the technical details and capabilities of the Product Cloud EPCIS 2.0 support, see our EPCIS API documentation