> For the complete documentation index, see [llms.txt](https://docs.solutioo.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.solutioo.de/entwicklerdokumentationen-business-central-dhl-connector/dhl-connector-entwicklerdokumentation/codeunit-referenz/72242952-soudhl-api-management.md).

# 72242952 SOUDHL API Management

## Verantwortung

Zentrale Transport- und Label-Codeunit für Parcel DE und MyDHL Express. Sie kapselt Authentifizierung, Request-Aufbau, HTTP, Response-Parsing, Persistenz, Labeldownload und PDF-Vorschau.

**Wichtig:** Technisch öffentliche Hilfsmethoden sind nicht automatisch unterstützte Partner-APIs. Externe Apps sollen die High-Level-Methoden und Events verwenden.

## Unterstützte High-Level-API

### `IsExpress(): Boolean`

Liest den ersten Konfigurationsdatensatz und liefert, ob Express aktiv ist. Keine Schreibwirkung.

### `GenerateLabel(PackageHeader: Record "SOUDHL Package Header"; var ExtraMessage: Text): Boolean`

Hauptentry für beide Services. Prüft Service, erzeugt und speichert das Label, committet den Labelerfolg und stößt danach optional die Kartonbestandsbuchung an. `ExtraMessage` enthält fachliche Fehler oder Inventurwarnungen.

### `GetRate(ReceiverCountry: Code[10]; ReceiverPostalCode: Text; ReceiverCity: Text; WeightKg: Decimal; LengthCm: Decimal; WidthCm: Decimal; HeightCm: Decimal; ProductCode: Code[5]; var Price: Decimal; var Currency: Text; var ExtraMessage: Text): Boolean`

Live-Preisabfrage für Express. Keine Tabellenwrites. Für Parcel DE wird `false` geliefert.

### `DownloadLabel(PackageHeader: Record "SOUDHL Package Header")`

Lädt das gespeicherte Label im `Print Format` herunter. Meldung statt Fehler, wenn kein Blob vorhanden ist.

### `DownloadCustomsDoc(PackageHeader: Record "SOUDHL Package Header")`

Lädt das gespeicherte CN23-/Customs-Dokument herunter.

## Integration Events

Vollständige Subscriber-Signaturen, Timing und Beispiele stehen unter **Integration Events**.

```al
[IntegrationEvent(false, false)]
local procedure OnBeforeGenerateLabel(
    var PackageHeader: Record "SOUDHL Package Header";
    SalesHeader: Record "Sales Header";
    IsExpress: Boolean)

[IntegrationEvent(false, false)]
local procedure OnAfterGenerateLabel(
    PackageHeader: Record "SOUDHL Package Header";
    Success: Boolean;
    ExtraMessage: Text)

[IntegrationEvent(false, false)]
local procedure OnBeforeSendParcelDEShipmentRequest(
    var RequestJson: JsonObject;
    PackageHeader: Record "SOUDHL Package Header";
    SalesHeader: Record "Sales Header")

[IntegrationEvent(false, false)]
procedure OnBeforeSendShipmentRequest(
    var RequestJson: JsonObject;
    PackageHeader: Record "SOUDHL Package Header";
    SalesHeader: Record "Sales Header")

[IntegrationEvent(false, false)]
local procedure OnBeforeGetRate(
    var ReceiverCountry: Code[10];
    var ReceiverPostalCode: Text;
    var ReceiverCity: Text;
    var WeightKg: Decimal;
    var LengthCm: Decimal;
    var WidthCm: Decimal;
    var HeightCm: Decimal;
    var ProductCode: Code[5])

[IntegrationEvent(false, false)]
local procedure OnAfterGetRate(
    ReceiverCountry: Code[10];
    ReceiverPostalCode: Text;
    ReceiverCity: Text;
    WeightKg: Decimal;
    LengthCm: Decimal;
    WidthCm: Decimal;
    HeightCm: Decimal;
    ProductCode: Code[5];
    Success: Boolean;
    Price: Decimal;
    Currency: Text;
    ExtraMessage: Text)
```

`OnBeforeGenerateLabel` läuft nach dem Empfänger-Snapshot in beiden Labelpfaden. `OnAfterGenerateLabel` deckt Erfolg und Fehler ab. `OnBeforeSendShipmentRequest` bleibt Express-only. `OnBeforeSendParcelDEShipmentRequest` ist der symmetrische Parcel-DE-Hook. `GetRate` behält seine öffentliche Signatur; Before und After werden intern um den Aufruf gelegt.

## Technisch öffentlich, aber kein stabiler Partnervertrag

### `BaseUrl(): Text`

Ermittelt Express-Live- oder Test-URL. Endpunktdetails bleiben Implementierung der App.

### `GenerateToken(var Token: Text): Boolean`

Gemeinsamer Authentifizierungstest. Wird vom Setup verwendet. Consumer-Apps sollen weder Token beziehen noch speichern.

### `CallPostAPI(ApiUrl: Text; RequestJson: Text; var ResponseText: Text; var ExtraMessage: Text): Boolean`

Low-Level-HTTP-POST. Umgeht fachliche Invarianten und kann sich mit DHL-Versionen ändern.

### `GetErrorDetail(APIResponseText: Text; var ErrorMessage: Text)`

Dispatcht auf Parcel- oder Express-Fehlerparser.

### `TryGetByProduct(Product: Enum SOUDHLProducts; var Map: Record "SOU DHL Billing Map"): Boolean`

Sucht die erste gültige Billing-Map-Zeile des Produkts.

### `ConvertPdfLabelToJpgAndStore(var PackageHeader: Record "SOUDHL Package Header"; var ExtraMessage: Text): Boolean`

Sendet ein PDF an den konfigurierten Konvertierungsdienst und speichert die Media-Vorschau. Wird intern und vom Labels Report genutzt.

## Lokale Parcel-DE-Methoden

* `GenerateTokenParcelDE`: OAuth-Zugriffstoken
* `CallPostAPIParcelDE`: Bearer-POST
* `GenerateLabelParcelDE`: Request, Call und Persistenz
* `GetErrorDetailParcelDE`: `validationMessages`
* `ParcelClientId` / `ParcelClientSecret`: Secret-Auflösung
* `ResolveParcelCountryCode`: Alpha-3-Land
* `ResolveParcelBillingNumber`: EKP + Produkt + Service

## Lokale Express-Methoden

* `GenerateTokenExpress`: Basic-Auth-Material
* `CallPostAPIExpress`: Headers und HTTP
* `GenerateLabelExpress`: Shipment-Orchestrierung
* `ParseShipmentResponse`: Tracking und Label
* `BuildShipperObject`, `BuildReceiverObject`, `BuildPackageObject`: Payload-Teile
* `BuildExportDeclaration`: Exportpositionen aus Package Lines
* `AddAccount`, `AddNotification`: Arrays
* `WeightInKg`, `NetWeightKg`, `DimensionInCm`: Normalisierung
* `IncotermOrDefault`, `PlannedShippingDateTime`, `NewMessageReference`: Defaults
* `ParseRateResponse`, `BuildRateAddress`, `GetErrorDetailExpress`: Rate und Fehler

## Gemeinsame interne Methoden

`ResolveAzureUrl` und `ResolveAzureKey` lösen den PDF-Konvertierungsdienst auf. Konkrete Secret-Werte sind kein Dokumentationsbestandteil.

## Abhängigkeiten

Configuration, Box, Package Header/Line, Billing Number/Map, Sales Header/Line, Country/Region; Secret Mgt, Recipient Mgt, Customs Mgt, Packing Mgt, Express Helper, Box Inventory Mgt und Installation.

## Seiteneffekte

* Empfänger-Snapshot
* Tracking auf Quellaufträgen
* Label-/Customs-Blobs und Media
* Uploadstatus und Datum
* expliziter Commit nach Labelerfolg
* optionale Inventurbuchung in separater Transaktion
* additive Integration Events ohne zusätzlichen `Commit()`

## Fehler und Grenzen

* `FindFirst()` erwartet einen Setupdatensatz.
* Parcel kann bei fehlendem Land oder Billing hart abbrechen.
* Express-Rate nimmt den ersten Produktpreis.
* Das Express-Request-Event existiert nur für Express; Parcel DE nutzt `OnBeforeSendParcelDEShipmentRequest`.
* Labeldaten enthalten personenbezogene Informationen und dürfen nicht unkontrolliert geloggt werden.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.solutioo.de/entwicklerdokumentationen-business-central-dhl-connector/dhl-connector-entwicklerdokumentation/codeunit-referenz/72242952-soudhl-api-management.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
