Files
JiriUhlir 0e05fef335 first
2026-07-16 11:56:15 +02:00

3.9 KiB

PPL CPL API — přehled služby

Stateless multi-tenant proxy nad PPL CPL API (Create Package Label). Upstream: https://api.dhl.com/ecs/ppl/myapi2 (production), https://api-dev.dhl.com/ecs/ppl/myapi2 (test). Dokumentace PPL: https://ppl-cpl-api.apidog.io/

Autentizace

Každý request nese hlavičky:

  • X-Client-Id — PPL ClientId (secret)
  • X-Client-Secret — PPL ClientSecret (secret)
  • X-Environmentproduction (default) nebo test
  • Accept-Language — volitelně, předává se do PPL (např. cs-CZ)

Služba z údajů získá OAuth Bearer token (POST {base}/login/getAccessToken, grant client_credentials, scope myapi2) a cachuje ho in-memory pod SHA-256 hashem údajů. Důvod: PPL vydá max. 12 tokenů/min a token platí 30 minut. Token se obnovuje 60 s před expirací; na HTTP 401 z PPL se jednou obnoví a request se zopakuje.

Limity PPL, které služba respektuje

  • min. 40 ms rozestup mezi requesty (globální throttle v procesu),
  • max. 1000 zásilek / 100 objednávek v jednom batchi,
  • batchId platí 30 dní,
  • pouze Latin znaky bez diakritiky — viz transliterace níže.

Transliterace diakritiky

CPL API odmítá texty s diakritikou. Těla POST /shipments/batch, /shipments/create-and-wait, /orders/batch a /orders/create-and-wait se defaultně rekurzivně transliterují přes unidecode (Jiří DvořákJiri Dvorak). Chování:

  • query parametr transliterate=true|false na requestu má přednost,
  • jinak platí env CPL_TRANSLITERATE (default true),
  • generická /proxy/... NEtransliteruje nikdy (předává 1:1).

Chybové odpovědi

Jednotný JSON {error, message, detail}; detail obsahuje původní problem+json z PPL (typ, title, errors...).

Status Význam
400 validační chyba (vstup zde nebo v PPL)
401 chybějící X- hlavičky nebo PPL odmítlo údaje/token
403 chybí oprávnění (role) k metodě v PPL
404 batch/zásilka/objednávka neexistuje
429 rate limit PPL
502 výpadek / neočekávaná chyba PPL

Všechny chyby se logují (bez secrets) — žádná tichá selhání.

Konfigurace (environment variables)

Proměnná Default Význam
ROOT_PATH "" prefix za reverse proxy (/apps/pplcplapi)
CPL_DEFAULT_ENVIRONMENT production prostředí bez hlavičky X-Environment
CPL_PRODUCTION_BASE_URL / CPL_TEST_BASE_URL viz výše base URL upstreamu
CPL_OAUTH_SCOPE myapi2 OAuth scope
CPL_TRANSLITERATE true default transliterace diakritiky
UPSTREAM_TIMEOUT_SECONDS 60 timeout volání PPL
TOKEN_REFRESH_MARGIN_SECONDS 60 předstih obnovy tokenu
MIN_REQUEST_INTERVAL_SECONDS 0.04 rozestup requestů na PPL
BATCH_POLL_INTERVAL_SECONDS 1.0 interval pollingu create-and-wait
BATCH_WAIT_TIMEOUT_SECONDS 30 default timeout create-and-wait
LOG_LEVEL INFO úroveň logování

Žádné secrets se nekonfigurují přes env — vše chodí per-request v hlavičkách.

Struktura kódu

app/
  main.py            — FastAPI aplikace, root_path, popis pro Swagger
  config.py          — env konfigurace
  credentials.py     — X- hlavičky -> Credentials (dependency)
  token_cache.py     — in-memory cache OAuth tokenů
  cpl_client.py      — autentizovaný httpx klient, throttle, relay helpery
  transliterate.py   — rekurzivní unidecode JSON těl
  errors.py          — typované chyby + handlery
  routers/
    meta.py          — /health, /version
    shipments.py     — zásilky, etikety, tracking, storno, celní dokumenty
    orders.py        — objednávky svozu/přepravy
    codelists.py     — číselníky, /version-information, /cpl-info
    lookups.py       — /access-points, /address-whisper, /routing, /data/{guid}
    customer.py      — /customer, /customer/addresses, /customer/number-range
    proxy.py         — generická proxy /proxy/{cesta}