API surfaces
Commerce exposes four API surfaces from one application. The route prefix is not cosmetic — it decides how you authenticate, what you can see, what your responses look like and what happens when something fails.
Pick the door before you write anything. Coming through the wrong one is the most common way to lose a day here.
| UI API | Back office API | Integration API | Public API | |
|---|---|---|---|---|
| Route | /api/ui |
/api/admin |
/api/integration |
/api/public |
| Who calls it | A user in a storefront | The client's back-office staff | The ERP or its middleware | A third party, outside the business |
| Authentication | Cookie session | Cookie session | Bearer JWT | API key header |
| Authorization | PortalUser, then a per-action customer role |
HostAdmin |
InboundPolicy on the bearer scheme |
The key scheme alone |
| Customer scope | Scoped to the user's active session | Bypass — sees everything | Bypass | Bypass; the caller names the customer |
| Request shape | Whatever the endpoint takes | Whatever the endpoint takes | A batch envelope | A batch of keys |
| Response shape | Plain DTOs | Plain DTOs | A per-item result list | Wrapped in { "data": … } |
| On failure | Problem details | Problem details | Problem details | Its own problem shape, applied outermost |
| Rate limited | No | No | No | Yes, per token |
| Breaking it costs | A storefront release | An admin release | An upstream integration change | A phone call to someone else's company |
That last row is the one that should change how you behave. Three of these surfaces are internal and move when you move. The fourth is consumed by people who did not attend your planning meeting.
Two things every surface shares
Authentication mechanics — the cookie session, Entra, the schemes and the trusted-origins rules — are common to all of them and live on Authentication.
Correlation. Every request gets a correlation id, carried on an X-Correlation-Id header, so one
customer action can be followed across the log for the request and any background work it triggered.
Why four and not one
A single surface would have to authenticate every caller the same way — and these callers have nothing in common. A browser cannot hold a secret. An ERP has no user to sign in as. A third party must be rate-limited and revocable without touching anyone else. Attempting one scheme for all three produces the worst of each.
Splitting by route prefix rather than by host or deployment keeps that difference visible in the URL, which means it is visible in the logs, in the reverse proxy, and in the mind of whoever is reading a stack trace at the time.