SNHP Billing API

The billing API from SNHP — 22 operation(s) for billing.

Operations 22

POST /v1/billing/checkout_session Checkout Session #
POST /v1/billing/agentic_topup Agentic Topup #
POST /v1/billing/webhook Webhook #
GET /v1/billing/balance Balance #
POST /v1/advice/session Open Advice Session #
POST /v1/advice/move Advice Move #
POST /v1/advice/bundle Advice Bundle Move #
POST /v1/advice/close Close Advice Session #
POST /v1/keys/rotate Rotate Key #
POST /v1/advice/request Advice Request #
GET /v1/store/catalog Store Catalog #
GET /v1/store/notary_pubkey Store Notary Pubkey #
POST /v1/fetch Store Fetch #
POST /v1/store/request Store Request #
GET /v1/store/request/{request_id} Store Request Status #
GET /v1/store/requests Store Requests #
GET /v1/store/observatory Store Observatory #
GET /v1/store/my_requests Store My Requests #
POST /v1/store/park Store Park #
GET /v1/store/parcel/{ticket} Store Retrieve #
POST /v1/memory/save Memory Save #
GET /v1/memory/parcel/{ticket} Memory Load #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/snhp-dev-billing-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

snhp-dev-billing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Game Theory Layer for AI Agents Billing API
  description: 'Start with ONE tool: POST /v1/negotiate/turn — plain-dollar price negotiation (your walk-away + the other side''s offers in dollars -> the counter to send, a ready-to-send message, accept/walk advice).'
  version: 0.1.0
tags:
- name: Billing
paths:
  /v1/billing/checkout_session:
    post:
      tags:
      - Billing
      summary: Checkout Session
      operationId: checkout_session_v1_billing_checkout_session_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckoutIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/billing/agentic_topup:
    post:
      tags:
      - Billing
      summary: Agentic Topup
      description: 'Fund the wallet by redeeming an agent-carried Shared Payment Token — no

        human at a hosted Checkout URL. Same counter fee (5% + 30¢) as every top-up;

        the fee is printed in the response as fee_cents.


        PREVIEW: Stripe''s SPT flow is a versioned preview and needs preview

        services-terms acceptance + a US legal entity + a rotated key before live

        use (see vend/AGENTIC_PAYMENTS.md). Test mode works with the monkeypatched

        Stripe layer / an ordinary sk_test_* + a test-helper token.'
      operationId: agentic_topup_v1_billing_agentic_topup_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgenticTopupIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/billing/webhook:
    post:
      tags:
      - Billing
      summary: Webhook
      operationId: webhook_v1_billing_webhook_post
      parameters:
      - name: stripe-signature
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Stripe-Signature
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/billing/balance:
    get:
      tags:
      - Billing
      summary: Balance
      description: 'The ONE wallet, in millicents (1000 per cent), with the starter grant

        and own-money buckets both visible — the balance no longer lies about the

        50¢ (STORE.md §6). The key travels in the X-API-Key header, never a query

        param (a secret must not land in access logs or proxies).


        `guaranteed_calls_remaining` (roadmap: fund the pipeline before the 402) is a

        CONSERVATIVE floor per registered commodity slot: total // max_price_millicents

        — how many calls the wallet can afford if EVERY call cost the published

        ceiling. It is a floor because calls settle at wholesale passthrough (usually

        well under the cap), so the real number is ≥ this. Stateless and mechanical:

        no trailing average, no state, no telemetry read. An UNAVAILABLE slot (no

        healthy backend) reports 0 — you are guaranteed no calls it cannot serve.'
      operationId: balance_v1_billing_balance_get
      parameters:
      - name: X-API-Key
        in: header
        required: true
        schema:
          type: string
          title: X-Api-Key
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/advice/session:
    post:
      tags:
      - Billing
      summary: Open Advice Session
      description: 'Open a PAID negotiation session: $2 once covers every move of this

        negotiation (cap 10 moves, 7 days). Category-tuned, deterministic,

        receipted. The free generic tool is POST /v1/negotiate/turn — pay for

        the tuned, auditable, replayable version. Pass their_offers to get the

        first move back with the session.'
      operationId: open_advice_session_v1_advice_session_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionOpenIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/advice/move:
    post:
      tags:
      - Billing
      summary: Advice Move
      description: 'A move inside your paid session — no additional charge. Pass the

        FULL offer history each time, oldest first.'
      operationId: advice_move_v1_advice_move_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionMoveIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/advice/bundle:
    post:
      tags:
      - Billing
      summary: Advice Bundle Move
      description: 'A MULTI-ISSUE move inside your paid session — the logrolling tier the

        free tool lacks. No additional charge. Returns the recommended package

        (guaranteed to clear your stated BATNA), trade logic, inferred

        counterparty priorities, acceptance probability, and the receipt.'
      operationId: advice_bundle_move_v1_advice_bundle_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BundleMoveIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/advice/close:
    post:
      tags:
      - Billing
      summary: Close Advice Session
      description: 'Mark the negotiation finished. Optional but good hygiene — it

        timestamps the outcome, which calibrates the category priors. Returns the

        `closed` flag AND a signed session-summary receipt (GAUNTLET #4: the close

        used to emit nothing auditable) — moves count, total charged, and the

        per-move context_hashes — for the customer to hand a principal. An unknown

        session or key mismatch → 404 (indistinguishable, so a session id can''t be

        probed with someone else''s key).'
      operationId: close_advice_session_v1_advice_close_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionCloseIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/keys/rotate:
    post:
      tags:
      - Billing
      summary: Rotate Key
      description: 'Rotate your API key: a replacement is issued, the full credit

        balance carries over, and the old key is invalidated IMMEDIATELY (no

        grace period — possession of the key is the authorization, and a

        compromised key must die at once). Save the new key: keys are shown

        once and cannot be recovered, only rotated. Lost your key entirely?

        Email the contact address you registered with from that same address —

        recovery is a manual, human-verified process by design.'
      operationId: rotate_key_v1_keys_rotate_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RotateIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/advice/request:
    post:
      tags:
      - Billing
      summary: Advice Request
      description: 'The null-query intake: ask for anything the machine doesn''t stock.

        Free. Size-capped, stored as data, never rendered raw. Unmet demand

        decides what gets stocked next. Legacy name for the same intake as

        POST /v1/store/request — one box, two doors (GAUNTLET #5): every

        filing gets a request_id you can check.


        Pass `watch: true` WITH an api_key to flag the ask for a heads-up on a

        status flip (poll GET /v1/store/my_requests to see it — the notify is

        poll-based, no push); an anonymous watch is ignored. The chosen flag is

        echoed back as `watch`.'
      operationId: advice_request_v1_advice_request_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/store/catalog:
    get:
      tags:
      - Billing
      summary: Store Catalog
      description: 'THE STORE''s shelf: the commodity slots (tier, admission cap,

        predicate id, request doc, serving-backend ids), the anchor SKUs, and the

        two published pricing facts — wholesale-passthrough cost basis on every

        receipt plus the counter fee on top-ups. No key material ever appears

        here.'
      operationId: store_catalog_v1_store_catalog_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /v1/store/notary_pubkey:
    get:
      tags:
      - Billing
      summary: Store Notary Pubkey
      description: 'The receipt-signing notary''s PUBLIC key, at a stable path so a verifier

        can PIN it OUT-OF-BAND (not just trust the pubkey embedded in a receipt) and

        confirm it matches the receipt''s pubkey_fingerprint. Returns {pubkey_pem,

        fingerprint, key_source}. This is the STORE receipt notary (vend.receipt_

        signing / NOTARY_KEY_PEM) — DISTINCT from /v1/keys/trust_anchor (first-strike

        CA) and /v1/keys/settlement_notary (AP2 mandates), which are different keys.


        key_source is VISIBLE: with ''ephemeral'' a signature proves only signer-

        consistency within one server lifetime; a production notary pins a persistent

        key (''env'', from NOTARY_KEY_PEM). Never returns private material.'
      operationId: store_notary_pubkey_v1_store_notary_pubkey_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /v1/fetch:
    post:
      tags:
      - Billing
      summary: Store Fetch
      description: 'Fetch/extract one page → markdown, paid from your wallet at wholesale

        passthrough. Settlement-on-delivery: charged ONLY on non-empty markdown.


        Pass your key in an `Authorization: Bearer gt_*` or `X-API-Key` header

        (RECOMMENDED — that reaches the 600/min keyed rate-limit lane; a body-only

        key falls to the 60/min per-IP floor because the limiter never parses

        bodies) or in the JSON body `api_key` (backcompat). The header wins if both

        are present.


        A backend or predicate failure is a NORMAL uncharged outcome — 200 with the

        canonical envelope {ok: false, charged: false, reason: ,

        code: } — because you cannot pay for nothing; that asymmetry is

        the product surface, not an HTTP error. `code` is one of unknown_slot,

        slot_unavailable, insufficient_balance, all_backends_failed, predicate_failed;

        a delivered-but-failed call may also carry backends_tried [{id, reason}],

        backends_untried, backend_id, and a retry_hint. One client code path reads

        `charged`/`code` for every outcome. (Legacy keys like `error` survive as

        aliases.) Insufficient balance → 402; a missing or unknown api_key → 401.'
      operationId: store_fetch_v1_fetch_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FetchIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/store/request:
    post:
      tags:
      - Billing
      summary: Store Request
      description: 'File a request for a capability the store doesn''t stock. Free, keyless

        OK. Returns {request_id, status, watch, check} — the demand loop now hands

        back something to return FOR (GAUNTLET #5). Size-capped, stored as data,

        never rendered raw. Pass `watch: true` WITH an api_key to flag the ask for a

        heads-up on a status flip (poll GET /v1/store/my_requests — poll-based, no

        push); an anonymous watch is ignored, and the chosen flag is echoed back.'
      operationId: store_request_v1_store_request_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StoreRequestIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/store/request/{request_id}:
    get:
      tags:
      - Billing
      summary: Store Request Status
      description: 'Check a filed request by id: {request_id, status, status_note, filed_at,

        door, text}. `status` is ''logged'' until the shelf-owner acts, then

        status_note carries the reason-to-return. Unknown id → 404. No key material;

        the text is display-truncated and remains untrusted data.'
      operationId: store_request_status_v1_store_request__request_id__get
      parameters:
      - name: request_id
        in: path
        required: true
        schema:
          type: string
          title: Request Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/store/requests:
    get:
      tags:
      - Billing
      summary: Store Requests
      description: 'The public demand tally (GAUNTLET #5): {total, distinct, recent[],

        requests[]}. `requests` is distinct asks with EXACT-MATCH duplicate counts

        (whitespace/case folded, no fuzzy classification — mechanical, no LLM),

        most-asked first. No key material; text display-truncated.'
      operationId: store_requests_v1_store_requests_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /v1/store/observatory:
    get:
      tags:
      - Billing
      summary: Store Observatory
      description: 'The public, citable observatory (vend.observatory.snapshot): per-slot

        call volumes and the MECHANICAL tally of what agents ask for that nobody

        sells yet. Every number is a count, a sum, or an exact-match group — no

        interpretation, no LLM. Aggregate + PSEUDONYMOUS: wallets appear only as

        counts of a keyed pseudonym (repeat_key), never a raw api_key, so NO key

        material can leak. Pure read, no auth. The demand-loop citation asset: what

        the shelf is missing, straight from the raw records.'
      operationId: store_observatory_v1_store_observatory_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /v1/store/my_requests:
    get:
      tags:
      - Billing
      summary: Store My Requests
      description: 'Your OWN filings (roadmap: a voter comes back a reachable customer), keyed

        to YOUR api_key — the private counterpart to the public GET /v1/store/requests

        tally. Carry the key in `Authorization: Bearer gt_*` or `X-API-Key`, never a

        query param (a secret must not land in access logs). A missing or unknown key

        → 401. Returns {requests: [{request_id, filed_at, text, status, status_note,

        status_ts, watch, same_ask_count}]}, newest first — text display-truncated,

        still untrusted data; no key material and no repeat_key on the surface. Only

        rows attributable to this key (via the keyed pseudonym, never a raw key match)

        are returned, so one key can never read another''s filings.'
      operationId: store_my_requests_v1_store_my_requests_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /v1/store/park:
    post:
      tags:
      - Billing
      summary: Store Park
      description: 'Park an ENCRYPTED blob, get a claim ticket (blind locker, §2c). Charged a

        thin flat park fee ONLY on durable store; an empty/oversize/unencodable blob

        is uncharged. Key via `Authorization: Bearer`/`X-API-Key` (header wins) or

        body `api_key`. The receipt''s content_hash is over YOUR ciphertext, so you

        can prove what you stored without the store ever seeing plaintext.'
      operationId: store_park_v1_store_park_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ParkIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/store/parcel/{ticket}:
    get:
      tags:
      - Billing
      summary: Store Retrieve
      description: 'Retrieve a parked parcel by its claim ticket (blind locker, §2c). Returns

        {ok, blob_b64, size_bytes, expires_at} — the ciphertext you parked, which

        only YOU can decrypt. Key via `Authorization: Bearer`/`X-API-Key`. A wrong

        owner reads as a missing ticket (404). Retrieval is free (the park settled

        it). An expired TTL is 404; a lost at-rest key is 503.'
      operationId: store_retrieve_v1_store_parcel__ticket__get
      parameters:
      - name: ticket
        in: path
        required: true
        schema:
          type: string
          title: Ticket
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/memory/save:
    post:
      tags:
      - Billing
      summary: Memory Save
      description: 'Save persistent memory for your agent across sessions (alias of

        POST /v1/store/park — the blind locker). You encrypt before saving; the store

        holds only ciphertext (blind custody) and signs a receipt over its hash — it

        cannot read your memory. Saving uses your prepaid wallet (a new key''s 50¢

        starter credit covers first saves); loading it back is free. Same handler and

        behavior as /v1/store/park.'
      operationId: memory_save_v1_memory_save_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ParkIn'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/memory/parcel/{ticket}:
    get:
      tags:
      - Billing
      summary: Memory Load
      description: 'Load a memory you saved in an earlier session (alias of

        GET /v1/store/parcel/{ticket}). Returns the ciphertext you saved, which only

        YOU can decrypt; retrieval is free. Same handler and behavior as

        /v1/store/parcel/{ticket}.'
      operationId: memory_load_v1_memory_parcel__ticket__get
      parameters:
      - name: ticket
        in: path
        required: true
        schema:
          type: string
          title: Ticket
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    AgenticTopupIn:
      properties:
        api_key:
          type: string
          title: Api Key
        amount_cents:
          type: integer
          title: Amount Cents
          description: cents of wallet credit to buy (min 200); you pay this + the counter fee (5% + 30¢)
        payment_token:
          type: string
          title: Payment Token
          description: a Stripe Shared Payment Token (spt_…) the agent carries
      type: object
      required:
      - api_key
      - amount_cents
      - payment_token
      title: AgenticTopupIn
    BundleMoveIn:
      properties:
        api_key:
          type: string
          title: Api Key
        session_id:
          type: string
          title: Session Id
        issues:
          items:
            additionalProperties: true
            type: object
          type: array
          title: Issues
        their_offers:
          anyOf:
          - items:
              additionalProperties: true
              type: object
            type: array
          - type: 'null'
          title: Their Offers
        my_priorities:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: My Priorities
        my_batna:
          type: number
          title: My Batna
          default: 0.4
        their_batna_estimate:
          type: number
          title: Their Batna Estimate
          default: 0.4
        cooperation:
          anyOf:
          - type: number
          - type: 'null'
          title: Cooperation
      type: object
      required:
      - api_key
      - session_id
      - issues
      title: BundleMoveIn
    CheckoutIn:
      properties:
        api_key:
          type: string
          title: Api Key
        pack:
          anyOf:
          - type: string
          - type: 'null'
          title: Pack
          description: small ($10.80) | medium ($52.80) | large ($210.30)
        amount_cents:
          anyOf:
          - type: integer
          - type: 'null'
          title: Amount Cents
          description: 'custom top-up: cents of wallet credit (min 200); you pay this + the counter fee (5% + 30¢)'
        success_url:
          type: string
          title: Success Url
          default: https://snhp.dev/paid
        cancel_url:
          type: string
          title: Cancel Url
          default: https://snhp.dev/cancel
      type: object
      required:
      - api_key
      title: CheckoutIn
    SessionMoveIn:
      properties:
        api_key:
          type: string
          title: Api Key
        session_id:
          type: string
          title: Session Id
        their_offers:
          items:
            type: number
          type: array
          title: Their Offers
        my_offers:
          anyOf:
          - items:
              type: number
            type: array
          - type: 'null'
          title: My Offers
        rounds_left:
          anyOf:
          - type: integer
            minimum: 1.0
          - type: 'null'
          title: Rounds Left
      type: object
      required:
      - api_key
      - session_id
      - their_offers
      title: SessionMoveIn
    SessionCloseIn:
      properties:
        api_key:
          type: string
          title: Api Key
        session_id:
          type: string
          title: Session Id
      type: object
      required:
      - api_key
      - session_id
      title: SessionCloseIn
    StoreRequestIn:
      properties:
        text:
          type: string
          maxLength: 4000
          title: Text
          description: what you wish the counter stocked
        api_key:
          anyOf:
          - type: string
          - type: 'null'
          title: Api Key
        watch:
          type: boolean
          title: Watch
          description: with an api_key, flag this ask to hear back on a status flip — poll GET /v1/store/my_requests; no email/webhook
          default: false
      type: object
      required:
      - text
      title: StoreRequestIn
    RequestIn:
      properties:
        text:
          type: string
          maxLength: 4000
          title: Text
          description: what you wish the machine stocked
        api_key:
          anyOf:
          - type: string
          - type: 'null'
          title: Api Key
        watch:
          type: boolean
          title: Watch
          description: with an api_key, flag this ask to hear back on a status flip — poll GET /v1/store/my_requests; no email/webhook
          default: false
      type: object
      required:
      - text
      title: RequestIn
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
    RotateIn:
      properties:
        api_key:
          type: string
          title: Api Key
      type: object
      required:
      - api_key
      title: RotateIn
    ParkIn:
      properties:
        api_key:
          anyOf:
          - type: string
          - type: 'null'
          title: Api Key
        blob_b64:
          type: string
          title: Blob B64
          description: your ciphertext as base64 — ENCRYPT BEFORE PARKING; the store holds only opaque bytes and cannot read them
        ttl_seconds:
          anyOf:
          - type: integer
          - type: 'null'
          title: Ttl Seconds
          description: requested lifetime; clamped to [60s, 7d]. The effective expires_at is returned — never a silent surprise.
      type: object
      required:
      - blob_b64
      title: ParkIn
    FetchIn:
      properties:
        api_key:
          anyOf:
          - type: string
          - type: 'null'
          title: Api Key
        url:
          type: string
          maxLength: 2048
          title: Url
          description: http(s) URL to read → markdown
      type: object
      required:
      - url
      title: FetchIn
    SessionOpenIn:
      properties:
        api_key:
          type: string
          title: Api Key
        category:
          type: string
          title: Category
          description: resale | supply | retail
        side:
          type: string
          title: Side
          description: buy | sell
        walk_away:
          type: number
          exclusiveMinimum: 0.0
          title: Walk Away
          description: your floor (sell) / ceiling (buy)
        target:
          type: number
          exclusiveMinimum: 0.0
          title: Target
          description: your aspiration
        their_offers:
          anyOf:
          - items:
              type: number
            type: array
          - type: 'null'
          title: Their Offers
        my_offers:
          anyOf:
          - items:
              type: number
            type: array
          - type: 'null'
          title: My Offers
        rounds_left:
          anyOf:
          - type: integer
            minimum: 1.0
          - type: 'null'
          title: Rounds Left
        seed:
          type: integer
          title: Seed
          default: 0
      type: object
      required:
      - api_key
      - category
      - side
      - walk_away
      - target
      title: SessionOpenIn