Generated 2026-08-18, updated same day after the frontend backlog (F1–F65) closed. Directly from source (every `this.http.get/post/patch/put/delete` call across `src/app/core/`, `src/app/features/admin/`, `src/app/services/api.service.ts`). This is not a design document — it is a **census**: every endpoint this codebase currently calls or will call once its gateway swap goes live, in one place, cross-referenced against the contracts that already exist.
**This is the final handoff doc for this pass.** Frontend work is done except one item that genuinely cannot be finished without a live backend (§19). Everything else — every gateway, every model, every invariant — is written, tested, and pushed. What follows is everything backend needs to make it real.
**Why this exists.** The individual Phase/Track contracts in this directory each cover one domain well. Nothing until now listed the *entire* surface in one pass, so a backend dev building against these docs had no way to see what's fully specified, what's inferred-and-needs-confirmation, and what has no contract at all. This closes that gap.
**Status legend**
| Status | Meaning |
|---|---|
| ✅ Specified | Exact shape exists in a Phase/Track contract doc. Build as written. |
| ⚠️ Inferred | Endpoint follows this codebase's own REST conventions (path pattern, verb) but no contract doc states it explicitly. Flagged in source with a comment at the call site. **Confirm or correct before building — do not treat as final.** |
| ❌ Undocumented | Legacy endpoint, no contract anywhere, still called by `api.service.ts`. Will be replaced when the corresponding `/api/v2` migration lands (Track N) — do not invest in these long-term, but they are live today. |
---
## 1. Legacy surface (still called today, no `/api/v2` contract)
These come from `BACKEND-API-REFERENCE.md`, not `docs/backend/`. Base URL is `environment.localhostApiUrl` / tenant-resolved; `qrBaseUrl` is a separate provider base for QR-specific calls.
| Method | Path | Called from | Status |
|---|---|---|---|
| GET | `/ping` | `api.service.ts` | ❌ Undocumented — health check |
| GET | `/category` | `api.service.ts`, `api-category.repository.ts` | ❌ Undocumented — full category tree |
| GET | `/category/{categoryID}` | `api.service.ts` | ❌ Undocumented — one category + its items |
| GET | `/items/{itemID}` | `api.service.ts` | ❌ Undocumented — single item detail |
| POST | `/websession/{sessionId}` | `api.service.ts` | ❌ Undocumented — sync cart to a Telegram web session |
| POST | `/items/{itemID}/callback` | `api.service.ts` | ❌ Undocumented — "call me back" request |
| POST | `/items/{itemID}/questiion` | `api.service.ts` | ❌ Undocumented — product Q&A (note: `questiion` typo is load-bearing, do not silently "fix" without checking the live backend uses the same typo) |
| POST | `{qrBaseUrl}/qr` | `api.service.ts` | ❌ Undocumented — direct QR payment creation |
| POST | `/cart` | `api.service.ts` | ❌ Undocumented — legacy payment creation, client-sent `amount` (superseded by §2 below for new checkout flow; **still live** for any caller not yet migrated) |
| GET | `{qrBaseUrl}/qr/dynamic/{partnerId}/{qrId}` | `api.service.ts` | ❌ Undocumented — QR payment status poll |
| GET | `{qrBaseUrl}/card/{partnerId}/{orderId}` | `api.service.ts` | ❌ Undocumented — card payment status poll |
| POST | `/orders` | `api.service.ts` | ❌ Undocumented — records a paid cart as a backoffice order, fire-and-forget |
**Recommendation:** these 15 need their own contract doc if they are staying, or a deprecation timeline if `/api/v2/storefront/*` replaces them. Right now they are simply undocumented and live — the single biggest gap in `docs/backend/`.
| POST | `/api/admin/v2/orders/{id}/refund-request` | `admin-orders-api.gateway.ts` (note: gateway calls this `refund-request`; interface method is named `requestRefund` — same endpoint) |
| POST | `/api/admin/v2/orders/{id}/notes` | `admin-orders-api.gateway.ts` |
| POST | `/api/admin/v2/orders/{id}/archive` | `admin-orders-api.gateway.ts` |
| POST | `/api/admin/v2/orders/{id}/restore` | `admin-orders-api.gateway.ts` |
| GET | `/api/seller/v1/finance/settlements` | (contract-only, no current caller) | ✅ Specified |
| GET | `/api/admin/v2/sellers` | `seller-api.gateway.ts` | ⚠️ Inferred — contract only specifies the caller's own `GET /api/seller/v1/profile`, not an admin list-all |
| GET | `/api/admin/v2/sellers/{sellerId}/team` | `seller-api.gateway.ts` | ⚠️ Inferred — contract's `GET /api/seller/v1/team` is session-scoped, not parameterized |
| GET | `/api/admin/v2/marketplaces/{id}/lifecycle` | `marketplace-api.gateway.ts` | ✅ Specified |
| GET | `/api/admin/v2/marketplaces` (list) | `marketplace-api.gateway.ts` | ⚠️ Inferred — contract specifies `POST` for creation, not the list `GET` |
| GET | `/api/admin/v2/marketplaces/{id}/domains` | `marketplace-api.gateway.ts` | ⚠️ Inferred |
| GET | `/api/admin/v2/integrations/{connectorId}/dead-letter` | `connector-api.gateway.ts` | ⚠️ Inferred — contract specifies replay, not the list |
| POST | `/api/admin/v2/integrations/{connectorId}/dead-letter/{id}/replay` | `connector-api.gateway.ts` | ✅ Specified — path corrected 2026-08-18; the gateway initially omitted `connectorId`, caught while writing this doc, fixed in the same pass |
| GET | `/api/admin/v2/dashboard/metrics` | `admin-dashboard-metrics-api.gateway.ts` |
**Recommendation: these are the highest-priority gap.** Three full admin domains with real UI and real gateways, zero backend contract. Whoever picks up Phase 5/7 next should write these as proper contract docs — the endpoint shapes above are a starting point, not a spec.
## 16. Partner provisioning API — ✅ Specified
Contract: [PARTNER-PROVISIONING-API-CONTRACT.md](PARTNER-PROVISIONING-API-CONTRACT.md) §4, §6. This is the one domain where the frontend gateway was built *from* the contract, not the other way around — no drift to reconcile.
| Method | Path | Called from |
|---|---|---|
| GET | `/api/partner/v1/companies/{companyId}/hierarchy?environment=` | `partner-hierarchy-api.gateway.ts` |
| GET | `/api/partner/v1/nodes/{nodeId}` | `partner-hierarchy-api.gateway.ts` |
| GET | `/api/partner/v1/nodes/lookup?externalReference=&environment=` | `partner-hierarchy-api.gateway.ts` |
| POST | `/api/partner/v1/companies/{companyId}/projects` | `partner-hierarchy-api.gateway.ts` |
| POST | `/api/partner/v1/projects/{projectId}/stores` | `partner-hierarchy-api.gateway.ts` |
| POST | `/api/partner/v1/stores/{storeId}/payment-points` | `partner-hierarchy-api.gateway.ts` |
## 18. Marketplace publish/revision model — ✅ Specified
Contract: [PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md) §5. Frontend core built (`marketplace-revision-*.gateway.ts`), not yet wired into the project editor's UI — see §20.
| Method | Path | Called from |
|---|---|---|
| POST | `/api/admin/v2/marketplaces/{id}/revisions` | `marketplace-revision-api.gateway.ts` — create draft |
| POST | `/api/admin/v2/marketplaces/{id}/revisions/{revId}/validate` | `marketplace-revision-api.gateway.ts` |
| POST | `/api/admin/v2/marketplaces/{id}/revisions/{revId}/publish` | `marketplace-revision-api.gateway.ts` |
| POST | `/api/admin/v2/marketplaces/{id}/revisions/{revId}/rollback` | `marketplace-revision-api.gateway.ts` — creates a NEW revision, never mutates the old one |
**One real ambiguity in §5 itself, flagged for confirmation, not guessed silently:** the pipeline is described as 4 stages (`draft → validated → preview → publish`) but only 3 write endpoints exist (validate/publish/rollback) — there is no dedicated "move to preview" call. The frontend model assumes `POST .../validate` moves a revision straight to `preview` (the state `publish` requires), treating `validated` as a value the caller may never observe. **Confirm this is correct before implementing** — if the real response returns `status: 'validated'` and requires a separate step to reach `preview`, the frontend model and this doc both need updating.
## 19. RoutingContext on payments — carried through, not yet backend-verified
Contract: [PARTNER-PROVISIONING-API-CONTRACT.md](PARTNER-PROVISIONING-API-CONTRACT.md) §7, [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §6.5. Not a separate endpoint — a field addition backend needs to populate on existing responses:
```ts
routing?: {
companyId: string;
routingPath: string[];
leafNodeId: string;
environment: 'TEST' | 'LIVE';
merchantReference: string;
providerPaymentId: string;
}
```
Frontend added this as an **optional** field on `AdminOrder` (`admin-order.model.ts`) and renders it on the order detail page when present. Nothing breaks if it's absent — but nothing shows the payment-point attribution either until backend populates it on `GET /api/admin/v2/orders/{id}`.
## 20. Order pricing breakdown — same pattern, different fields
Contract: [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §5.3. Optional fields added to `AdminOrderItem` and `AdminOrder`:
```ts
// per line
unitPriceMinor?: number;
lineTotalMinor?: number;
priceSnapshotId?: string;
discountMinor?: number;
// per order
fxQuoteId?: string;
deliveryMinor?: number;
```
Frontend renders a "total formula" panel on the order detail page (`order-total-formula.component.ts`) reconstructing `total = sum(unitPrice*qty) - discounts + delivery`, with the FX quote used. **It refuses to show a partial breakdown** — every line must carry `unitPriceMinor` or the panel says "not available" instead of a number that's silently wrong. Populate these fields on `GET /api/admin/v2/orders/{id}` to make it real; until then it correctly shows nothing.
## 21. Dashboard metrics — 8 new optional fields, no shape confirmed
Contract intent: [PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md) §7's target metric list — no contract doc defines `GET /api/admin/v2/dashboard/metrics`'s response shape (§15 already flagged this endpoint has no spec at all). Frontend added these as optional fields on `AdminDashboardMetrics`, each rendering `'unknown'` (not a fabricated `'healthy'`) while absent:
```ts
gmvMinor?: number;
currency?: string;
paidOrdersCount?: number;
conversionRate?: number; // 0-1, not a percentage
paymentFailureRate?: number; // 0-1
moderationQueueCount?: number;
lowStockCount?: number;
unmatchedEventsCount?: number;
integrationHealthyCount?: number;
integrationTotalCount?: number;
```
This is a genuine ask, not a confirmed contract — §15's recommendation to write a real spec for this endpoint still stands. These field names are what the frontend already expects; change them here first if backend needs different ones.
## 22. Idempotency — frontend now guards, backend enforcement is still required
The frontend added a client-side guard against double-submitting checkout (a real bug: double-clicking used to fire two `POST /api/v2/storefront/checkout` calls — fixed in `cart.component.ts`, `checkoutInFlight` signal). **This does not replace backend idempotency and was never meant to.** It closes one specific UI race; it does nothing for a retried request from a flaky network, a backgrounded tab resuming, or an actual duplicate webhook delivery. Contract requirements are unchanged and still required:
1.**Build the ✅ rows as written** — they match an existing contract doc exactly. This includes §18's 4 revision endpoints, pending confirmation on the `validated`/`preview` ambiguity called out there.
2.**Confirm or correct every ⚠️ row** — each one has a comment at its call site in source explaining the inference. Search the codebase for `Inferred` to find all 24 in place, with the reasoning right next to the code.
3.**Populate the 3 optional field sets (§19–21)** on the endpoints that already exist — `routing` and pricing-breakdown fields on `GET /api/admin/v2/orders/{id}`, the 8 metric fields on `GET /api/admin/v2/dashboard/metrics`. Nothing on the frontend breaks while these are absent; nothing shows the real data either.
4.**Write a contract for §15** (transactions, monitoring, moderation) — real UI, real gateways, zero spec. Highest-priority gap in this whole list.
5.**Decide the fate of §1** — 15 legacy endpoints with no contract at all, still live. Either document them as a stable, permanent surface, or set a Track N migration date.
6.**Enforce idempotency server-side regardless of §22** — the frontend's double-click guard is a UI nicety, not a substitute for `Idempotency-Key`/`providerEventId` dedup.
## One item that stays blocked until a real backend exists
The frontend backlog (F1–F65, tracked this session) is complete except **F60: the full acceptance-path E2E** — seller → catalog → storefront → cart → checkout → payment → order → notification → fulfillment, in one test, against real infrastructure. Every other item is written, unit-tested, E2E-covered where an E2E test could prove something real, and pushed. This one cannot be honestly finished by mocking harder — it needs an actual backend to run against. Once even a minimal version of Phases 1–4 is live, this is the next thing to build (`docs/PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md` Track Q, Q3).