PharmaAutopilot
...

API Referenz

Basis-URL: https://api.msv3gateway.example.com

Alle Anfragen und Antworten verwenden Content-Type: application/json, sofern nicht anders angegeben.


Authentifizierung

Jeder geschuetzte Endpunkt erfordert zwei Authentifizierungsebenen als HTTP-Header.

HeaderErforderlich beiBeschreibung
X-API-KeyAlle Endpunkte ausser GET /v1/healthIhr Gateway-API-Schluessel. Identifiziert Ihr Konto und setzt Rate-Limits durch.
X-MSV3-UsernameGrosshaendler-EndpunkteMSV3-Benutzername vom Grosshaendler.
X-MSV3-PasswordGrosshaendler-EndpunkteMSV3-Passwort vom Grosshaendler.

Zugangsdaten werden nur fuer die Dauer des SOAP-Aufrufs im Speicher gehalten und danach geloescht. Sie werden niemals persistiert.

Sandbox-Modus

API-Schluessel mit dem Praefix pk_test_ leiten Anfragen an die Sandbox-Umgebung weiter. Anfragen an noweda_test erreichen den echten NOWEDA-Testserver. Alle anderen Grosshaendler werden auf einen integrierten Mock geleitet.

Idempotency Keys

Alle aendernden Endpunkte akzeptieren einen optionalen Idempotency-Key-Header.

Idempotency-Key: my-order-2026-04-27-001

Das Gateway speichert den Schluessel-Hash und die zugehoerige Antwort fuer 24 Stunden. Wiederholte Anfragen mit dem gleichen Schluessel liefern die gespeicherte Antwort zurueck, ohne den SOAP-Aufruf erneut auszufuehren.


Fehlerformat

Alle 4xx- und 5xx-Antworten verwenden diese Struktur:

{
  "error": "invalid_request",
  "message": "PZN must be 1-8 digits, got: 'abc123'",
  "wholesaler": "noweda",
  "error_code": "3002"
}

Vollstaendige Fehler-Referenz: Fehlercodes und Loesungen


Rate Limiting

Anfragen werden pro API-Schluessel limitiert. Bei Ueberschreitung antwortet das Gateway mit 429 und einem Retry-After-Header.

HTTP/1.1 429 Too Many Requests
Retry-After: 30

Endpunkte

GET /v1/health

Liveness-Probe. Keine Authentifizierung erforderlich.

// Antwort 200
{
  "status": "ok",
  "version": "1.0.0"
}

GET /v1/wholesalers

Gibt alle registrierten Grosshaendler zurueck. Erfordert: X-API-Key

// Antwort 200
{
  "wholesalers": [
    {
      "id": "noweda",
      "name": "NOWEDA eG",
      "verified": true,
      "capabilities": ["order", "availability", "contracts"]
    }
  ]
}

POST /v1/wholesalers/custom

Registriert einen eigenen MSV3-Grosshaendler-Endpunkt. Erfordert: X-API-Key

// Anfrage
{
  "name": "My Wholesaler GmbH",
  "endpoint": "https://msv3.my-wholesaler.de/msv3"
}

// Antwort 200
{
  "wholesaler": {
    "id": "my-wholesaler-gmbh",
    "name": "My Wholesaler GmbH",
    "endpoint": "https://msv3.my-wholesaler.de/msv3",
    "verified": false,
    "capabilities": []
  }
}

POST /v1/connection/test

Prueft MSV3-Zugangsdaten gegen einen Grosshaendler. Gibt Round-Trip-Latenz zurueck.

Erfordert: X-API-Key, X-MSV3-Username, X-MSV3-Password

// Anfrage
{ "wholesaler": "noweda" }

// Antwort 200
{
  "connected": true,
  "wholesaler": "noweda",
  "latency_ms": 142
}

Fehler: 400, 401, 404, 502


POST /v1/availability

Echtzeit-Verfuegbarkeit fuer bis zu 50 Artikel abfragen, inklusive Lieferanteile, geschaetzter Lieferzeiten und Substitutionen.

Erfordert: X-API-Key, X-MSV3-Username, X-MSV3-Password

FeldTypPflichtBeschreibung
wholesalerstringJaGrosshaendler-ID
itemsarrayJa1-50 Artikel
items[].pznstringJaPZN, 1-8 Ziffern
items[].quantityintegerJaAngefragte Menge
items[].demand_typeenumNeindirect (Standard), one_of_many, unspecified
// Antwort 200
{
  "wholesaler": "noweda",
  "response_type": "standard",
  "items": [
    {
      "pzn": "761271",
      "quantity_requested": 5,
      "available": true,
      "deliveries": [
        {
          "type": "normal",
          "quantity": 5,
          "tour": "00345H",
          "estimated_at": "2026-04-28T10:00:00"
        }
      ],
      "substitution": null
    }
  ]
}

Fehler: 400, 401, 404, 502

POST /v1/availability/bulk

Schlanke Pruefung, welche PZNs aus einer Liste aktuell auf Lager sind. Keine Mengen oder Bedarfsarten noetig. Nuetzlich zum Vorfiltern grosser Kataloge.

// Anfrage
{
  "wholesaler": "noweda",
  "pzns": ["761271", "4211896", "10203595"]
}

// Antwort 200
{
  "wholesaler": "noweda",
  "available_pzns": ["761271", "4211896"]
}

GET /v1/contracts?wholesaler=noweda

Vertragsdaten zwischen Ihrer Apotheke und dem Grosshaendler abrufen - Faehigkeiten, unterstuetzte Bestelltypen und alle woechentlichen Bestellfenster.

// Antwort 200
{
  "wholesaler": "noweda",
  "customer_id": "Now00079800",
  "capabilities": {
    "bulk_availability": true,
    "return_offers": true,
    "substitution": false,
    "order_types": {
      "normal": true,
      "batch": true,
      "special": false,
      "shipping": false
    }
  },
  "delivery_windows": [
    { "day": "monday", "closes_at": "10:29" },
    { "day": "monday", "closes_at": "14:30" }
  ]
}

POST /v1/orders

Arzneimittelbestellung an den Grosshaendler ueber MSV3 uebermitteln. Mit ?dry_run=true validieren, ohne die Bestellung aufzugeben.

Erfordert: X-API-Key, X-MSV3-Username, X-MSV3-Password

FeldTypPflichtBeschreibung
wholesalerstringJaGrosshaendler-ID
itemsarrayJaMindestens 1 Artikel
items[].pznstringJaPZN, 1-8 Ziffern
items[].quantityintegerJaBestellmenge
items[].delivery_preferenceenumNeinnormal, backorder, grouped, disposition
// Antwort 200
{
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "confirmed",
  "wholesaler": "noweda",
  "dry_run": false,
  "items": [
    {
      "pzn": "761271",
      "quantity_ordered": 3,
      "quantity_confirmed": 3,
      "delivery_preference": "backorder",
      "deliveries": [
        {
          "type": "normal",
          "quantity": 3,
          "tour": "00345H",
          "tour_id": "00345H2704261403",
          "estimated_at": "2026-04-28T10:00:00"
        }
      ]
    }
  ]
}

status-Werte: confirmed, dry_run, queued_night_mode

Fehler: 400, 401, 404, 422 (Bestellung abgelehnt), 502

GET /v1/orders/{order_id}/status?wholesaler=noweda

Aktuellen Status einer zuvor aufgegebenen Bestellung abrufen.

// Antwort 200
{
  "order_id": "GW-ABCDEF12",
  "status": "available",
  "items": [
    {
      "pzn": "761271",
      "quantity_ordered": 3,
      "delivery_preference": "backorder"
    }
  ]
}

status-Werte: available, expired, unknown


GET /v1/deliveries?wholesaler=noweda

Unbestaetigte Lieferavise vom Grosshaendler abrufen. Nach Verarbeitung mit POST /v1/deliveries/confirm bestaetigen.

// Antwort 200
{
  "wholesaler": "noweda",
  "deliveries": [
    {
      "tracking_number": "LS-123",
      "barcode": "1*123",
      "order_type": "normal",
      "date": "2026-04-27",
      "has_shortages": false,
      "items": [
        {
          "pzn": "761271",
          "quantity_delivered": 3,
          "shortages": 0
        }
      ]
    }
  ]
}

POST /v1/deliveries/confirm

Lieferungen anhand ihrer Trackingnummern bestaetigen.

// Anfrage
{
  "wholesaler": "noweda",
  "tracking_numbers": ["LS-123", "LS-124"]
}

// Antwort 200
{
  "wholesaler": "noweda",
  "confirmed": ["LS-123", "LS-124"],
  "status": "confirmed"
}

GET /v1/deliveries/history?wholesaler=noweda

Historische Lieferavise abrufen. Filtern nach Trackingnummer oder Barcode.


POST /v1/returns

Retourenantrag einreichen. Jeder Artikel muss die Original-Lieferscheinnummer und einen Retourengrund angeben.

WertBeschreibung
order_errorArtikel versehentlich bestellt
not_deliveredBerechnet, aber nicht erhalten
damagedBeschaedigt eingetroffen
expiry_too_shortVerfallsdatum zu nah
over_deliveredMehr Stueck als bestellt geliefert

POST /v1/returns/announce

Bevorstehende Retoure ankuendigen. Der Grosshaendler kann die Retoure in mehrere Anteile aufteilen.

POST /v1/returns/offers

Preis-/Gutschrift-Informationen vom Grosshaendler fuer eine potenzielle Retoure anfordern. Erfordert die return_offers-Faehigkeit im Vertrag.


GET /v1/documents/{id}?wholesaler=noweda

PDF-Dokument (Lieferschein, Retourenlabel) anhand seiner ID herunterladen. Antwort: application/pdf binaer.


POST /v1/webhooks

Webhook-Abonnement erstellen. Erfordert nur X-API-Key -- keine MSV3-Zugangsdaten.

EreignisAusloeser
delivery.receivedNeue Lieferbenachrichtigung verfuegbar
delivery.shortageLieferung enthaelt Fehlmengen
order.status_changedBestellstatus aktualisiert
wholesaler.status_changedGrosshaendler-Endpunkt ist hoch-/runtergefahren
// Anfrage
{
  "url": "https://example.com/hooks/msv3",
  "wholesaler": "noweda",
  "events": ["delivery.received", "order.status_changed"]
}

// Antwort 201
{
  "id": "whk_a1b2c3d4e5f6",
  "url": "https://example.com/hooks/msv3",
  "wholesaler": "noweda",
  "events": ["delivery.received"],
  "signing_secret": "a1b2c3d4e5f6...",
  "active": true
}

Wichtig: Das signing_secret wird nur einmal zurueckgegeben. Speichern Sie es sicher.

GET /v1/webhooks

Alle Webhook-Abonnements auflisten. Das Signing-Secret ist maskiert.

DELETE /v1/webhooks/{id}

Webhook-Abonnement dauerhaft loeschen. Gibt 204 bei Erfolg zurueck.


Webhook-Signaturen

Jede Webhook-Zustellung enthaelt einen X-MSV3-Signature-Header mit dem HMAC-SHA256-Digest des Anfrage-Bodies.

X-MSV3-Signature: sha256=a1b2c3d4e5f6...
X-MSV3-Event: delivery.received
X-MSV3-Request-Id: evt_9f3a...

Verifizieren Sie immer die Signatur, bevor Sie Webhook-Payloads verarbeiten. Verwenden Sie Roh-Bytes -- parsen Sie den Body nicht vor der Verifizierung.