---
seo:
  description: >-
    Control-plane API for Sarvex V1 — the authenticated surface behind the
    merchant console, the operator tooling, and the store-connector ingest
    endpoint.
sidebar:
  label: Overview
title: Sarvex V1 API
---
Control-plane API for Sarvex V1 — the authenticated surface behind the merchant
console, the operator tooling, and the store-connector ingest endpoint.

## Scope of this document
This specification covers the **control plane** and the **sync-plane ingest edge**
(`/connector/*`). It deliberately does **not** specify the **serving plane**
(the UCP edge: profile, discovery, pricing, availability, shipping, and the three
checkout-session operations). Those endpoints conform to the published UCP / Google
UCP-checkout schemas — they are governed by an external specification, not by
Sarvex's own contract, and are versioned against the UCP spec version recorded per
merchant in `conformance_record`. See the backend architecture document, Domains 4–5.

## Conventions (true for every operation)
- **Tenant scoping:** `merchant_id` is **never** a path or query parameter. It is
  read from the authenticated principal's token claim server-side, so a token can
  only ever reach its own tenant's data. Operators select a merchant via the
  `X-Operate-As` header (see security schemes), which is audit-logged.
- **Wire format:** all request and response bodies are JSON with **snake_case**
  field names.
- **List envelope:** all collection responses are
  `{ "data": [...], "page": { "cursor": string|null, "has_more": boolean } }`.
- **Error envelope:** all non-2xx responses are
  `{ "error": { "code": string, "message": string, "details": object|null } }`.
- **Pagination:** cursor-based via the `cursor` query parameter; `limit` caps page size.
- **Idempotency:** all mutating operations accept an `Idempotency-Key` header;
  replays return the original result.
- **Money:** integer minor units (cents) plus an ISO-4217 `currency` field; never floats.
- **Timestamps:** RFC 3339 / ISO 8601 UTC strings.

Version 1.0.0

Base URL: `https://api.sarvex.example.com/v1`, `https://api.staging.sarvex.example.com/v1`

## Contact

Marketing-site contact-form ingest (sarvex.example.com). Not merchant/operator-authenticated —
gated by a shared bearer token issued to the website only, scoped to this one endpoint.

- [`POST /contact`](/docs/api/control-plane/contact/post-contact) — Receive a contact-form submission from the marketing website

## Auth

Resolving the principal from the externally-issued, Sarvex-verified JWT. No login/logout — authentication is handled by the IdP (OAuth 2.0 authorization-code flow).

- [`GET /auth/me`](/docs/api/control-plane/auth/get-auth-me) — Resolve the current principal from the verified JWT

## Account

Merchant profile and Google-required business facts.

- [`GET /account`](/docs/api/control-plane/account/get-account) — Get the merchant account
- [`PATCH /account`](/docs/api/control-plane/account/patch-account) — Update account profile or business facts
- [`GET /account/members`](/docs/api/control-plane/account/get-account-members) — List team members
- [`POST /account/members`](/docs/api/control-plane/account/post-account-members) — Invite a team member (owner self-serve)

## Stores

The stores a merchant operates (merchant → store → connector). One in V1, modelled for many.

- [`GET /stores`](/docs/api/control-plane/stores/get-stores) — List the merchant's stores
- [`POST /stores`](/docs/api/control-plane/stores/post-stores) — Create a store under the merchant
- [`GET /stores/{store_id}`](/docs/api/control-plane/stores/get-stores-store-id) — Get a store
- [`GET /stores/{store_id}/profile`](/docs/api/control-plane/stores/get-stores-store-id-profile) — Get a store's business profile
- [`PUT /stores/{store_id}/profile`](/docs/api/control-plane/stores/put-stores-store-id-profile) — Set a store's business profile

## Payment

Per-store payment-handler configuration (instruments vs handlers model).

- [`GET /stores/{store_id}/payment-config`](/docs/api/control-plane/payment/get-stores-store-id-payment-config) — Get a store's payment-handler configuration
- [`PUT /stores/{store_id}/payment-config`](/docs/api/control-plane/payment/put-stores-store-id-payment-config) — Set a store's payment-handler configuration

## Connectors

Store connection, pairing, health. A connector belongs to a store.

- [`GET /connectors`](/docs/api/control-plane/connectors/get-connectors) — List connected stores
- [`POST /stores/{store_id}/connectors/pairing`](/docs/api/control-plane/connectors/post-stores-store-id-connectors-pairing) — Begin connecting a store
- [`GET /connectors/{connector_id}`](/docs/api/control-plane/connectors/get-connectors-connector-id) — Get a connector
- [`DELETE /connectors/{connector_id}`](/docs/api/control-plane/connectors/delete-connectors-connector-id) — Disconnect a store
- [`POST /connectors/{connector_id}/resync`](/docs/api/control-plane/connectors/post-connectors-connector-id-resync) — Trigger a full reconciliation pull

## Connector Ingest

**Sync-plane-served endpoints bundled here by convention.** These `/connector/*` paths
are actually served by the sync plane (not the control plane); they are included in this
spec for operational convenience (a single auth token reaches both control and sync).
Covered operations: plugin-facing ingest (HMAC-signed). Covers both plugin roles: change
signals (push) and the profile fetch the plugin serves at the merchant origin (Role 2).
The plugin does not proxy the UCP API — the profile's endpoint points directly at Sarvex.

- [`POST /connectors/pairing/complete`](/docs/api/control-plane/connector-ingest/post-connectors-pairing-complete) — Complete pairing and provision store credentials
- [`POST /connector/signals`](/docs/api/control-plane/connector-ingest/post-connector-signals) — Receive a change signal from the store plugin
- [`POST /connector/heartbeat`](/docs/api/control-plane/connector-ingest/post-connector-heartbeat) — Plugin heartbeat
- [`GET /connector/profile`](/docs/api/control-plane/connector-ingest/get-connector-profile) — Fetch the merchant's current UCP profile (for the plugin to serve at /.well-known/ucp)

## Catalog

Readiness score, products, attribute mappings.

- [`GET /stores/{store_id}/catalog/readiness`](/docs/api/control-plane/catalog/get-stores-store-id-catalog-readiness) — Get the current Agent Readiness Score
- [`GET /stores/{store_id}/catalog/products`](/docs/api/control-plane/catalog/get-stores-store-id-catalog-products) — List products with per-product readiness
- [`GET /stores/{store_id}/catalog/products/{sku}`](/docs/api/control-plane/catalog/get-stores-store-id-catalog-products-sku) — Get product detail with issues and attribute mappings
- [`POST /stores/{store_id}/catalog/audits`](/docs/api/control-plane/catalog/post-stores-store-id-catalog-audits) — Trigger a catalog audit

## Tasks

The task spine — every actionable item, by owner.

- [`GET /tasks`](/docs/api/control-plane/tasks/get-tasks) — List tasks (the task spine)
- [`GET /tasks/{task_id}`](/docs/api/control-plane/tasks/get-tasks-task-id) — Get a task with its typed drill-in payload
- [`POST /tasks/{task_id}/resolve`](/docs/api/control-plane/tasks/post-tasks-task-id-resolve) — Resolve a task

## Remediation

Rule-based fixes and reversible write-backs.

- [`GET /stores/{store_id}/catalog/remediations`](/docs/api/control-plane/remediation/get-stores-store-id-catalog-remediations) — List available remediations
- [`POST /stores/{store_id}/catalog/remediations/apply`](/docs/api/control-plane/remediation/post-stores-store-id-catalog-remediations-apply) — Apply rule-based remediations in a batch
- [`POST /stores/{store_id}/catalog/write-backs/{write_back_id}/revert`](/docs/api/control-plane/remediation/post-stores-store-id-catalog-write-backs-write-back-id-revert) — Revert a write-back to its prior value

## Validation

Pre-validation, sandbox, and production validation status.

- [`GET /stores/{store_id}/validation/status`](/docs/api/control-plane/validation/get-stores-store-id-validation-status) — Get the merchant's validation status
- [`GET /stores/{store_id}/validation/runs`](/docs/api/control-plane/validation/get-stores-store-id-validation-runs) — List validation runs (conformance records)
- [`POST /stores/{store_id}/validation/runs`](/docs/api/control-plane/validation/post-stores-store-id-validation-runs) — Trigger a pre-validation run

## UCP Presence

Read-only view of the hosted profile and manifest.

- [`GET /stores/{store_id}/presence`](/docs/api/control-plane/ucp-presence/get-stores-store-id-presence) — Get the hosted UCP presence summary
- [`GET /stores/{store_id}/presence/manifest`](/docs/api/control-plane/ucp-presence/get-stores-store-id-presence-manifest) — Get the raw served manifest
- [`POST /stores/{store_id}/presence/rebuild`](/docs/api/control-plane/ucp-presence/post-stores-store-id-presence-rebuild) — Force a serving-cache rebuild

## Orders

Orders created via Google checkout and their status sync.

- [`GET /stores/{store_id}/orders`](/docs/api/control-plane/orders/get-stores-store-id-orders) — List orders created via Google checkout
- [`GET /stores/{store_id}/orders/{order_id}`](/docs/api/control-plane/orders/get-stores-store-id-orders-order-id) — Get an order with its sync state

## Health

Post-go-live integration health and consistency.

- [`GET /stores/{store_id}/health`](/docs/api/control-plane/health/get-stores-store-id-health) — Get a store's overall health
- [`GET /stores/{store_id}/health/consistency`](/docs/api/control-plane/health/get-stores-store-id-health-consistency) — List consistency findings across sources
- [`GET /stores/{store_id}/health/history`](/docs/api/control-plane/health/get-stores-store-id-health-history) — Endpoint-health timeline — probe outcomes and status-check transitions
- [`GET /alerts`](/docs/api/control-plane/health/get-alerts) — List this merchant's endpoint-health alerts
- [`PATCH /alerts/{alert_id}`](/docs/api/control-plane/health/patch-alerts-alert-id) — Acknowledge or resolve an alert

## Checkout Sessions

Checkout Escalation Console — session projection, event timeline, and diagnosis for stalled or escalated checkouts.

- [`GET /checkout-sessions`](/docs/api/control-plane/checkout-sessions/get-checkout-sessions) — List checkout sessions
- [`GET /checkout-sessions/live`](/docs/api/control-plane/checkout-sessions/get-checkout-sessions-live) — List sessions currently in progress
- [`GET /checkout-sessions/{checkout_session_id}`](/docs/api/control-plane/checkout-sessions/get-checkout-sessions-checkout-session-id) — Get a checkout session, including its diagnosis
- [`GET /checkout-sessions/{checkout_session_id}/timeline`](/docs/api/control-plane/checkout-sessions/get-checkout-sessions-checkout-session-id-timeline) — Get a checkout session's event timeline

## Ledger

Lost Revenue Ledger — classified, priced, per-store visibility into checkouts that didn't convert.

- [`GET /ledger/summary`](/docs/api/control-plane/ledger/get-ledger-summary) — Monthly rollup, one entry per currency
- [`GET /ledger/entries`](/docs/api/control-plane/ledger/get-ledger-entries) — List lost-checkout entries
- [`PATCH /ledger/entries/{entry_id}`](/docs/api/control-plane/ledger/patch-ledger-entries-entry-id) — Change an entry's triage status

## Channel Dashboard

Agent sessionization, discovery→checkout funnel, and web-baseline comparison for the merchant's UCP-powered checkout channel — what it's earning and how it compares to the web channel.

- [`GET /channel/summary`](/docs/api/control-plane/channel-dashboard/get-channel-summary) — KPI summary, per surface and combined, with prior-period deltas
- [`GET /channel/funnel`](/docs/api/control-plane/channel-dashboard/get-channel-funnel) — Discovery-to-checkout funnel stage counts and derived rates
- [`GET /channel/daily`](/docs/api/control-plane/channel-dashboard/get-channel-daily) — Daily time series of funnel/revenue counts
- [`GET /channel/comparison`](/docs/api/control-plane/channel-dashboard/get-channel-comparison) — Agentic revenue vs. the merchant's web-channel baseline

## Agent Behavior Insights

- [`GET /insights/capability_gaps`](/docs/api/control-plane/agent-behavior-insights/get-insights-capability-gaps) — Capabilities agents requested that the merchant doesn't declare
- [`GET /insights/product_demand`](/docs/api/control-plane/agent-behavior-insights/get-insights-product-demand) — Top products by agent request count
- [`GET /insights/negotiation`](/docs/api/control-plane/agent-behavior-insights/get-insights-negotiation) — Negotiation outcomes, failure breakdown, and payment-handler mismatch detail

## Billing

Plan, usage, and Stripe-hosted management links.

- [`GET /billing`](/docs/api/control-plane/billing/get-billing) — Get plan, status, and usage
- [`POST /billing/portal-link`](/docs/api/control-plane/billing/post-billing-portal-link) — Create a Stripe Customer Portal link
- [`POST /billing/webhooks/stripe`](/docs/api/control-plane/billing/post-billing-webhooks-stripe) — Stripe webhook receiver

## Notifications

Channel preferences for the fixed V1 alert set.

- [`GET /notifications/preferences`](/docs/api/control-plane/notifications/get-notifications-preferences) — Get notification channel preferences
- [`PUT /notifications/preferences`](/docs/api/control-plane/notifications/put-notifications-preferences) — Replace notification channel preferences

## Activation

The store's own UCP activation lifecycle — profile served, capabilities declared,
signatures verifying, checkout working. Sarvex and the merchant only: nothing in
this lifecycle references feeds or any other agent surface. `active` is the terminal success state and is complete on its own; a
store may sit there with zero surfaces enrolled indefinitely.

- [`GET /stores/{store_id}/activation`](/docs/api/control-plane/activation/get-stores-store-id-activation) — Get the store's UCP activation state
- [`POST /stores/{store_id}/activation/verify`](/docs/api/control-plane/activation/post-stores-store-id-activation-verify) — Run conformance verification against the store's own endpoints

## Surfaces

Agent-surface enrollment — per-store, zero-to-many, registry-driven. A surface is
declared as a descriptor (requirements, prerequisite checks, artifacts, external
steps, verification signal); adding one is a descriptor plus its adapters, never a
change to these endpoints. The only dependency on activation runs one way:
enrollment cannot progress past `available` unless the store is `active`. Surfaces
never gate each other.

- [`GET /surfaces`](/docs/api/control-plane/surfaces/get-surfaces) — List the surface registry
- [`GET /stores/{store_id}/surfaces`](/docs/api/control-plane/surfaces/get-stores-store-id-surfaces) — List the store's enrollment state on every registered surface
- [`POST /stores/{store_id}/surfaces/{surface_id}/enroll`](/docs/api/control-plane/surfaces/post-stores-store-id-surfaces-surface-id-enroll) — Begin enrollment on a surface
- [`POST /stores/{store_id}/surfaces/{surface_id}/prerequisites/evaluate`](/docs/api/control-plane/surfaces/post-stores-store-id-surfaces-surface-id-prerequisites-evaluate) — Re-evaluate a surface's prerequisites on demand
- [`POST /stores/{store_id}/surfaces/{surface_id}/submit`](/docs/api/control-plane/surfaces/post-stores-store-id-surfaces-surface-id-submit) — Record that the merchant completed the surface's external steps
- [`PUT /stores/{store_id}/surfaces/{surface_id}/config`](/docs/api/control-plane/surfaces/put-stores-store-id-surfaces-surface-id-config) — Replace the merchant-supplied configuration for a surface
- [`DELETE /stores/{store_id}/surfaces/{surface_id}`](/docs/api/control-plane/surfaces/delete-stores-store-id-surfaces-surface-id) — Withdraw enrollment from a surface

## Journey

The per-store onboarding state machine.

- [`GET /stores/{store_id}/journey`](/docs/api/control-plane/journey/get-stores-store-id-journey) — Get the store's current journey state
- [`GET /stores/{store_id}/journey/stream`](/docs/api/control-plane/journey/get-stores-store-id-journey-stream) — Subscribe to live journey updates for the store

## Operator

Operator-only provisioning (create merchant, invite member, create store), board, enter-as-merchant, audit, manual-step capture.

- [`GET /operator/merchants`](/docs/api/control-plane/operator/get-operator-merchants) — List merchants
- [`POST /operator/merchants`](/docs/api/control-plane/operator/post-operator-merchants) — Provision a new merchant (tenant)
- [`POST /operator/merchants/{merchant_id}/members`](/docs/api/control-plane/operator/post-operator-merchants-merchant-id-members) — Invite a member to a merchant (authorize an email)
- [`POST /operator/merchants/{merchant_id}/stores`](/docs/api/control-plane/operator/post-operator-merchants-merchant-id-stores) — Create a store under a merchant
- [`GET /operator/board`](/docs/api/control-plane/operator/get-operator-board) — List all merchants by journey state (the board)
- [`GET /operator/manual-steps`](/docs/api/control-plane/operator/get-operator-manual-steps) — List captured manual steps
- [`POST /operator/manual-steps`](/docs/api/control-plane/operator/post-operator-manual-steps) — Capture a manual step (the Phase B automation backlog)
- [`GET /operator/audit-log`](/docs/api/control-plane/operator/get-operator-audit-log) — Read the operator audit log
- [`PUT /operator/manual-steps/{step_id}/retag`](/docs/api/control-plane/operator/put-operator-manual-steps-step-id-retag) — Reclassify a manual step
- [`POST /operator/manual-steps/bulk-retag`](/docs/api/control-plane/operator/post-operator-manual-steps-bulk-retag) — Reclassify many manual steps at once
- [`GET /operator/timeline-metrics`](/docs/api/control-plane/operator/get-operator-timeline-metrics) — Merchants per engagement stage over time
- [`POST /operator/act-on-behalf`](/docs/api/control-plane/operator/post-operator-act-on-behalf) — Run an operator action as a merchant (audit-logged)
