openapi: 3.2.0 info: title: Game Theory Layer for AI Agents Store 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: Store paths: /v1/store/catalog: get: tags: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: - Store 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: 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 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 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