# info.description
The partner-facing move-commerce API: quote a move, instant-book a real Order, read booking status, and receive durable signed `booking.*` webhooks.

## Authentication
Every request carries a partner API key as an HTTP bearer token: `Authorization: Bearer <pdk_…>`. A key is bound to ONE partner and carries a fixed scope set. A request with no/invalid key is `401`; a key lacking the required scope is `403`. Keys are `live` or `test` (`livemode`): a quote/booking made with a test key never mixes with live data, and a test booking only delivers to test webhook subscriptions.

## Idempotency
POST endpoints that create state (`/move-quotes`, `/bookings`, `/webhooks`) require an `Idempotency-Key` header. Re-sending the SAME key replays the original result (a quote re-emits its token; a booking returns the committed order). Re-using a key with a DIFFERENT body is a `409` conflict — never a silent overwrite.

## Errors
Errors return the Stripe-shaped envelope `{ "error": { "code", "message", "param"?, "requestId"? } }`. Branch on the HTTP status and `error.code` (stable across versions), not the message text.

## Rate limits
Requests are rate-limited per key. A burst over the ceiling returns `429` with a `Retry-After` header (seconds). The limiter is cross-instance; under a backing-store outage it degrades to a per-isolate limiter (never fail-open).

## Webhooks
Subscribe to `booking.*` events. Each delivery is a POST to your URL with a `Spear-Signature` header = `t=<unix>,v1=<hex-hmac>` over the raw body, keyed by `HMAC-SHA256(<your endpoint secret>, "<t>.<rawBody>")`. Verify it (constant-time) and check `t` freshness. During a secret rotation both the new and previous secret sign within the overlap window (`v1` may carry two values) so you can swap verifiers with no dropped deliveries. Delivery is AT-LEAST-ONCE — dedupe on the event `id` (stable across redrives). A persistently-failing endpoint auto-disables; re-enable it after fixing.

## Embed (resident-facing browser surface)
Beyond this server-to-server API, Spear hosts a resident-facing embed (ADR-0301). Your BACKEND mints a short-lived, origin-bound BROWSER token via `POST /embed-sessions` (your `pdk_` key + the `partner:embed:create` scope) and injects it into your own UI; that token — NOT the `pdk_` secret — authorizes the browser `/embed/move-quotes`, `/embed/bookings`, and `/embed/bookings/{bookingId}` endpoints (the `embedSession` bearer scheme). Each browser session is per-resident (a `pes_` session id): a quote/booking is bound to its minting session + surface, and booking-status is authorized on the session (another session’s id returns `404`). The browser endpoints answer CORS + an `OPTIONS` preflight; Origin/CORS is CSRF/defense-in-depth, NOT the authorization (the verified token + the origin binding are). Alternatively, iframe Spear’s OWN hosted widget at `/embed/{tenantSlug}/{partnerId}` (it server-mints its own token); that page is frameable by partner sites via a scoped CSP `frame-ancestors` (the app-wide `X-Frame-Options: DENY` is lifted only there).

# paths./api/partner/v1/move-quotes.post.description
Rate a move from origin to destination ZIP. Returns a price-locked quote with a `quoteToken` (re-validated at book time) when the lane is serviceable, or `{ "serviceable": false }` when it is not. Requires the `partner:quote` scope + an `Idempotency-Key`.

# paths./api/partner/v1/move-quotes.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/move-quotes.post.responses.200.description
The idempotent replay of an already-issued quote.

# paths./api/partner/v1/move-quotes.post.responses.201.description
A new price-locked quote (or a not-serviceable result).

# paths./api/partner/v1/move-quotes.post.responses.403.description
The key lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/move-quotes.post.responses.409.description
The Idempotency-Key was used for a different request.

# paths./api/partner/v1/bookings.post.description
Commit a real Order at the locked basis of a `quoteToken`. Requires the `partner:booking:create` scope + an `Idempotency-Key`. The booked price IS the quoted price; a quote books at most once.

# paths./api/partner/v1/bookings.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/bookings.post.responses.200.description
The idempotent replay of an already-committed booking.

# paths./api/partner/v1/bookings.post.responses.403.description
The key lacks `partner:booking:create`, or the partner is not enabled.

# paths./api/partner/v1/bookings.post.responses.404.description
The quote does not exist for this partner.

# paths./api/partner/v1/bookings.post.responses.409.description
The quote already booked, the price-lock expired, the key was reused for a different quote, or the quote mode (test/live) differs from the booking key.

# paths./api/partner/v1/bookings/{bookingId}.get.description
Read the status of one of your own bookings. Requires `partner:booking:read`. An unknown, malformed, or another partner’s id all return the same `404` (no enumeration oracle).

# paths./api/partner/v1/bookings/{bookingId}.get.parameters[].description
Booking id (`pbk_` + 24 lowercase hex). A value not matching the pattern returns the uniform `404`, NOT a `4xx` validation error.

# paths./api/partner/v1/referrals.get.description
Reconcile your referral fees + payout status (Stage 3 / ADR-0302). One entry per committed booking that earned a referral, newest-booked first, keyset-paginated. Requires `partner:referrals:read` (pdk-only — never an embed session). The response carries only facts you own (booking / order / quote / bookedAt, the fee, the lifecycle status, the statement / payout handles); never internal tenant / customer / GL detail.

# paths./api/partner/v1/referrals.get.parameters[].description
An opaque keyset cursor from a prior page’s `next_cursor`. A malformed cursor returns `400`.

# paths./api/partner/v1/webhooks.post.description
Register an endpoint for `booking.*` events. Requires `partner:webhooks:manage` + an `Idempotency-Key`. The signing secret is returned ONCE here — store it; it is never returned again.

# paths./api/partner/v1/webhooks.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/webhooks.post.responses.201.description
The subscription was created (carries the one-time `secret`).

# paths./api/partner/v1/webhooks.post.responses.409.description
The Idempotency-Key was used for a different subscription.

# paths./api/partner/v1/webhooks.post.responses.422.description
Invalid body (bad url / scope / unknown event type).

# paths./api/partner/v1/webhooks.get.description
List your subscriptions (secrets are never returned). Requires `partner:webhooks:manage`.

# paths./api/partner/v1/webhooks/{subscriptionId}.get.parameters[].description
Subscription id (`pwh_…`). Another partner’s / unknown id returns `404`.

# paths./api/partner/v1/webhooks/{subscriptionId}/rotate-secret.post.summary
Rotate a webhook signing secret (with overlap).

# paths./api/partner/v1/webhooks/{subscriptionId}/rotate-secret.post.description
Bump the signing secret; the previous secret stays valid for delivery during the overlap window so you can swap verifiers with no dropped deliveries. Returns the NEW secret once.

# paths./api/partner/v1/webhooks/{subscriptionId}/rotate-secret.post.parameters[].description
Subscription id (`pwh_…`). Another partner’s / unknown id returns `404`.

# paths./api/partner/v1/webhooks/{subscriptionId}/rotate-secret.post.responses.200.description
The rotated subscription (carries the new one-time `secret`).

# paths./api/partner/v1/webhooks/{subscriptionId}/disable.post.parameters[].description
Subscription id (`pwh_…`). Another partner’s / unknown id returns `404`.

# paths./api/partner/v1/webhooks/{subscriptionId}/enable.post.description
Re-enable a disabled (or auto-disabled) endpoint and reset its failure counter.

# paths./api/partner/v1/webhooks/{subscriptionId}/enable.post.parameters[].description
Subscription id (`pwh_…`). Another partner’s / unknown id returns `404`.

# paths./api/partner/v1/embed-sessions.post.summary
Mint a browser embed-session token (headless).

# paths./api/partner/v1/embed-sessions.post.description
Your BACKEND mints a short-lived, origin-bound browser token to inject into your own UI. Requires `partner:embed:create`. The `origin` MUST be one of your registered `allowedOrigins`; `scopes` (optional) is intersected with the embed-eligible set {partner:quote, partner:booking:create, partner:booking:read} AND your key. NO Idempotency-Key — each mint is a fresh per-resident session.

# paths./api/partner/v1/embed-sessions.post.responses.403.description
The key lacks `partner:embed:create`, or the partner is not enabled.

# paths./api/partner/v1/embed-sessions.post.responses.422.description
The origin is not a registered allowedOrigin, or the requested scopes are ineligible/empty.

# paths./api/partner/v1/embed/move-quotes.post.summary
Quote a move from resident facts (browser).

# paths./api/partner/v1/embed/move-quotes.post.description
The browser quote endpoint: a resident submits move facts (bedroom count + optional inventory), mapped server-side to a price-locked quote. Authorized by an `embedSession` token (NOT a pdk_ key); answers CORS for the bound origin (preflight via OPTIONS). Requires the `partner:quote` embed scope + an `Idempotency-Key` (keyed on the resident facts).

# paths./api/partner/v1/embed/move-quotes.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/embed/move-quotes.post.responses.201.description
A new price-locked quote (or a not-serviceable result).

# paths./api/partner/v1/embed/move-quotes.post.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/move-quotes.post.responses.409.description
The Idempotency-Key was used for different facts.

# paths./api/partner/v1/embed/move-quotes.post.responses.422.description
Invalid body (bad ZIP / resident facts).

# paths./api/partner/v1/embed/bookings.post.description
The browser instant-book endpoint: commit a real Order at the locked basis of a `quoteToken`. Authorized by an `embedSession` token; the quote MUST have been minted by the SAME session (a cross-session / cross-surface quote fails closed as not-found). Requires the `partner:booking:create` embed scope + an `Idempotency-Key`. Subject to a per-(tenant, partner) monthly quota.

# paths./api/partner/v1/embed/bookings.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/embed/bookings.post.responses.403.description
The session lacks `partner:booking:create`, or the partner is not enabled.

# paths./api/partner/v1/embed/bookings.post.responses.404.description
The quote does not exist for this session.

# paths./api/partner/v1/embed/bookings.post.responses.409.description
The quote already booked, the price-lock expired, or the key was reused for a different quote.

# paths./api/partner/v1/embed/bookings.post.responses.429.description
Rate limited, or the monthly quota is reached.

# paths./api/partner/v1/embed/sign.post.summary
Sign the binding estimate (browser, consumer e-sign).

# paths./api/partner/v1/embed/sign.post.description
Self-Serve Move Commerce Phase 4 (ADR-0336). Record the customer’s electronic signature on the binding estimate for a `quoteToken` BEFORE booking, so a binding self-serve quote completes the FMCSA binding-estimate ceremony in-widget. Authorized by an `embedSession` token; the quote MUST have been minted by the SAME session (cross-session/cross-surface fails closed as not-found). The signer is named by a pseudonymous, tenant-derived id (no raw PII); device IP/UA are digested into the evidence hash, never stored cleartext. Send the SAME `Idempotency-Key` on the following `POST /embed/bookings` so the booking is bound to this signature. Requires `partner:booking:create`.

# paths./api/partner/v1/embed/sign.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/embed/sign.post.responses.403.description
The session lacks `partner:booking:create`, or the partner is not enabled.

# paths./api/partner/v1/embed/sign.post.responses.404.description
The quote does not exist for this session.

# paths./api/partner/v1/embed/sign.post.responses.422.description
Invalid body / malformed quoteToken / missing affirmation.

# paths./api/partner/v1/embed/sign.post.responses.429.description
Rate limited, or the monthly quota is reached.

# paths./api/partner/v1/embed/converse.post.summary
Dispatch a conversational tool call (browser / voice model).

# paths./api/partner/v1/embed/converse.post.description
Self-Serve Move Commerce Phase 6 (ADR-0338 D-2). The CLOSED server-side tool-dispatch the realtime voice client (client-side tool calls) + the chat path both route through. Send `{ tool, args }` to execute ONE tool from the closed set (`quote`, `checkCapacity`, `startCapture`, `confirmCapture`, `prepareSign`, `book`, `handoff`). The tool NAME + ARGS are UNTRUSTED; the channel principal is resolved SERVER-side (a transcript can never assert authority); the spine composers are server-authoritative. A tool refusal (unknown tool / bad args / scope-denied / a composer `no`) returns `200` with `{ ok: false, code }` — a structured refusal, not an HTTP error. `{ messages }` (consumer chat, Conversational Rail Varsity Phase 4) streams the rail model SERVER-side over the SAME closed dispatch tools, and is GATED behind `SPEAR_CONSUMER_TEXT_ENABLED` (default OFF → `503`); its guarded (digit-free) prose is recorded SEALED under the per-session conversation crypto-shred subject (RTBF-reachable, never plaintext). Requires `partner:quote` (the per-tool scope — `book` needs `partner:booking:create` — is enforced in the dispatch).

# paths./api/partner/v1/embed/converse.post.responses.200.description
The tool result — `{ tool, ok, data }` on success or `{ tool, ok:false, code }`.

# paths./api/partner/v1/embed/converse.post.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/converse.post.responses.503.description
Consumer chat is dark-shipped (SPEAR_CONSUMER_TEXT_ENABLED off) or otherwise unavailable (fail-closed).

# paths./api/partner/v1/embed/conversation/token.post.summary
Mint an anonymous consumer conversation session (browser).

# paths./api/partner/v1/embed/conversation/token.post.description
Conversational Rail Varsity Phase 4 (ADR-0338 D-4). The ANONYMOUS, POST-only faucet that issues the FIRST embed-session token for a consumer text/voice booking chat (there is NO page-render mint). Unauthenticated by design — it is fronted by a HARD gate: the `SPEAR_CONSUMER_TEXT_ENABLED` / `_VOICE_ENABLED` dark-ship flags (both off → `503`), a per-IP flood shed, a CAPTCHA/abuse gate that fails CLOSED when unconfigured (`503`) and refuses a bad token (`403`), per-IP + per-tenant AGGREGATE mint ceilings, and a uniform `404` for any unknown / disabled / non-`direct` channel (no enumeration oracle). Issues a `surface:direct` portal-guest session with conversational scopes; the raw session id rides inside the signed token.

# paths./api/partner/v1/embed/conversation/token.post.responses.201.description
A minted consumer conversation session token.

# paths./api/partner/v1/embed/conversation/token.post.responses.404.description
Unknown / disabled / non-direct channel (uniform — no enumeration oracle).

# paths./api/partner/v1/embed/conversation/token.post.responses.422.description
Invalid body (missing tenantSlug / partnerId).

# paths./api/partner/v1/embed/conversation/token.post.responses.429.description
Rate limited (per-IP or per-tenant mint ceiling).

# paths./api/partner/v1/embed/conversation/token.post.responses.503.description
Consumer conversation is dark-shipped (flags off) or the abuse gate is unconfigured (fail-closed).

# paths./api/partner/v1/embed/voice/token.post.summary
Mint a realtime voice session token (browser).

# paths./api/partner/v1/embed/voice/token.post.description
Self-Serve Move Commerce Phase 6 (ADR-0338 D-1/D-4). Mint a short-lived realtime token the browser connects to the voice gateway with (the raw gateway key never reaches the client). FAIL-CLOSED (`503`) until a gateway that binds a HARD per-session-token spend ceiling AT MINT is wired (the SHIP PRECONDITION) — no token is minted until then, so a leaked token cannot drain the project budget. The per-session rate limit is the bounded mint faucet. Requires `partner:quote`.

# paths./api/partner/v1/embed/voice/token.post.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/voice/token.post.responses.503.description
Realtime voice is not available (fail-closed).

# paths./api/partner/v1/embed/bookings/{bookingId}.get.summary
Read a booking by id (browser, session-scoped).

# paths./api/partner/v1/embed/bookings/{bookingId}.get.description
Read the status of a booking made by THIS embed session. Authorized by an `embedSession` token; another session’s / unknown / malformed id all return the same `404` (no oracle). Requires `partner:booking:read`.

# paths./api/partner/v1/embed/bookings/{bookingId}.get.parameters[].description
Booking id (`pbk_` + 24 lowercase hex). A non-matching value returns the uniform `404`.

# paths./api/partner/v1/embed/availability.get.summary
List available move dates (browser, self-serve capacity).

# paths./api/partner/v1/embed/availability.get.description
Self-Serve Move Commerce Phase 3 (ADR-0334/0335). Returns the upcoming days that have OPEN capacity for the tenant — the source for a `direct` widget date picker that shows only available days. Authorized by an `embedSession` token; the tenant is SERVER-derived from the session. A tenant with no self-serve capacity ceiling returns `[]` (fail closed — no unbounded calendar). Requires `partner:quote`.

# paths./api/partner/v1/embed/availability.get.parameters[].description
Start date `YYYY-MM-DD` (defaults to today).

# paths./api/partner/v1/embed/survey.post.summary
Upload a walkthrough video to sharpen the quote (browser).

# paths./api/partner/v1/embed/survey.post.description
Self-Serve Move Commerce Phase 5 (ADR-0337). Upload a short pre-book walkthrough video (multipart/form-data: `video` + `quoteToken` + `consent`) to open an AI capture that sharpens the quote. Authorized by an `embedSession` token; the walkthrough is bound to the quote the SAME session owns (the prospect ref is server-derived — a cross-session or already-precision quoteToken is refused). Per-session + per-IP upload count caps + a per-session byte budget bound abuse; consent is attested and the video is stored under an erasable prospect data-subject. Poll the `GET` for the reconcile status, then `POST /embed/survey/requote`. Requires `partner:quote` + an `Idempotency-Key`.

# paths./api/partner/v1/embed/survey.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/embed/survey.post.requestBody.content.multipart/form-data.schema.properties.quoteToken.description
The price-lock token of the quote this session owns.

# paths./api/partner/v1/embed/survey.post.requestBody.content.multipart/form-data.schema.properties.consent.description
The capture consent attestation ("true").

# paths./api/partner/v1/embed/survey.post.responses.201.description
The walkthrough was stored and the capture opened.

# paths./api/partner/v1/embed/survey.post.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/survey.post.responses.404.description
The quote does not exist for this session.

# paths./api/partner/v1/embed/survey.post.responses.409.description
The quote is already a precision re-quote — upload against your original quote.

# paths./api/partner/v1/embed/survey.post.responses.422.description
Invalid multipart body (missing video / quoteToken).

# paths./api/partner/v1/embed/survey.post.responses.429.description
Rate limited, or the upload count / byte budget is exceeded.

# paths./api/partner/v1/embed/survey.get.summary
Read the walkthrough capture status (browser).

# paths./api/partner/v1/embed/survey.get.description
Poll the reconcile status of the walkthrough for the quote this session owns: `none` (no upload) → `open` (analyzing) → `reconciled` (ready to re-quote) → `confirmed`. Authorized by an `embedSession` token. Requires `partner:quote`.

# paths./api/partner/v1/embed/survey.get.parameters[].description
The price-lock token of the quote this session owns.

# paths./api/partner/v1/embed/survey.get.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/survey.get.responses.404.description
The quote does not exist for this session.

# paths./api/partner/v1/embed/survey.delete.summary
Erase the walkthrough (on-request prospect RTBF) (browser).

# paths./api/partner/v1/embed/survey.delete.description
Self-Serve Move Commerce (ADR-0337 / VV5). A never-booked resident erases the walkthrough they uploaded, on request, before the retention floor reaps it. Authorized by an `embedSession` token; the prospect data-subject is derived from the quote this session owns (a sibling session cannot erase another’s). Routes through the crypto-shred erasure chokepoint (the subject key is destroyed + the erasure recorded) and hard-deletes the video bytes. Idempotent. Requires `partner:quote`.

# paths./api/partner/v1/embed/survey.delete.parameters[].description
The price-lock token of the quote this session owns.

# paths./api/partner/v1/embed/survey.delete.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/survey.delete.responses.404.description
The quote does not exist for this session.

# paths./api/partner/v1/embed/survey/requote.post.summary
Re-quote from the confirmed walkthrough (browser, precision).

# paths./api/partner/v1/embed/survey/requote.post.description
Self-Serve Move Commerce Phase 5 (ADR-0337 D-5). Confirm the walkthrough and re-price the move from its reconciled inventory, replacing the coarse facts quote with a precision one. Authorized by an `embedSession` token; re-verifies the session OWNS the quote (the consumer never supplies a rate/total). Returns a fresh price-lock token (linked to the walkthrough) to carry to sign/book. Requires `partner:quote` + an `Idempotency-Key`.

# paths./api/partner/v1/embed/survey/requote.post.parameters[].description
A unique key per logical request; re-sending replays the original result.

# paths./api/partner/v1/embed/survey/requote.post.requestBody.content.application/json.schema.properties.quoteToken.description
The price-lock token of the quote this session owns.

# paths./api/partner/v1/embed/survey/requote.post.responses.403.description
The session lacks `partner:quote`, or the partner is not enabled.

# paths./api/partner/v1/embed/survey/requote.post.responses.404.description
The quote does not exist for this session.

# paths./api/partner/v1/embed/survey/requote.post.responses.409.description
The walkthrough is not reconciled yet, or has no priceable lines.

# webhooks.booking.committed.post.summary
A partner booking was committed (delivered to your subscription URL).

# webhooks.booking.committed.post.description
Spear POSTs this signed event to each enabled subscription whose scopes include the event type. Verify the `Spear-Signature` header before trusting the body. Delivery is at-least-once; dedupe on `id`.

# webhooks.referral.paid.post.summary
A referral payout settled to your connected account (Stage 3 / ADR-0302).

# webhooks.referral.paid.post.description
Spear POSTs this signed event when a referral payout SETTLES. The body is a ReferralPayout (statement / payout / amount / provider reference), never a raw GL posting. Verify `Spear-Signature`; delivery is at-least-once; dedupe on `id`.

# components.securitySchemes.pdkKey.description
A partner API key (`pdk_…`). Bound to one partner; carries a fixed scope set from: partner:quote, partner:booking:create, partner:booking:read, partner:webhooks:manage, partner:embed:create, partner:referrals:read.

# components.securitySchemes.embedSession.description
A short-lived BROWSER embed-session token (portal-guest provenance) — minted via POST /embed-sessions (headless) or by the hosted widget page. Carries a per-resident session + a closed embed-scope subset; NOT a pdk_ key. Authorizes the /embed/* browser endpoints only.

# components.schemas.MoveQuoteRequest.properties.coverage.description
Optional valuation coverage election. Omit (or "released-value") for the statutory default — no premium. A "full-value" election prices a Full-Value-Protection premium FROM THE TENANT TARIFF (you supply only the election; the FVP rate is server-side, never caller-supplied) and requires declaredValue; the premium appears as a `valuation` line item. Omitting coverage is byte-identical to the prior quote.

# components.schemas.MoveQuoteRequest.properties.declaredValue.description
The shipment value to insure — REQUIRED when coverage is "full-value". The FVP premium is the tenant tariff rate applied to this value (server-priced); a currency that disagrees with the tariff is rejected.

# components.schemas.MoveQuoteResult.description
A price-locked quote, or a not-serviceable result.

# components.schemas.MoveQuote.properties.quoteToken.description
The price-lock token to pass to POST /bookings; re-validated + expires.

# components.schemas.MoveQuote.properties.lineItems.description
The itemized priced lines making up the total (e.g. linehaul, fuel, and — for a full-value coverage election — a `valuation` Full-Value-Protection premium priced from the tenant tariff).

# components.schemas.BookingRequest.properties.quoteToken.description
A price-lock token from POST /move-quotes.

# components.schemas.EmbedSessionMintRequest.properties.origin.description
An https origin from your registered allowedOrigins (the token is bound to it).

# components.schemas.EmbedSessionMintRequest.properties.scopes.description
Optional. Defaults to every embed-eligible scope your key holds; intersected with the eligible set + your key.

# components.schemas.EmbedSession.properties.token.description
The browser embed-session bearer token (short-lived). Present as `Authorization: Bearer <token>` on /embed/* calls.

# components.schemas.ResidentMoveQuoteRequest.properties.facts.description
Resident move facts, mapped server-side to rated cargo lines.

# components.schemas.ResidentMoveQuoteRequest.properties.coverage.description
Optional valuation coverage election. Omit (or "released-value") for the statutory default — no premium. A "full-value" election prices a Full-Value-Protection premium FROM THE TENANT TARIFF (the resident supplies only the election; the FVP rate is server-side) and requires declaredValue; the premium appears as a `valuation` line item.

# components.schemas.ResidentMoveQuoteRequest.properties.declaredValue.description
The shipment value to insure — REQUIRED when coverage is "full-value". The FVP premium is the tenant tariff rate applied to this value (server-priced).

# components.schemas.WebhookSubscriptionRequest.properties.url.description
An https URL with no embedded credentials.

# components.schemas.WebhookSubscription.properties.disabledAt.description
ISO instant the endpoint was (auto-)disabled.

# components.schemas.CreatedWebhookSubscription.allOf[].properties.secret.description
The signing secret — returned ONCE (on create / rotate); never again.

# components.schemas.Referral.description
A partner referral fee + its lifecycle status (Stage 3 / ADR-0302). Partner-safe — never carries tenant / customer / payee / GL-account / ledger-id detail.

# components.schemas.Referral.properties.status.description
accrued_pending = earned, awaiting a statement; eligible = in an approved/prepared statement; paid = the payout settled; returned = the payout reversed.

# components.schemas.Referral.properties.providerReference.description
The provider transfer reference (e.g. `tr_…`), once paid.

# components.schemas.ReferralList.properties.next_cursor.description
Pass as `?cursor=` to fetch the next page (present iff `has_more`).

# components.schemas.BookingWebhookEvent.properties.id.description
Stable event id — dedupe on this (delivery is at-least-once).

# components.schemas.ReferralPayout.description
A settled referral payout (Stage 3 / ADR-0302). Partner-safe — statement / payout handles + the fee + the provider reference, never internal tenant / payee / GL detail.

# components.schemas.ReferralPayout.properties.providerReference.description
The provider transfer reference (e.g. `tr_…`).

# components.schemas.ReferralPaidWebhookEvent.properties.id.description
Stable event id — dedupe on this (delivery is at-least-once).