TWIN Supply Chain Docs
Tutorials

Freight Forwarder

Authenticate, publish Goods Loads, add events and documents, and read your data back.

Freight Forwarders publish Goods Load data to TWIN via the Dataspace Connector. Once published, TWIN automatically routes notifications to the relevant parties — border agencies, location operators — based on the Goods Load's route.

Throughout this guide, Goods Load means the same thing as consignment — TWIN's schema and API say "consignment", while freight forwarders say "Goods Load" day to day.

TWIN sends two ISN signals to registered Border Agencies automatically: a Pre-Notification signal when you Create or Update a Goods Load, and a Despatch signal when you add a twin:despatched event (see Add an event below).

Authenticate

Exchange your email and password for a session cookie.

Request
POST /authentication/login
Content-Type: application/json
Body
{
  "email": "you@example.com",
  "password": "your-password"
}

The JWT arrives via Set-Cookie. Include it on every subsequent request.

See Authentication for full details.

Publish a Goods Load

Send a Create activity to the inbox. The object field contains the Goods Load payload.

POST /supply-chain/data-space/inbox
Content-Type: application/json
Cookie: access_token=<jwt>
{
  "@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:your-org.example.com"
    }
  },
  "object": {
    "@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
    "type": "Consignment",
    "identifier": "MYREF-001",
    "globalId": "urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}

This example shows the minimum required fields — a real Goods Load payload will include many more. See Publish Data for all available options.

Returns 200 OK with an activity-log entry — check status and tasks[].error in the body, since a processing failure is reported there and not in the HTTP status.

Update a Goods Load

Send an Update activity to modify an existing Goods Load. Resend the whole payload, not just the fields you changed — TWIN replaces the Goods Load with the data you send, so anything you omit is removed.

POST /supply-chain/data-space/inbox
Content-Type: application/json
Cookie: access_token=<jwt>
{
  "@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:your-org.example.com"
    }
  },
  "object": {
    "@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
    "type": "Consignment",
    "identifier": "MYREF-001",
    "globalId": "urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "summaryDescription": "Updated description"
  }
}

This payload is short because the Goods Load published above only carried the minimum fields. If yours has more, repeat every one of them here or they will be removed — including carrierParty and carrierAssignedId if a Carrier Booking event has set them. Attached documents and recorded events themselves stay attached.

TWIN matches the Goods Load by globalId or identifier. Returns 200 OK.

Add an event

Send an Add activity with a SupplyChainEvent to record a status update. Reference the Goods Load in target using both globalId and identifier.

POST /supply-chain/data-space/inbox
Content-Type: application/json
Cookie: access_token=<jwt>
{
  "@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:your-org.example.com"
    }
  },
  "object": {
    "@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
    "type": "SupplyChainEvent",
    "typeCode": "twin:despatched",
    "occurrenceDateTime": "2026-06-02T09:00:00.000Z"
  },
  "target": {
    "@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
    "type": "Consignment",
    "identifier": "MYREF-001",
    "globalId": "urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}

See Event types for all available typeCode values.

Add a document

Send an Add activity with a Document to attach a file to the Goods Load.

POST /supply-chain/data-space/inbox
Content-Type: application/json
Cookie: access_token=<jwt>
{
  "@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:your-org.example.com"
    }
  },
  "object": {
    "@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
    "type": "Document",
    "documentTypeCode": "unece:DocumentCodeList#271",
    "identifier": "DOC-001",
    "versionId": "v1",
    "issueDateTime": "2026-06-01T14:00:00.000Z",
    "uRIId": "https://docs.your-org.example.com/DOC-001.pdf"
  },
  "target": {
    "@context": "https://vocabulary.uncefact.org/unece-context-D23B.jsonld",
    "type": "Consignment",
    "identifier": "MYREF-001",
    "globalId": "urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}

See Add a document for all required fields.

Read your Goods Loads

List all Goods Loads visible to your organisation:

GET /supply-chain/data-space/consignments
Cookie: access_token=<jwt>

Returns a paginated list. Use cursor and limit to page through results. To retrieve a specific Goods Load with its events and documents:

GET /supply-chain/data-space/consignments/<globalId>
Cookie: access_token=<jwt>

See Read Consignments for all available endpoints and response shapes.

On this page