OTEP Download Home

OTEP — Open Tracking Event Protocol

Übersetzung zur besseren Verständlichkeit — maßgeblich ist die englische Fassung.

Status: Entwurf v0.1 · Eine offene, herstellerneutrale Spezifikation · Lizenz: offen (siehe §10)

OTEP ist ein offenes, herstellerneutrales Protokoll für den Lebenszyklus jedes verfolgbaren Objekts. Es definiert ein Ereignismodell und ein Statusvokabular, sodass Tracking-Ereignisse aus jeder Quelle — eigene Flottenzustellung, Drittanbieter-Kuriere, Frachtführer-Labels und darüber hinaus — ausgetauscht, verstanden und auf internationale Standards projiziert werden können, ohne für jede Partei neu integrieren zu müssen.

Dieses Dokument ist die Spezifikation: die Struktur, die Felder, die Statustabellen, der Zustands- automat, die Zuordnungen zu externen Standards und die Konformitätsregeln für den Aufbau einer konformen Implementierung. Es ist implementierungsunabhängig — es beschreibt das Protokoll, nicht die internen Abläufe eines bestimmten Herstellers. RFC-2119-Schlüsselwörter (MUST / SHOULD / MAY) sind normativ.

1. Was OTEP löst

Tracking ist fragmentiert: jeder Frachtführer benennt Felder und Statuscodes anders, jeder Zustellkanal meldet in seiner eigenen Form, und die Anbindung an globale Standards bedeutet immer wieder eine erneute Integration. OTEP gibt Produzenten und Konsumenten eine einzige gemeinsame Sprache: ein Produzent gibt OTEP-Ereignisse einmal aus, und jeder OTEP-Konsument versteht sie und kann sie auf den von ihm benötigten Standard projizieren.

2. Designprinzipien

  1. Ereignisbasiert (event-sourced). Die Ereignis-Zeitleiste ist die Quelle der Wahrheit; der „aktuelle Status“ ist immer eine Projektion — der Status des jüngsten Ereignisses.
  2. Was / Wann / Wo / Warum. Jedes Ereignis ist um diese vier Dimensionen herum aufgebaut — dieselben Dimensionen, die GS1 EPCIS, IATA ONE Record und UN/CEFACT gemeinsam haben — sodass diese Standards Ausgabeprojektionen eines OTEP-Ereignisses sind und keine parallelen Modelle.
  3. Quellen ohne Liste sind kein Hindernis. Eine Quelle, die nur einen aktuellen Status (keine Historie) bereitstellt, wird durch Synthese eines Ereignisses pro beobachteter Änderung behandelt (§5).
  4. Additiv. OTEP wird neben jeder bestehenden Tracking-API bereitgestellt; seine Einführung erfordert nie eine bahnbrechende Änderung an dem, was Konsumenten bereits verwenden.

3. Die OTEP-Zeitleiste

Eine Zeitleiste ist ein Umschlag, der das verfolgte Objekt und eine geordnete Liste von Ereignissen trägt.

{
  "otep_version": "0.1",
  "profile": "parcel",                  // domain profile (§8)
  "subject": {
    "tracking_number": "SR123...",      // ≥1 identifier required
    "order_id": 12345,                  // optional
    "package_id": 67890,                // optional
    "external_tracking_number": "1Z...",// optional
    "gs1_sscc": "00...",                // optional — enables EPCIS epcList
    "piece_id": "..."                   // optional — enables ONE Record linkage
  },
  "current_status": "delivered",        // projection of the latest event
  "delivered": true,
  "events": [ /* OTEP events, §4 */ ]
}

Das OTEP-Ereignis

{
  // WHAT — carried once at the timeline level (subject above)

  // WHEN
  "occurred_at": "2026-06-10T09:30:00-04:00",  // event instant, ISO-8601 with offset
  "recorded_at": "2026-06-10T09:45:23-04:00",  // ingestion instant (optional)
  "time_type": "actual",                        // actual | estimated | scheduled

  // WHERE
  "location": {
    "name": "Toronto Hub",
    "code": "YYZ-2",
    "gln": "0614141000005",                     // GS1 GLN → EPCIS SGLN
    "lat": 43.6777, "lng": -79.6248,
    "country": "CA"                             // ISO 3166-1 alpha-2
  },

  // WHY / WHAT HAPPENED
  "status_code": "out_for_delivery",            // an OTEP status code (§4)
  "phase": "out_for_delivery",                  // derived from status_code
  "incident_reason": null,                       // an OTEP incident reason (§4) when exception

  // WHO
  "actor": { "type": "driver", "name": "Jane D.", "phone": "+1..." },

  // PROVENANCE
  "source": {
    "type": "self_delivery",                    // self_delivery | third_party_delivery | carrier_label
    "provider_id": null,
    "carrier_code": null,
    "external_event_code": null,                 // your raw status code (preserve it)
    "raw": { /* original payload */ }
  },

  // PROOF
  "pod": {
    "photos": [ { "url": "...", "content_base64": null } ],
    "signature": [ { "url": "...", "content_base64": null } ],
    "recipient": "John Smith"
  }
}

Jedes Feld außer subject, occurred_at, status_code und source ist optional — partielle Quellen füllen aus, was sie haben. Node-/Hub-Scans setzen location auf die scannende Einrichtung. Hochfrequente GPS-Telemetrie ist KEIN OTEP-Ereignis; ein Ereignis wird bei einer Statusänderung oder einem Node-Scan ausgegeben.

4. Vokabular

4.1 Statuscodes

20 kanonische Lebenszyklus-Codes. phase ist immer aus dem Code ableitbar.

code phase terminal POD Bedeutung
information_submitted pre_shipment Bestellinformationen empfangen
booking_confirmed pre_shipment Frachtführer/Buchung bestätigt
awaiting_pickup pre_shipment abholbereit
out_for_pickup pickup unterwegs zur Abholung
picked_up pickup beim Versender abgeholt
pickup_failed exception Abholversuch fehlgeschlagen
pickup_rescheduled exception Abholung wird erneut versucht
received inbound in der Einrichtung empfangen
arrival_scan inbound Ankunftsscan am Node
in_transit transit in Bewegung
package_outbound transit Einrichtung verlassen
removed_from_route exception von der Route genommen
route_cancelled exception Route storniert
out_for_delivery out_for_delivery auf dem Fahrzeug
delivered delivered an Empfänger zugestellt
delivery_failed exception Zustellversuch fehlgeschlagen
delivery_rescheduled exception wird erneut versucht / erneut zugestellt
return_to_sender return Rücksendung an Ursprung
rejected_by_recipient return Empfänger verweigert
cancelled return Bestellung storniert

4.2 Phasen

pre_shipment · preparing · pickup · inbound · in_custody · transit · out_for_delivery · delivered · exception · return. (preparing und in_custody sind für Nicht-Paket-Profile reserviert — §8.)

4.3 Quelltypen & Zeittypen

source.type: self_delivery · third_party_delivery · carrier_label. time_type: actual · estimated · scheduled (Standard actual).

4.4 Vorfallgründe (incident reasons)

Wenn sich ein Ereignis in der Phase exception befindet, SHOULD es einen incident_reason aus diesem normalisierten Vokabular tragen:

5. Zustandsautomat & Quellen nur mit Status

Phasen schreiten vorwärts; Ausnahmen unterbrechen und lösen sich wieder auf. Terminalzustände (delivered, return_to_sender, rejected_by_recipient, cancelled) schließen das Objekt ab.

pre_shipment → preparing → pickup → inbound → in_custody → transit → out_for_delivery → delivered ✓
                                       └──────────── exception ──────────┘
                                       └──────────── return / cancelled ✓

Regeln:

6. Zuordnungen zu externen Standards

Die vier Dimensionen von OTEP entsprechen Feld für Feld den wichtigsten Standards, sodass jeder eine Ausgabeprojektion eines OTEP-Ereignisses ist.

OTEP GS1 EPCIS 2.0 IATA ONE Record UN/CEFACT
occurred_at (+offset) eventTime + eventTimeZoneOffset eventDate + eventTimeType=Actual Event Date/Time
recorded_at recordTime recordedAt
subject (sscc/piece) epcList (SSCC URN) linkedObject → Piece/Shipment Consignment
location (gln/lat/lng) readPoint / bizLocation (SGLN) recordedAtLocation → Location Location
status_code bizStep + disposition eventCode Transport status code
actor sourceList / extension Actor / Party Party
incident_reason disposition / ErrorDeclaration event remark Status reason code

Werte pro Code (EPCIS CBV bizStep/disposition, ONE Record eventCode, UN/CEFACT-Code) werden im maschinenlesbaren Codebook veröffentlicht. Über diese internationalen Standards hinaus kann eine OTEP- Zeitleiste auch auf OpenTelemetry-Traces, OGC SensorThings-Beobachtungen und gängige Handelsplattformen (AfterShip, Shopify, Amazon, Walmart, BigCommerce, Magento, WooCommerce, Etsy) projiziert werden.

Vertrauensgrad: EPCIS CBV-Werte sind stabile Standard-URNs. ONE Record- und UN/CEFACT-Codewerte sind eine bestmögliche Annäherung für die letzte Meile und sollten vor der externen Verwendung gegen die offiziellen Codelisten validiert werden. „Delivered to consignee“ hat keinen exakten CBV-bizStep — die nächstliegende Annäherung (receiving + received) wird verwendet, oder eine Erweiterungs-URN aus dem Benutzervokabular.

7. Die OTEP-API

OTEP wird über eine kleine, nur lesende HTTP-Schnittstelle konsumiert; alle Endpunkte sind öffentlich.

Verb Path Liefert
GET /api/v1/otep/trackings/{tracking_number} die Zeitleiste für eine Sendungsnummer
GET /api/v1/otep/trackings/{tracking_number}/events nur Ereignisse
POST /api/v1/otep/trackings/batch viele Sendungsnummern in einem Aufruf
POST /api/v1/otep/validate Konformitätsprüfung für eine übermittelte Zeitleiste (§9)

Eine GraphQL-Abfrage, die dieselbe Zeitleiste bereitstellt, ist ebenfalls verfügbar.

Inhaltsaushandlung (content negotiation)

Dieselbe Zeitleiste wird in die von Ihnen angeforderte Darstellung serialisiert, über einen ?format=- Query-Parameter oder ein Accept-Profil:

Anfrage Darstellung
?format=otep (default) native OTEP-Zeitleiste
?format=epcis GS1 EPCIS 2.0 (JSON-LD ObjectEvents)
?format=onerecord IATA ONE Record (LogisticsEvents)
?format=uncefact UN/CEFACT transport status
?format=otlp OpenTelemetry-Traces
?format=sensorthings OGC SensorThings-Beobachtungen
?format=aftership | shopify | amazon | walmart | bigcommerce | magento | woocommerce | etsy die Tracking-/Fulfillment-Form der Plattform

Ereignisse, denen in einer Projektion kein Code zugewiesen werden kann, werden übersprungen und gezählt (niemals stillschweigend verworfen).

8. Domänenprofile

OTEP ist ein allgemeines Protokoll, kein Paketprotokoll. Die Protokollebene (Ereignisumschlag, Phasen- Rückgrat, Zustandsautomat) ist universell; konkrete Statuscodes gehören zu einem Profil, das auf der Zeitleiste über profile deklariert wird. Die Codes in §4 sind das parcel-Profil. Andere Domänen — Umzug, Essenslieferung, Lagerung und darüber hinaus — fügen unter ihrem Profil eigene Codesätze hinzu, mit dem Namensraum otep:<profile>:<code>, die jeweils auf dasselbe Phasen-Rückgrat abbilden. Das Hinzufügen eines Profils ist eine Erweiterung, keine Protokolländerung.

9. Konformitätsspezifikation (normativ)

Ein Produzent oder Konsument ist OTEP-konform, wenn jedes von ihm ausgegebene oder akzeptierte Ereignis diese Tabellen und Regeln erfüllt.

9.1 Zeitleisten-Umschlag

Feld Typ Erf. Einschränkungen
otep_version string MUST semver, z. B. 0.1
profile string MUST ein registriertes Profil
subject object MUST §9.2
current_status string|null SHOULD ein Statuscode (§4)
current_phase string|null SHOULD MUST gleich der Phase von current_status sein, wenn beide vorhanden
delivered boolean SHOULD true genau dann, wenn current_status = delivered
events array MUST Ereignisobjekte (§9.3), nach occurred_at sortierbar

9.2 subject

Mindestens EINES von tracking_number / order_id / package_id MUST vorhanden sein.

Feld Typ Einschränkungen
tracking_number string nicht leer
order_id / package_id integer|null
external_tracking_number string|null
gs1_sscc string|null 18 Ziffern
piece_id string|null

9.3 Ereignisobjekt

# Feld Typ Erf. Einschränkungen
1 occurred_at string MUST ISO-8601 mit Offset
2 recorded_at string|null SHOULD ISO-8601
3 time_type string MAY (default actual) actual | estimated | scheduled
4 status_code string|null MUST¹ ein Code in §4.1
5 phase string|null SHOULD MUST gleich der Phase von status_code sein
6 incident_reason string|null SHOULD² ein Grund in §4.4
7 description string|null MAY menschenlesbar
8 location object|null MAY §9.4
9 actor object|null MAY { type, name?, phone? }; type ∈ {driver, operator, carrier, system}
10 source object MUST §9.5
11 pod object|null MAY³ { photos[], signature[], recipient? }

¹ Ein codiertes Ereignis MUST einen Statuscode aus §4.1 tragen. Ein Rohscan, den Sie noch nicht klassifizieren können, MAY status_code = null setzen, MUST aber den nativen Code in source.external_event_code bewahren und MUST gezählt werden, niemals verworfen. ² Ein Ereignis der Phase exception SHOULD einen incident_reason tragen. ³ Ereignisse mit status_code ∈ {delivered, picked_up} SHOULD ein pod tragen.

9.4 location

name (string) · code (string) · gln (GS1 GLN, 13 Ziffern) · lat / lng (WGS-84) · country (ISO 3166-1 alpha-2). Alle optional.

9.5 source

Feld Typ Erf. Einschränkungen
type string MUST self_delivery | third_party_delivery | carrier_label
provider_id integer|null MAY
carrier_code string|null MAY
external_event_code string|null SHOULD⁴ Ihr Roh-Statuscode
raw object|null MAY ursprüngliche Nutzlast

⁴ MUST vorhanden sein, wenn status_code null ist, damit der native Code niemals verloren geht.

9.6 Regeln

  1. Zeit. occurred_at MUST als ISO-8601 parsbar sein. Normalisieren Sie numerische Epochs und .NET /Date(ms)/ bei der Aufnahme; geben Sie diese Formen nicht aus.
  2. Ordnung / Dedup. Konsumenten MUST nach occurred_at sortieren, ein Eintreffen in falscher Reihenfolge tolerieren und auf (subject, status_code, occurred_at) deduplizieren.
  3. Zustandsautomat. Nach einem Terminalstatus keine weiteren Ereignisse ausgeben, außer einem dokumentierten RMA / Wiedereröffnung.
  4. Kein stiller Verlust. Ereignisse, die nicht codiert werden können, MUST gezählt, niemals verworfen werden.
  5. Ableitung. phase, current_status, current_phase, delivered sind Projektionen — wenn vorhanden, MUST sie mit der Ereignis-Zeitleiste konsistent sein.

9.7 Konformitätsstufen & Validierung

Überprüfen Sie Ihre Ausgabe, indem Sie eine Zeitleiste an POST /api/v1/otep/validate senden. Behandeln Sie alle errors als blockierend; beheben Sie warnings. Ein maschinenlesbares JSON Schema und das vollständige Codebook (jeder Statuscode, jede Phase und jede externe Zuordnung) werden für die Offline-Validierung veröffentlicht.

10. Offenheit & Governance

OTEP ist eine offene Spezifikation, frei für jede Partei zur Implementierung.

11. Hersteller-Interoperabilität — bringen Sie Ihren eigenen Standard mit

OTEP heißt andere Hersteller willkommen, ihren eigenen Tracking-Ereignis-Standard mitzubringen, damit OTEP damit interoperieren kann, in beide Richtungen:

Selbst wenn Sie OTEP nicht direkt übernehmen können, sind Sie willkommen, einen einzigen normalisierten otep_status zu Ihren eigenen API-Antworten hinzuzufügen und Ihre Tracking-Ereignis-Codes für die Querverbindungs-Zuordnung zu teilen. Schlagen Sie Zuordnungen gegen diese Spezifikation vor (statt zu forken), damit Implementierer konvergieren; neue Formate fügen sich in dieselbe ?format=-Inhaltsaushandlung ein und brechen niemals einen bestehenden Konsumenten.