# Complete Frontend API Surface — Master Endpoint List Generated 2026-08-18, updated same day after the frontend backlog (F1–F65) closed, updated again same day to add §0 after a direct question ("everything is there? payment auth?") caught that the first pass only grepped `src/app/` — auth moved into the external `@marketplaces/auth` package this session, and its own HTTP calls (§0) were missing from what this doc called "complete." Fixed by grepping `node_modules/@marketplaces/auth/dist/` directly. 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`, and now the auth package). 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. | --- ## 0. Auth — lives in `@marketplaces/auth`, not this repo, and payment authorization runs through it Two separate, real mechanisms. Both are called from the external package (`node_modules/@marketplaces/auth/dist/`), which is why §0 didn't exist in the first pass of this doc — that pass only grepped `src/app/`. ### 0.1 Telegram QR/session — ✅ Specified, **live** Per `BACKEND-HANDOFF.md` §3 and `PACKAGES-USAGE.md`. **Customer and admin login call the same endpoints** — only client-side storage differs, which is exactly why every admin endpoint must independently verify authorization server-side (stated plainly in `BACKEND-HANDOFF.md` §3 as "the single most serious open issue in the system"). | Method | Path | Purpose | |---|---|---| | POST | `{authApiUrl}/users/sessions` | create a session from a Telegram login | | GET | `{authApiUrl}/users/sessions/{id}` | poll / check session status | | DELETE | `{authApiUrl}/users/sessions/{id}` | log out | Expected response: `{ webSessionID, user: { userId, username, firstName, lastName }, status, expiresAt }` — parsed permissively client-side (many key-name variants accepted), but a clean backend implementation should return exactly this shape. ### 0.2 Ed25519 admin challenge/response — specified, **not built** Per `BACKEND-HANDOFF.md` §3 and the package's own `ed25519/models/auth-api.model.ts`. This is what backend-authorizes an admin session distinctly from a customer one, and it does not exist server-side yet — every request today shows a `backend-unavailable` screen once the client reaches for it, nothing is mocked. | Method | Path | |---|---| | GET | `/api/admin/auth/challenge` | | POST | `/api/admin/auth/verify` | | POST | `/api/admin/auth/refresh` | | POST | `/api/admin/auth/logout` | ### 0.3 What this has to do with payment There is no separate "payment login." Authorization for anything payment-adjacent — creating a checkout session, viewing `GET /api/admin/v2/orders/{id}`'s pricing breakdown (§20), touching a partner credential (§16) — rides on whichever of the two sessions above is active. The partner-provisioning API (§16) has its **own**, separate signed-request auth (§6 of that contract, public-key based, no session token at all) — that one is unrelated to Telegram/ed25519 and is not a gap, it's a different, already-built mechanism for a different caller (partners, not our own admins or customers). **The actual payment gap is §1 below, not auth**: QR/card payment creation and status polling are real, live, and completely undocumented anywhere in `docs/backend/`. --- ## 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 | | GET | `/searchitems` | `api.service.ts` | ❌ Undocumented — search | | GET | `/items/randomitems` | `api.service.ts` | ❌ Undocumented — related/random items | | 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 | `/items/{itemID}/notify-me` | `api.service.ts` | ❌ Undocumented — back-in-stock subscription | | POST | `/purchase-email` | `api.service.ts` | ❌ Undocumented — post-purchase email collection | | POST | `/orders` | `api.service.ts` | ❌ Undocumented — records a paid cart as a backoffice order, fire-and-forget | **Recommendation:** these 11 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/`. **Removed 2026-08-21, no longer called by this codebase:** `POST {qrBaseUrl}/qr` (direct QR creation), `POST /cart` (legacy payment creation with client-sent `amount`), `GET {qrBaseUrl}/qr/dynamic/{partnerId}/{qrId}` and `GET {qrBaseUrl}/card/{partnerId}/{orderId}` (status polls). §2's checkout flow made these dead in code (`createPaymentIntent`) as of the earlier `@marketplaces/payment` integration commit; confirmed zero remaining callers and deleted the dead `ApiService` methods, request/response types, and unused fields (`qrBaseUrl`, `cartPaymentPartnerId`) in the same pass. If a real backend still serves these endpoints, they are now backend-only surface with no frontend caller — decide their fate independently of this doc. --- ## 2. Storefront checkout & cart — ✅ Specified Contract: [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §5.2, [PHASE-6-CART-CHECKOUT-CONTRACT.md](PHASE-6-CART-CHECKOUT-CONTRACT.md) §3, §5. | Method | Path | Called from | |---|---|---| | GET | `/api/v2/storefront/cart` | `server-cart-api.gateway.ts` | | POST | `/api/v2/storefront/cart/lines` | `server-cart-api.gateway.ts` | | PATCH | `/api/v2/storefront/cart/lines/{lineId}` | `server-cart-api.gateway.ts` | | DELETE | `/api/v2/storefront/cart/lines/{lineId}` | `server-cart-api.gateway.ts` | | POST | `/api/v2/storefront/checkout` | `server-cart-api.gateway.ts`, `api.service.ts` (two different callers, same contract) | | POST | `/api/v2/storefront/payments/intents` | `api.service.ts` | ## 3. Pricing — ✅ Specified Contract: [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §3.1. | Method | Path | Called from | |---|---|---| | GET | `/api/v2/pricing/fx-quote?base="e=` | `fx-quote-api.gateway.ts` | ## 4. Identity & permissions — ✅ Specified Contracts: [PHASE-8-IDENTITY-MESSAGING-CONTRACT.md](PHASE-8-IDENTITY-MESSAGING-CONTRACT.md) §2, [TRACK-S-SECURITY-RBAC-CONTRACT.md](TRACK-S-SECURITY-RBAC-CONTRACT.md) §2. | Method | Path | Called from | |---|---|---| | GET | `/api/identity/v1/vk/authorize` | `vk-id-api.gateway.ts` | | POST | `/api/identity/v1/vk/callback` | `vk-id-api.gateway.ts` | | GET | `/api/identity/v1/session/permissions` | `permission-api.gateway.ts` | ## 5. Team / RBAC — mixed Contract: [TRACK-S-SECURITY-RBAC-CONTRACT.md](TRACK-S-SECURITY-RBAC-CONTRACT.md) §8. | Method | Path | Called from | Status | |---|---|---|---| | GET | `/api/admin/v2/audit` | `permission-api.gateway.ts`, `admin-users-api.gateway.ts?actor=` | ✅ Specified | | POST | `/api/admin/v2/team/invite` | `admin-users-api.gateway.ts` | ✅ Specified | | GET | `/api/admin/v2/team?marketplaceId=` | `admin-users-api.gateway.ts` | ✅ Specified | | PATCH | `/api/admin/v2/team/{userId}` | `admin-users-api.gateway.ts` | ✅ Specified | | DELETE | `/api/admin/v2/team/{userId}` | (interface exists, not yet called) | ✅ Specified | | GET | `/api/admin/v2/team/roles` | `admin-users-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/team/invitations` | `admin-users-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/team/{userId}/sessions` | `admin-users-api.gateway.ts` | ⚠️ Inferred | | PATCH | `/api/admin/v2/team/{userId}/status` | `admin-users-api.gateway.ts` | ⚠️ Inferred | | DELETE | `/api/admin/v2/team/invitations/{id}` | `admin-users-api.gateway.ts` | ⚠️ Inferred | | DELETE | `/api/admin/v2/team/sessions/{sessionId}` | `admin-users-api.gateway.ts` | ⚠️ Inferred | ## 6. Orders & notifications — ✅ Specified Contract: [PHASE-2-ORDERS-NOTIFICATIONS-CONTRACT.md](PHASE-2-ORDERS-NOTIFICATIONS-CONTRACT.md). | Method | Path | Called from | |---|---|---| | GET | `/api/admin/v2/orders?marketplaceId=&status=&source=&page=&pageSize=` | `admin-orders-api.gateway.ts` | | GET | `/api/admin/v2/orders/{id}` | `admin-orders-api.gateway.ts` | | PATCH | `/api/admin/v2/orders/{id}/status` | `admin-orders-api.gateway.ts` | | 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` | | DELETE | `/api/admin/v2/orders/{id}` | `admin-orders-api.gateway.ts` | | GET | `/api/admin/v2/notifications?marketplaceId=&unreadOnly=&eventType=` | `admin-notifications-api.gateway.ts` | | PATCH | `/api/admin/v2/notifications/{id}/read` | `admin-notifications-api.gateway.ts` | | PATCH | `/api/admin/v2/notifications/read-all` | `admin-notifications-api.gateway.ts` | ⚠️ Inferred (bulk mark-read not in contract) | ## 7. Catalog / offers — ✅ Specified + ⚠️ Inferred Contract: [PHASE-3-CATALOG-OFFER-FULFILLMENT-CONTRACT.md](PHASE-3-CATALOG-OFFER-FULFILLMENT-CONTRACT.md) §7. | Method | Path | Called from | Status | |---|---|---|---| | GET | `/api/admin/v2/products?marketplaceId=&status=&search=&page=&pageSize=` | `admin-products-api.gateway.ts` | ✅ Specified | | GET | `/api/admin/v2/products/{id}` | `admin-products-api.gateway.ts` | ✅ Specified | | POST | `/api/admin/v2/products` | `admin-products-api.gateway.ts` | ✅ Specified | | PATCH | `/api/admin/v2/products/{id}` | `admin-products-api.gateway.ts` | ✅ Specified | | GET | `/api/admin/v2/offers?productId=&sellerId=&status=` | `offer-api.gateway.ts` | ✅ Specified | | POST | `/api/admin/v2/offers/{id}/publish` | `offer-api.gateway.ts` | ✅ Specified — 422 + `details[]` on executability failure | | GET | `/api/admin/v2/offers/lookup?sku=&sellerSku=&externalId=` | `offer-api.gateway.ts` | ✅ Specified | | GET | `/api/admin/v2/products/categories` | `admin-products-api.gateway.ts` | ⚠️ Inferred | | DELETE | `/api/admin/v2/products/{id}` | `admin-products-api.gateway.ts` | ⚠️ Inferred | | POST | `/api/admin/v2/products/{id}/duplicate` | `admin-products-api.gateway.ts` | ⚠️ Inferred | | POST | `/api/admin/v2/products/{id}/archive` | `admin-products-api.gateway.ts` | ⚠️ Inferred | | POST | `/api/admin/v2/products/{id}/restore` | `admin-products-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/offers/{offerId}/inventory` | `offer-api.gateway.ts` | ⚠️ Inferred | ## 8. Categories — ✅ Specified (pre-existing, F29 done before this session) | Method | Path | Called from | |---|---|---| | GET | `{baseUrl}` (categories collection) | `admin-categories-api.gateway.ts` | | GET | `{baseUrl}/{id}` | `admin-categories-api.gateway.ts` | | POST | `{baseUrl}` | `admin-categories-api.gateway.ts` | | PUT | `{baseUrl}/{id}` | `admin-categories-api.gateway.ts` | | DELETE | `{baseUrl}/{id}` | `admin-categories-api.gateway.ts` | | POST | `{baseUrl}/{id}/restore` | `admin-categories-api.gateway.ts` | | GET | `{baseUrl}/slug-taken` | `admin-categories-api.gateway.ts` | ## 9. Seller portal — mixed Contract: [PHASE-5-SELLER-PORTAL-CONTRACT.md](PHASE-5-SELLER-PORTAL-CONTRACT.md) §3. | Method | Path | Called from | Status | |---|---|---|---| | 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 | ## 10. Payments, refunds, reconciliation, settlements — ✅ Specified Contract: [PHASE-7-PAYMENTS-RECONCILIATION-CONTRACT.md](PHASE-7-PAYMENTS-RECONCILIATION-CONTRACT.md). | Method | Path | Called from | |---|---|---| | GET | `/api/admin/v2/orders/{orderId}/refunds` | `finance-api.gateway.ts` | | GET | `/api/admin/v2/reconciliation/queue` | `finance-api.gateway.ts` | | POST | `/api/admin/v2/reconciliation/{id}/resolve` | `finance-api.gateway.ts` | | GET | `/api/admin/v2/finance/settlements?sellerId=` | `finance-api.gateway.ts` | ## 11. Tenant registry — mixed Contract: [PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md). | Method | Path | Called from | Status | |---|---|---|---| | 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 | ## 12. Connector framework — mixed Contract: [PHASE-4-CONNECTOR-FRAMEWORK-CONTRACT.md](PHASE-4-CONNECTOR-FRAMEWORK-CONTRACT.md) §7-8. | Method | Path | Called from | Status | |---|---|---|---| | GET | `/api/admin/v2/integrations` | `connector-api.gateway.ts` | ✅ Specified | | PATCH | `/api/admin/v2/integrations/{id}` | `connector-api.gateway.ts` (pause/resume via `status` field) | ✅ Specified | | 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 | ## 13. Content modules (Gorbushka-class) — ⚠️ Mostly inferred Contract: [PHASE-10-CONTENT-MODULES-CONTRACT.md](PHASE-10-CONTENT-MODULES-CONTRACT.md) §2. | Method | Path | Called from | Status | |---|---|---|---| | POST | `/api/admin/v2/content/rent-listings/{id}/leads` | `mall-content-api.gateway.ts` | ✅ Specified | | GET | `/api/admin/v2/content/shops` | `mall-content-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/content/shop-categories` | `mall-content-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/content/floors` | `mall-content-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/content/floors/{floorId}/pins` | `mall-content-api.gateway.ts` | ⚠️ Inferred | | GET | `/api/admin/v2/content/rent-listings` | `mall-content-api.gateway.ts` | ⚠️ Inferred | ## 14. Analytics — ✅ Specified Contract: [TRACK-A-ANALYTICS-CONTRACT.md](TRACK-A-ANALYTICS-CONTRACT.md) §1. | Method | Path | Called from | |---|---|---| | POST | `/api/v2/storefront/analytics/events` | `analytics-api.gateway.ts` | ## 15. Transactions, monitoring, moderation — ❌ No contract doc exists These three domains have gateways calling `/api/admin/v2/{resource}` by convention only. No Phase/Track doc covers any of them. | Method | Path | Called from | |---|---|---| | GET | `/api/admin/v2/transactions` | `admin-transactions-api.gateway.ts` | | POST | `/api/admin/v2/transactions/{id}/retry` | `admin-transactions-api.gateway.ts` | | PATCH | `/api/admin/v2/transactions/{id}` | `admin-transactions-api.gateway.ts` | | GET | `/api/admin/v2/monitoring/events` | `admin-monitoring-api.gateway.ts` | | GET | `/api/admin/v2/monitoring/queues` | `admin-monitoring-api.gateway.ts` | | GET | `/api/admin/v2/monitoring/webhooks` | `admin-monitoring-api.gateway.ts` | | GET | `/api/admin/v2/moderation/reviews` | `admin-moderation-api.gateway.ts` | | GET | `/api/admin/v2/moderation/reviews/{id}` | `admin-moderation-api.gateway.ts` | | PATCH | `/api/admin/v2/moderation/reviews/{id}` | `admin-moderation-api.gateway.ts` (status/visible/pinned/featured — 4 different PATCH bodies, same endpoint) | | POST | `/api/admin/v2/moderation/reviews/{id}/notes` | `admin-moderation-api.gateway.ts` | | DELETE | `/api/admin/v2/moderation/reviews/{id}` | `admin-moderation-api.gateway.ts` | | GET | `/api/admin/v2/moderation/reports` | `admin-moderation-api.gateway.ts` | | PATCH | `/api/admin/v2/moderation/reports/{id}` | `admin-moderation-api.gateway.ts` | | 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` | | PATCH | `/api/partner/v1/nodes/{nodeId}/status` | `partner-hierarchy-api.gateway.ts` | | POST | `/api/partner/v1/nodes/{nodeId}/disable` | `partner-hierarchy-api.gateway.ts` | | GET | `/api/partner/v1/credentials?companyId=` | `partner-hierarchy-api.gateway.ts` | | POST | `/api/partner/v1/credentials` | `partner-hierarchy-api.gateway.ts` | | POST | `/api/partner/v1/credentials/{keyId}/rotate` | `partner-hierarchy-api.gateway.ts` | | DELETE | `/api/partner/v1/credentials/{keyId}` | `partner-hierarchy-api.gateway.ts` | ## 17. Backoffice data & bootstrap — ✅ Specified elsewhere (not a Phase/Track doc, but stable) | Method | Path | Called from | |---|---|---| | GET | `/api/backoffice/products` | `api-backoffice-data.provider.ts` | | GET | `/api/backoffice/categories` | `api-backoffice-data.provider.ts` | | GET | (tenant bootstrap URL) | `api-bootstrap.provider.ts` — see `BACKEND-HANDOFF.md` §1a | ## 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: - `PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md` §6.3 — webhook idempotency key = `provider + providerEventId` - `PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md` §6.4 — order creation idempotency key = `checkoutSessionId` - `PARTNER-PROVISIONING-API-CONTRACT.md` §5 — `Idempotency-Key` header semantics for all partner-API creates --- ## Summary counts | Status | Count | |---|---| | ✅ Specified | 54 | | ⚠️ Inferred (needs confirmation) | 24 | | ❌ Undocumented (legacy) | 11 | | **Total distinct endpoints called** | **93** | (§0's 3 Telegram endpoints count as Specified+live; its 4 ed25519 endpoints count as Specified+not-built — both are real, named endpoints with a known shape, distinct from §1's "no contract exists anywhere" undocumented status.) Plus 3 response-shape additions (§19–21) on existing endpoints — not new endpoints, new optional fields on responses those endpoints already return. ## What backend needs to do with this 0. **§0.2 first, ahead of everything else on this list.** The 4 ed25519 admin auth endpoints are the single most serious open issue named anywhere in `docs/backend/` (`BACKEND-HANDOFF.md` §3's own words). Every other item below assumes an admin session exists to authorize the request — that session mechanism does not exist server-side yet. 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).