Publish Data
Send consignments, events, and documents to TWIN — all through a single inbox endpoint.
Everything is published through one endpoint. You wrap your payload in an activity — a JSON object with a type that tells TWIN what to do with it.
Every request requires Cookie: access_token=<jwt>. See Authentication.
POST /supply-chain/data-space/inbox
POST /supply-chain/data-space/inbox
Content-Type: application/json
Cookie: access_token=<jwt>Every request body is an activity: a JSON wrapper with a type that tells TWIN what to do, and an object that carries the payload. Choose the operation you need:
type | What TWIN does | Details |
|---|---|---|
Create | Publishes a new consignment | Create or update a consignment |
Update | Updates an existing consignment — matched by globalId or identifier | Create or update a consignment |
Add | Attaches an event or document to an existing consignment | Add an event · Add a document |
All activities share the same top-level structure. actor is your organisation and is the same on every request — see Actor. target is only required for Add operations.
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Create | Update | Add",
"actor": { ... },
"object": { ... },
"target": { ... }
}Validation schema
The full activity schema including required fields, actor, object, and target:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/SupplyChainAppActivity",
"title": "SupplyChainAppActivity",
"description": "Supply Chain App Activity.",
"type": "object",
"properties": {
"actor": {
"$ref": "https://schema.twindev.org/supply-chain/SupplyChainAppActor",
"description": "The actor responsible for the activity."
},
"object": {
"$ref": "https://schema.twindev.org/supply-chain/SupplyChainAppObject",
"description": "Activity's object."
},
"target": {
"type": "object",
"properties": {
"@context": {
"const": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld"
},
"type": {
"const": "Consignment"
},
"identifier": {
"type": "string"
},
"globalId": {
"type": "string"
}
},
"required": [
"@context",
"type",
"identifier",
"globalId"
],
"description": "Target information."
}
},
"required": [
"actor",
"object"
],
"allOf": [
{
"description": "A dataspace activity that restricts an activity so that it can be handled by a Dataspace Data Plane",
"type": "object",
"properties": {
"@context": {
"$ref": "https://schema.twindev.org/w3c-activity-streams/ActivityStreamsContextType",
"description": "The LD Context.",
"$comment": "Inherited from ActivityStreamsActivity"
},
"type": {
"anyOf": [
{
"$ref": "https://schema.twindev.org/w3c-activity-streams/ActivityStreamsTypes"
},
{
"type": "string"
},
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "https://schema.twindev.org/w3c-activity-streams/ActivityStreamsTypes"
},
{
"type": "string"
}
]
}
}
],
"description": "Activity Type.",
"$comment": "Inherited from ActivityStreamsActivity"
},
"id": {
"type": "string",
"description": "Global identifier.",
"format": "uri",
"$comment": "Inherited from ActivityStreamsObject"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdLanguageMap"
}
],
"description": "Natural language name.",
"$comment": "Inherited from ActivityStreamsObject"
},
"nameMap": {
"$ref": "https://schema.twindev.org/json-ld/JsonLdLanguageMap",
"description": "Natural language name map.",
"$comment": "Inherited from ActivityStreamsObject"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdLanguageMap"
}
],
"description": "Summary of the Activity.",
"$comment": "Inherited from ActivityStreamsActivity"
},
"summaryMap": {
"$ref": "https://schema.twindev.org/json-ld/JsonLdLanguageMap",
"description": "Natural language summary map.",
"$comment": "Inherited from ActivityStreamsObject"
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdLanguageMap"
}
],
"description": "Natural language content.",
"$comment": "Inherited from ActivityStreamsObject"
},
"contentMap": {
"$ref": "https://schema.twindev.org/json-ld/JsonLdLanguageMap",
"description": "Natural language content map.",
"$comment": "Inherited from ActivityStreamsObject"
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "A link to the representation of the object.\n\nThe value can be a URI or an embedded node object.",
"$comment": "Inherited from ActivityStreamsObject"
},
"image": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "A graphical representation of the object.\n\nThe value can be a URI or an embedded `Image`/`Link` object.",
"$comment": "Inherited from ActivityStreamsObject"
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "An icon for the object.\n\nThe value can be a URI or an embedded `Image`/`Link` object.",
"$comment": "Inherited from ActivityStreamsObject"
},
"published": {
"type": "string",
"description": "Published date-time.",
"format": "date-time",
"$comment": "Inherited from ActivityStreamsObject"
},
"updated": {
"type": "string",
"description": "Updated date-time.",
"format": "date-time",
"$comment": "Inherited from ActivityStreamsObject"
},
"startTime": {
"type": "string",
"description": "Start time.",
"format": "date-time",
"$comment": "Inherited from ActivityStreamsObject"
},
"endTime": {
"type": "string",
"description": "End time.",
"format": "date-time",
"$comment": "Inherited from ActivityStreamsObject"
},
"duration": {
"type": "string",
"description": "Duration.",
"format": "duration",
"$comment": "Inherited from ActivityStreamsObject"
},
"generator": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "The generator of the Activity.",
"$comment": "Inherited from ActivityStreamsActivity"
},
"attachment": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Attachments.",
"$comment": "Inherited from ActivityStreamsObject"
},
"attributedTo": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Objects attributed to.",
"$comment": "Inherited from ActivityStreamsObject"
},
"audience": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Audience.",
"$comment": "Inherited from ActivityStreamsObject"
},
"context": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Context.",
"$comment": "Inherited from ActivityStreamsObject"
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Location.",
"$comment": "Inherited from ActivityStreamsObject"
},
"tag": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Tag.",
"$comment": "Inherited from ActivityStreamsObject"
},
"inReplyTo": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "In reply to.",
"$comment": "Inherited from ActivityStreamsObject"
},
"replies": {
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject",
"description": "Replies collection.\n\nTypically an embedded `Collection` of Objects that are replies to this object.",
"$comment": "Inherited from ActivityStreamsObject"
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Preview.",
"$comment": "Inherited from ActivityStreamsObject"
},
"to": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "To.",
"$comment": "Inherited from ActivityStreamsObject"
},
"bto": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "BTo.",
"$comment": "Inherited from ActivityStreamsObject"
},
"cc": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "CC.",
"$comment": "Inherited from ActivityStreamsObject"
},
"bcc": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "BCC.",
"$comment": "Inherited from ActivityStreamsObject"
},
"mediaType": {
"type": "string",
"description": "MIME media type of the referenced resource.",
"$comment": "Inherited from ActivityStreamsObject"
},
"result": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Result of the Activity.",
"$comment": "Inherited from ActivityStreamsActivity"
},
"origin": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Activity's origin.",
"$comment": "Inherited from ActivityStreamsActivity"
},
"instrument": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdNodeObject"
}
]
}
}
],
"description": "Instrument used in the Activity.",
"$comment": "Inherited from ActivityStreamsActivity"
}
},
"required": [
"@context",
"type"
],
"$comment": "Inlined utility base type DataspaceActivity so utility transformations can operate on concrete properties instead of a $ref."
}
]
}Create or update a consignment
Use type: Create to publish a new consignment. Use type: Update to modify one — TWIN matches it by globalId or identifier and merges the fields you send.
Three fields are always required in object: @context, identifier, and globalId. All UNECE D23B fields are optional and validated when present.
| Field | Type | Required | Description |
|---|---|---|---|
@context | string | Yes | Must be "https://vocabulary.uncefact.org/unece-context-D23B.jsonld" |
identifier | string | Yes | Your internal reference for this consignment |
globalId | string | Yes | A globally unique ID — use a UUID URN: urn:uuid:<uuid> |
Validation schema
Defines what TWIN accepts and validates. Required fields are @context, identifier, and globalId — all other UNECE D23B fields are optional.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/SupplyChainAppConsignment",
"title": "SupplyChainAppConsignment",
"description": "V2 consignment (D23B context).\nAll extended fields are optional for ingestion but validated if present.\nOnly minimal identity fields are required; all other UNECE fields are optional but validated if present.",
"type": "object",
"properties": {
"@context": {
"$ref": "https://schema.twindev.org/unece/UneceContextType",
"description": "JSON-LD Context."
},
"globalId": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdValueObject"
}
],
"description": "A global identifier of this supply chain consignment."
},
"identifier": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdValueObject"
}
],
"description": "A unique identifier for this referenced supply chain consignment."
},
"consignmentItemQuantity": {
"$ref": "https://schema.twindev.org/supply-chain/WrappedQuantity",
"description": "Wrapped quantity structures."
},
"packageQuantity": {
"$ref": "https://schema.twindev.org/supply-chain/WrappedQuantity",
"description": "Wrapped package quantity."
},
"weightUnitNetWeightMeasure": {
"type": "array",
"items": {
"$ref": "https://schema.twindev.org/supply-chain/WrappedWeightMeasure"
},
"description": "Wrapped weight net measurement"
}
},
"required": [
"@context",
"globalId",
"identifier"
],
"allOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceConsignment"
}
]
}For quantity and weight fields, TWIN uses wrapper objects that pair a numeric value with a unit code:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/WrappedQuantity",
"title": "WrappedQuantity",
"description": "Wrapped UNECE quantity structure (D23B).",
"type": "object",
"properties": {
"unece:QuantityTypeValue": {
"type": "string",
"description": "Quantity numeric value."
},
"unece:QuantityTypeCode": {
"$ref": "https://schema.twindev.org/unece/UneceQuantityCode",
"description": "Unit of measure code."
}
},
"required": [
"unece:QuantityTypeValue"
],
"allOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceQuantityType"
}
]
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/WrappedWeightMeasure",
"title": "WrappedWeightMeasure",
"description": "Wrapped UNECE weight measure structure.",
"type": "object",
"properties": {
"unece:WeightUnitMeasureTypeValue": {
"type": "string",
"description": "Weight measure numeric value."
},
"unece:WeightUnitMeasureTypeCode": {
"$ref": "https://schema.twindev.org/unece/UneceWeightUnitMeasureCode",
"description": "Unit of measure code."
}
},
"required": [
"unece:WeightUnitMeasureTypeValue"
],
"allOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceWeightUnitMeasureType"
}
]
}Publishing a new consignment (Example)
Minimum required fields plus consignor, consignee, and origin and destination ports.
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Create",
"actor": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "TradeParty",
"registeredId": {
"@type": "https://ref.gs1.org/voc/OrganizationID_Type-DID",
"@value": "did:web:acme-freight.example.com"
}
},
"object": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Consignment",
"identifier": "ACME-2026-001",
"globalId": "urn:uuid:a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"summaryDescription": "RORO vehicle consignment",
"consignor": {
"type": "TradeParty",
"name": "Acme Exports Ltd"
},
"consignee": {
"type": "TradeParty",
"name": "UK Imports Co"
},
"loadingBaseportLocation": {
"type": "LogisticsLocation",
"name": "Port of Calais",
"UNLocode": "FRCQF"
},
"unloadingBaseportLocation": {
"type": "LogisticsLocation",
"name": "Port of Felixstowe",
"UNLocode": "GBFXT"
}
}
}Updating an existing consignment (Example)
Only send the fields you want to change — TWIN merges them into the existing consignment.
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Update",
"actor": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "TradeParty",
"registeredId": {
"@type": "https://ref.gs1.org/voc/OrganizationID_Type-DID",
"@value": "did:web:acme-freight.example.com"
}
},
"object": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Consignment",
"identifier": "ACME-2026-001",
"globalId": "urn:uuid:a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"mainCarriageTransportMovement": {
"type": "ReferencedTransportMeans",
"identification": "BOOKING-XY9921"
}
}
}Publishing a consignment with multiple items (Example)
A consignment can carry several goods items in includedConsignment — each one is itself a Consignment with its own identifier, and describes its goods via includedConsignmentItem.
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Create",
"actor": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "TradeParty",
"registeredId": {
"@type": "https://ref.gs1.org/voc/OrganizationID_Type-DID",
"@value": "did:web:acme-freight.example.com"
}
},
"object": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Consignment",
"identifier": "ACME-2026-002",
"globalId": "urn:uuid:b2c3d4e5-f6a7-8901-bcde-f12345678901",
"summaryDescription": "Mixed consignment: fresh chicken and electronics",
"includedConsignment": [
{
"type": "Consignment",
"identifier": "ITEM-001",
"consignorParty": {
"type": "TradeParty",
"name": "Traders International",
"postalAddress": {
"type": "TradeAddress",
"tradeAddressCountryId": "unece:CountryId#PL"
}
},
"includedConsignmentItem": [
{
"type": "ConsignmentItem",
"goodsTypeCode": "unece:GoodsTypeCodeList#ZZZ",
"information": "500 live chickens",
"originCountry": {
"type": "Country",
"countryId": "unece:CountryId#PL"
}
}
]
},
{
"type": "Consignment",
"identifier": "ITEM-002",
"consignorParty": {
"type": "TradeParty",
"name": "EuroTech GmbH",
"postalAddress": {
"type": "TradeAddress",
"tradeAddressCountryId": "unece:CountryId#DE"
}
},
"includedConsignmentItem": [
{
"type": "ConsignmentItem",
"goodsTypeCode": "unece:GoodsTypeCodeList#ZZZ",
"information": "40 pallets of consumer electronics",
"originCountry": {
"type": "Country",
"countryId": "unece:CountryId#DE"
}
}
]
}
]
}
}Updating one item in a multi-item consignment (Example)
When an Update includes includedConsignment, TWIN treats it as the complete list of items: matching identifiers are updated, new ones are added, and any item missing from the list is removed. Omit the field to leave items untouched; send an empty array to remove them all.
To change a single item, resend every item you want to keep alongside the one you're updating:
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Update",
"actor": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "TradeParty",
"registeredId": {
"@type": "https://ref.gs1.org/voc/OrganizationID_Type-DID",
"@value": "did:web:acme-freight.example.com"
}
},
"object": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Consignment",
"identifier": "ACME-2026-002",
"globalId": "urn:uuid:b2c3d4e5-f6a7-8901-bcde-f12345678901",
"includedConsignment": [
{
"type": "Consignment",
"identifier": "ITEM-001",
"includedConsignmentItem": [
{
"type": "ConsignmentItem",
"information": "500 live chickens"
}
]
},
{
"type": "Consignment",
"identifier": "ITEM-002",
"includedConsignmentItem": [
{
"type": "ConsignmentItem",
"information": "60 pallets of consumer electronics"
}
]
}
]
}
}Only ITEM-002 changed (40 → 60 pallets); ITEM-001 is resent unchanged so it isn't dropped.
ITEM-002 here would remove ITEM-001 from the consignment.Add an event
Use type: Add with a SupplyChainEvent in object to record a status update. You must also include a target that identifies which consignment the event belongs to.
Validation schema
| Field | Type | Required | Description |
|---|---|---|---|
@context | string | Yes | Must be "https://vocabulary.uncefact.org/unece-context-D23B.jsonld" |
typeCode | string | Yes | One of the twin:* event type codes — see Event types |
All other UNECE SupplyChainEvent fields are optional.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/SupplyChainAppEvent",
"title": "SupplyChainAppEvent",
"description": "Supply Chain App Event.",
"type": "object",
"properties": {
"@context": {
"$ref": "https://schema.twindev.org/unece/UneceContextType",
"description": "JSON-LD Context."
},
"typeCode": {
"anyOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceSupplyChainEventTypeCodeList"
},
{
"type": "string"
}
],
"description": "A code specifying the type of supply chain event."
}
},
"required": [
"@context",
"typeCode"
],
"allOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceSupplyChainEvent"
}
]
}Event types
typeCode | When to use |
|---|---|
twin:preNotification | Goods have been pre-notified ahead of departure |
twin:despatched | Goods have been despatched |
twin:issuedDocument | A document has been issued |
twin:onwardSharing | Data has been shared onward with another party |
twin:carrierBooking | A carrier booking has been confirmed |
twin:locationOperatorMatch | A location operator has matched the consignment |
twin:atLocationOfExit | Goods have arrived at the exit location |
twin:leftLocationOfExit | Goods have left the exit location |
twin:atLocationOfEntry | Goods have arrived at the entry location |
twin:leftLocationOfEntry | Goods have left the entry location |
twin:arrivedAtFinalDestination | Goods have been delivered |
twin:locationOperatorMatch is the one event that is not sent by freight forwarders: location
operators send it to confirm a consignment routed through their facility. See the Location
Operator tutorial.
Target
Identifies the consignment to attach the event to. Required for all Add activities.
| Field | Type | Required | Value |
|---|---|---|---|
@context | string | Yes | "https://vocabulary.uncefact.org/unece-context-D23B.jsonld" |
type | string | Yes | "Consignment" |
globalId | string | Yes | The consignment's globalId |
identifier | string | Yes | The consignment's identifier |
Notifying goods arrived at the exit location (Example)
An event with timestamp and location, attached to an existing consignment.
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Add",
"actor": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "TradeParty",
"registeredId": {
"@type": "https://ref.gs1.org/voc/OrganizationID_Type-DID",
"@value": "did:web:acme-freight.example.com"
}
},
"object": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "SupplyChainEvent",
"typeCode": "twin:atLocationOfExit",
"occurrenceDateTime": "2026-06-02T09:00:00.000Z",
"occurrenceLocation": {
"type": "LogisticsLocation",
"name": "Port of Calais",
"UNLocode": "FRCQF"
}
},
"target": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Consignment",
"identifier": "ACME-2026-001",
"globalId": "urn:uuid:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Add a document
Use type: Add with a Document in object to attach a file to a consignment. You must also include a target — same shape as for events, see Target above.
Validation schema
| Field | Type | Required | Description |
|---|---|---|---|
@context | string | Yes | Must be "https://vocabulary.uncefact.org/unece-context-D23B.jsonld" |
type | string | Yes | Always "Document" |
documentTypeCode | string | Yes | UNECE document type code |
identifier | string | Yes | Your reference for this document |
issueDateTime | string | Yes | ISO 8601 datetime |
uRIId | string | Yes | URL pointing to the file |
versionId | string | Yes | Version identifier |
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/SupplyChainAppDocument",
"title": "SupplyChainAppDocument",
"description": "Supply Chain App Document.",
"type": "object",
"properties": {
"@context": {
"$ref": "https://schema.twindev.org/unece/UneceContextType",
"description": "JSON-LD Context."
},
"type": {
"const": "Document",
"description": "JSON-LD Type."
},
"documentTypeCode": {
"$ref": "https://schema.twindev.org/unece/UneceDocumentCodeList",
"description": "The code specifying the type of referenced document."
},
"identifier": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdValueObject"
}
],
"description": "A unique identifier for this referenced document."
},
"issueDateTime": {
"type": "string",
"description": "The formatted date or date time for the issuance of this referenced document.",
"format": "date-time"
},
"uRIId": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdValueObject"
}
],
"description": "The unique Uniform Resource Identifier (URI) for this referenced document."
},
"versionId": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "https://schema.twindev.org/json-ld/JsonLdValueObject"
}
],
"description": "The identifier for the version of this referenced document."
}
},
"required": [
"@context",
"type",
"documentTypeCode",
"identifier",
"issueDateTime",
"uRIId",
"versionId"
],
"allOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceDocument"
}
]
}Attaching a document to a consignment (Example)
A document with type code, version, issue date, and a URL pointing to the file.
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Add",
"actor": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "TradeParty",
"registeredId": {
"@type": "https://ref.gs1.org/voc/OrganizationID_Type-DID",
"@value": "did:web:acme-freight.example.com"
}
},
"object": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Document",
"documentTypeCode": "unece:DocumentCodeList#271",
"identifier": "CUSTOMS-DOC-001",
"versionId": "v1",
"issueDateTime": "2026-06-01T14:00:00.000Z",
"uRIId": "https://docs.acme-freight.example.com/CUSTOMS-DOC-001.pdf"
},
"target": {
"@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"type": "Consignment",
"identifier": "ACME-2026-001",
"globalId": "urn:uuid:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Actor
Your organisation as a UNECE TradeParty. Use the same value on every request.
| Field | Type | Required | Description |
|---|---|---|---|
@context | string | Yes | Always "https://vocabulary.uncefact.org/unece-context-D23B.jsonld" |
type | string | Yes | Always "TradeParty" |
registeredId | object | Yes | Your organisation's DID — { "@type": "...", "@value": "did:web:your-org.example.com" } |
Validation schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.twindev.org/supply-chain/SupplyChainAppActor",
"title": "SupplyChainAppActor",
"description": "Supply Chain App Actor.",
"type": "object",
"properties": {
"type": {
"const": "TradeParty",
"description": "Actor information."
},
"registeredId": {
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"@value": {
"type": "string"
}
},
"required": [
"@type",
"@value"
],
"description": "Registered identifier for the actor."
},
"@context": {
"const": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
"description": "Context for the actor."
}
},
"required": [
"type",
"registeredId",
"@context"
],
"allOf": [
{
"$ref": "https://schema.twindev.org/unece/UneceTradeParty"
}
]
}Response
201 Created — activity accepted and processed.
{
"id": "aig:019e...",
"status": "completed",
"generator": "supply-chain-node",
"dateCreated": "2026-06-30T14:00:00.000Z",
"tasks": [
{
"taskId": "...",
"dataspaceAppId": "supply-chain",
"result": 0,
"startDate": "2026-06-30T14:00:00.000Z",
"endDate": "2026-06-30T14:00:00.001Z",
"status": "completed"
}
]
}Errors
| Status | Cause |
|---|---|
400 | Malformed activity or missing required field |
401 | Missing or invalid credentials |
422 | Payload failed schema validation |