TWIN Supply Chain Docs
API Reference

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:

typeWhat TWIN doesDetails
CreatePublishes a new consignmentCreate or update a consignment
UpdateUpdates an existing consignment — matched by globalId or identifierCreate or update a consignment
AddAttaches an event or document to an existing consignmentAdd 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.

FieldTypeRequiredDescription
@contextstringYesMust be "https://vocabulary.uncefact.org/unece-context-D23B.jsonld"
identifierstringYesYour internal reference for this consignment
globalIdstringYesA 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.

Sending only 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

FieldTypeRequiredDescription
@contextstringYesMust be "https://vocabulary.uncefact.org/unece-context-D23B.jsonld"
typeCodestringYesOne 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

typeCodeWhen to use
twin:preNotificationGoods have been pre-notified ahead of departure
twin:despatchedGoods have been despatched
twin:issuedDocumentA document has been issued
twin:onwardSharingData has been shared onward with another party
twin:carrierBookingA carrier booking has been confirmed
twin:locationOperatorMatchA location operator has matched the consignment
twin:atLocationOfExitGoods have arrived at the exit location
twin:leftLocationOfExitGoods have left the exit location
twin:atLocationOfEntryGoods have arrived at the entry location
twin:leftLocationOfEntryGoods have left the entry location
twin:arrivedAtFinalDestinationGoods 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.

FieldTypeRequiredValue
@contextstringYes"https://vocabulary.uncefact.org/unece-context-D23B.jsonld"
typestringYes"Consignment"
globalIdstringYesThe consignment's globalId
identifierstringYesThe 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

FieldTypeRequiredDescription
@contextstringYesMust be "https://vocabulary.uncefact.org/unece-context-D23B.jsonld"
typestringYesAlways "Document"
documentTypeCodestringYesUNECE document type code
identifierstringYesYour reference for this document
issueDateTimestringYesISO 8601 datetime
uRIIdstringYesURL pointing to the file
versionIdstringYesVersion 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.

FieldTypeRequiredDescription
@contextstringYesAlways "https://vocabulary.uncefact.org/unece-context-D23B.jsonld"
typestringYesAlways "TradeParty"
registeredIdobjectYesYour 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

StatusCause
400Malformed activity or missing required field
401Missing or invalid credentials
422Payload failed schema validation

On this page