{"openapi":"3.0.3","info":{"title":"AUBRAI x402 Service","version":"0.1.0","description":"Aubrai is the world's first decentralized AI co-scientist for longevity research, developed by VitaDAO. Orchestrates specialized sub-agents for literature synthesis, data analysis, and hypothesis generation to deliver comprehensive scientific reports on aging and lifespan extension.\n\nAll endpoints are gated by x402 micropayments using USDC on Base. Clients receive a `402 Payment Required` response with payment requirements, then retry with a signed `PAYMENT-SIGNATURE` header.\n\nSee [x402 docs](https://docs.cdp.coinbase.com/x402/core-concepts/how-it-works) for details."},"servers":[{"url":"/","description":"Current deployment"}],"tags":[{"name":"Research","description":"Deep research endpoints — **$0.20–$8.00** per job (steering / smart / fully-autonomous)"},{"name":"Chat","description":"Aubrai chat agent — **$0.02** per request. Includes a TEE-encrypted private variant via HPKE."},{"name":"Literature","description":"Aubrai literature search agent — **$0.03** per request"},{"name":"System","description":"Health and operational endpoints"}],"paths":{"/api/deep-research/start":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$1.00"},"tags":["Research"],"summary":"Start a deep research job","description":"Submit a research query to AUBRAI. Requires an x402 payment signature.\n\nThe payment is **verified but not settled** — settlement happens asynchronously when the job completes.\n\nIf no `PAYMENT-SIGNATURE` header is provided, returns `402` with payment requirements.","operationId":"startResearch","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"x402 payment signature. Omit to receive `402` with payment requirements.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"The research query or question.","example":"What are the latest developments in quantum computing?"},"researchMode":{"type":"string","enum":["fully-autonomous"],"default":"fully-autonomous","description":"Deep research runs a single autonomous mode. Optional and ignored — always fully-autonomous."},"conversationId":{"type":"string","description":"Optional. Continue an existing conversation by providing its ID."},"clarificationSessionId":{"type":"string","description":"Optional. Session ID for clarification follow-ups."}}}}}},"responses":{"200":{"description":"Research job queued successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string","description":"Unique ID to poll for results."},"status":{"type":"string","enum":["queued"]}}},"example":{"conversationId":"conv_abc123","status":"queued"}}}},"400":{"description":"Invalid request body or missing `message` field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Missing required field: message"}}}},"402":{"description":"Payment required. Returns payment requirements in the `PAYMENT-REQUIRED` header and response body.","headers":{"PAYMENT-REQUIRED":{"description":"Encoded payment requirements for x402 clients.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"},"example":{"x402Version":2,"resource":{"url":"https://example.com/api/deep-research/start","description":"AUBRAI API request","mimeType":"application/json"},"accepts":[{"scheme":"exact","network":"eip155:8453","amount":"1000000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0xa06D...cDa9F","maxTimeoutSeconds":29400,"extra":{"name":"USDC","version":"2"}}]}}}},"500":{"description":"Internal server error (DB or payment verification failure).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Internal server error"}}}},"4xx":{"description":"Upstream AUBRAI API error relayed with original status code and body (e.g. 429 rate limit, 503 service unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"rate limit exceeded"}}}}}}},"/api/deep-research/{conversationId}":{"get":{"tags":["Research"],"summary":"Get research results","description":"Poll for the status and results of a research job.\n\n- **queued** — Job is still processing. No data returned.\n- **completed** — Payment was settled. Full AUBRAI response returned.\n- **timeout** — Payment expired before completion. A new x402 payment is required to retrieve the results.","operationId":"getResearch","parameters":[{"name":"conversationId","in":"path","required":true,"description":"The conversation ID returned from `POST /api/deep-research/start`.","schema":{"type":"string"}},{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"Required only when conversation status is `timeout`. Provide a new x402 payment to retrieve results.","schema":{"type":"string"}}],"responses":{"200":{"description":"Research status or completed results.","content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string"},"status":{"type":"string","enum":["queued","completed"]},"data":{"type":"object","description":"AUBRAI research data. Only present when status is `completed`.","nullable":true}}},"examples":{"queued":{"summary":"Job still processing","value":{"conversationId":"conv_abc123","status":"queued"}},"completed":{"summary":"Job completed with results","value":{"conversationId":"conv_abc123","status":"completed","data":{"summary":"Quantum computing has seen...","sources":["https://..."]}}}}}}},"402":{"description":"Payment required (conversation timed out, new payment needed).","headers":{"PAYMENT-REQUIRED":{"description":"Encoded payment requirements.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"},"example":{"x402Version":2,"resource":{"url":"https://example.com/api/deep-research/conv_abc123","description":"AUBRAI API request (retry)","mimeType":"application/json"},"accepts":[{"scheme":"exact","network":"eip155:8453","amount":"1000000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0xa06D...cDa9F","maxTimeoutSeconds":29400,"extra":{"name":"USDC","version":"2"}}]}}}},"404":{"description":"Conversation not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Conversation not found"}}}},"500":{"description":"Internal server error (DB or unknown status).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Internal server error"}}}},"4xx":{"description":"Upstream AUBRAI API error relayed with original status code and body (e.g. 429 rate limit, 503 service unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"service unavailable"}}}}}}},"/api/deep-research/encrypted":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$1.00"},"tags":["Research"],"summary":"Start an encrypted deep-research run","description":"Start an HPKE-encrypted deep-research run inside an attested private enclave. The sealed plaintext carries `{message, recoveryKey}` (same X25519 → HKDF-SHA256 → XChaCha20-Poly1305 scheme as `/api/chat/encrypted`, request info string `\"chat-private-request-v1\"`). Async — poll the returned `pollUrl` by POSTing the sealed `{recoveryKey}`.","operationId":"startEncryptedResearch","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hpke_ciphertext","hpke_ephemeral_public_key"],"properties":{"hpke_ciphertext":{"type":"string","description":"HPKE-encrypted {message, recoveryKey}, base64."},"hpke_ephemeral_public_key":{"type":"string","description":"Sender's one-time X25519 public key, base64."}}}}}},"responses":{"202":{"description":"Accepted — poll pollUrl for the sealed result.","content":{"application/json":{"schema":{"type":"object","properties":{"messageId":{"type":"string"},"status":{"type":"string","enum":["queued"]},"pollUrl":{"type":"string","format":"uri"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/deep-research/encrypted/status/{messageId}":{"post":{"tags":["Research"],"summary":"Poll an encrypted deep-research run","description":"Poll the sealed encrypted deep-research result. POST the sealed `{recoveryKey}` (same scheme). Response `status` is plaintext; when `completed`, decrypt `hpke_response_ciphertext` with info `\"chat-private-response-v1\"` to read `{reply, citations[], worldState, ...}`.","operationId":"getEncryptedResearchStatus","parameters":[{"name":"messageId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hpke_ciphertext","hpke_ephemeral_public_key"],"properties":{"hpke_ciphertext":{"type":"string","description":"HPKE-encrypted {recoveryKey}, base64."},"hpke_ephemeral_public_key":{"type":"string","description":"Sender's one-time X25519 public key, base64."}}}}}},"responses":{"200":{"description":"Run status (result sealed when completed).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","completed","failed"]},"hpke_response_ciphertext":{"type":"string"},"hpke_response_ephemeral_key":{"type":"string"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/chat":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$0.02"},"tags":["Chat"],"summary":"Start a chat job","description":"Submit a question to the Aubrai chat agent. Requires x402 payment of $0.02. Returns a requestId to poll for results. Literature retrieval is intent-driven and remains enabled when `fast: true`; use the separate deep-research API for deep research. Completed results use the canonical `ChatResult`: citeable `references[]`, non-citeable screening diagnostics in `rejectedReferences[]`, and citation/qualification checks in `quality`.\n\n**Poll** `/api/chat/status/{requestId}` every ~750ms until `status` is `completed` or `failed`; give up after 60s.","operationId":"startChat","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"x402 payment signature header. Make a request without it first to receive the 402 payment requirements.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"The question to send to the chat agent.","example":"What foods improve longevity?"},"fast":{"type":"boolean","description":"Legacy compatibility hint. Literature retrieval remains intent-driven in chat; this flag does not disable scientific retrieval or select deep research."}}}}}},"responses":{"202":{"description":"Job queued successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"requestId":{"type":"string"},"status":{"type":"string","enum":["queued"]}}},"example":{"requestId":"req_abc123","status":"queued"}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Missing required field: message"}}}},"402":{"description":"Payment required.","headers":{"PAYMENT-REQUIRED":{"description":"x402 payment requirements header.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/chat/status/{requestId}":{"get":{"tags":["Chat"],"summary":"Poll chat job status","description":"Poll for the result of a chat job. Poll every ~2s until `status` is `completed` or `failed`; give up after 60s. A 404 means the requestId is unknown (typo or expired >1h).","operationId":"getChatStatus","parameters":[{"name":"requestId","in":"path","required":true,"description":"The requestId returned from POST /api/chat.","schema":{"type":"string"}}],"responses":{"200":{"description":"Job status and result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["queued","active","completed","failed"]},"progress":{"type":"object","nullable":true,"properties":{"stage":{"type":"string"},"percent":{"type":"integer"}}},"result":{"allOf":[{"$ref":"#/components/schemas/QueuedChatResult"}],"nullable":true},"error":{"type":"string","nullable":true,"description":"Set when status is \"failed\"."}}},"examples":{"queued":{"summary":"Queued","value":{"status":"queued"}},"active":{"summary":"In progress","value":{"status":"active","progress":{"stage":"thinking","percent":80}}},"completed":{"summary":"Completed","value":{"status":"completed","result":{"reply":"A primary trial reported improvement [1].","answer":"A primary trial reported improvement [1].","text":"A primary trial reported improvement [1].\n\nSources:\n[1] [supporting] Primary trial. https://doi.org/10.1000/trial","conversationId":"conversation_abc123","references":[{"ordinal":1,"title":"Primary trial","url":"https://doi.org/10.1000/trial","source":"journal","evidenceRole":"supporting"}],"rejectedReferences":[],"quality":{"contractValid":true,"primaryEvidencePresent":true},"responseTime":5442}}},"failed":{"summary":"Failed","value":{"status":"failed","error":"upstream error"}}}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/enclave-key":{"get":{"tags":["Chat"],"summary":"Fetch enclave HPKE public key","description":"Returns the X25519 public key clients use to encrypt requests to `/api/chat/encrypted` and `/api/literature/encrypted`. Free — no payment required. Cached for 60s.\n\n**Note:** Despite the `hpke_*` field name (retained for wire compatibility), the encrypted endpoints use a *custom* scheme — **not** standard HPKE. Do not use an HPKE library. See the protocol on those endpoints.","operationId":"getEnclaveKey","responses":{"200":{"description":"Enclave's HPKE public key.","content":{"application/json":{"schema":{"type":"object","properties":{"hpke_public_key":{"type":"string","description":"X25519 public key, base64-encoded."}}},"example":{"hpke_public_key":"pBbUKMAOC20RbFqfbqNcmqUwb8TGUbpxw4jS4OOj+QY="}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/chat/encrypted":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$0.02"},"tags":["Chat"],"summary":"Encrypted chat (TEE)","description":"Submit an encrypted prompt to the Aubrai chat agent running inside an attested private enclave. Proxied to the enclave after x402 payment verification. Requires x402 payment of $0.02; payment authorization is valid for up to 10 minutes. Response is 200 with ciphertext inline, or 202 with `pollUrl`.\n\n**Privacy boundary:** HPKE protects request and response transport. Direct chat generation stays on the private model path. When a prompt triggers literature retrieval, Aubrai sends search material to external retrieval and literature-processing services; do not use literature mode for content that must remain enclave-confined.\n\n**Scheme:** X25519 ECDH → HKDF-SHA256 → XChaCha20-Poly1305. **Not standard HPKE — do not use an HPKE library.**\n\n**Protocol (plaintext = `{ message, conversationId?, retrievalBudget?, recoveryKey?, model?, attachments? }` — only `message` is required):**\n1. `serverPub = base64decode(GET /api/enclave-key → hpke_public_key)`\n2. `clientEphPriv = random 32 bytes; clientEphPub = X25519.pub(clientEphPriv)`\n3. `reqKey = HKDF-SHA256(ikm = X25519(clientEphPriv, serverPub), salt = clientEphPub, info = \"chat-private-request-v1\")`\n4. `nonce = random 24 bytes; ct = nonce || XChaCha20Poly1305.seal(reqKey, nonce, JSON.stringify(plaintext))`\n5. POST `{ hpke_ciphertext: base64(ct), hpke_ephemeral_public_key: base64(clientEphPub) }`\n6. On completed response (200 inline or via pollUrl):\n   - `respPub = base64decode(hpke_response_ephemeral_key)`\n   - `respKey = HKDF-SHA256(ikm = X25519(clientEphPriv, respPub), salt = respPub, info = \"chat-private-response-v1\")`\n   - `respCt = base64decode(hpke_response_ciphertext)`\n   - `plaintext = XChaCha20Poly1305.open(respKey, respCt[0:24], respCt[24:])`\n\n**Request plaintext fields:** `message` (string, required); `conversationId` (string, optional); `retrievalBudget` (`\"balanced\"` | `\"high-recall\"`, optional); `recoveryKey` (string, optional); `model` (string, optional and server-overridden); `attachments` (array of `{ filename, text }`, optional).\n\n**Decrypted response:** the canonical `ChatResult`, including `reply`, `answer`, `text`, citeable `references[]`, non-citeable `rejectedReferences[]`, and `quality`. Every inline `[N]` resolves only to `references[N-1]`. References expose title, URL, DOI/PMID/PMCID when known, year, source, evidence role/type, verification, confidence, and role reason. Legacy `metadata` remains for backward compatibility.","operationId":"startEncryptedChat","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"x402 payment signature header.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hpke_ciphertext","hpke_ephemeral_public_key"],"properties":{"hpke_ciphertext":{"type":"string","description":"The encrypted prompt, base64-encoded. Only the enclave can decrypt this."},"hpke_ephemeral_public_key":{"type":"string","description":"Sender's one-time X25519 public key, base64-encoded."}}}}}},"responses":{"200":{"description":"Sync encrypted response.","content":{"application/json":{"schema":{"type":"object","properties":{"requestId":{"type":"string"},"hpke_response_ciphertext":{"type":"string","description":"Encrypted AI response, base64-encoded."},"hpke_response_ephemeral_key":{"type":"string","description":"Enclave's one-time public key, base64-encoded."}}},"example":{"requestId":"abc123","hpke_response_ciphertext":"<base64>","hpke_response_ephemeral_key":"<base64>"}}}},"202":{"description":"Queued — poll pollUrl for result.","content":{"application/json":{"schema":{"type":"object","properties":{"requestId":{"type":"string"},"status":{"type":"string","enum":["queued"]},"pollUrl":{"type":"string","format":"uri","description":"Absolute URL to poll for status."}}},"example":{"requestId":"abc123","status":"queued","pollUrl":"https://x402-api.aubr.ai/api/chat/encrypted/status/abc123"}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required.","headers":{"PAYMENT-REQUIRED":{"description":"x402 payment requirements header.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/chat/encrypted/status/{requestId}":{"get":{"tags":["Chat"],"summary":"Poll encrypted chat status","description":"Poll the status of a queued encrypted chat job. Free — no payment required. When complete, returns the HPKE-encrypted reply payload; decrypted plaintext matches the `ChatResult` contract documented on POST /api/chat/encrypted.","operationId":"getEncryptedChatStatus","parameters":[{"name":"requestId","in":"path","required":true,"description":"The requestId returned from POST /api/chat/encrypted.","schema":{"type":"string"}}],"responses":{"200":{"description":"Job status. Completed responses carry the HPKE-encrypted reply.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","active"]}}},{"type":"object","properties":{"status":{"type":"string","enum":["completed"]},"requestId":{"type":"string"},"hpke_response_ciphertext":{"type":"string","description":"Encrypted AI response, base64-encoded."},"hpke_response_ephemeral_key":{"type":"string","description":"Enclave's one-time public key, base64-encoded."}}},{"type":"object","properties":{"status":{"type":"string","enum":["failed"]},"error":{"type":"string"}}}]},"examples":{"queued":{"summary":"Still queued","value":{"status":"queued"}},"active":{"summary":"Processing","value":{"status":"active"}},"completed":{"summary":"Done — encrypted reply","value":{"status":"completed","requestId":"abc123","hpke_response_ciphertext":"<base64>","hpke_response_ephemeral_key":"<base64>"}},"failed":{"summary":"Failed","value":{"status":"failed","error":"upstream error"}}}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/literature/encrypted":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$0.03"},"tags":["Literature"],"summary":"Encrypted literature transport","description":"Submit an HPKE-sealed literature query to the pinned Aubrai server and receive an encrypted result. Always async — long-poll `pollUrl` for the encrypted result. Requires x402 payment of $0.03.\n\n**Privacy boundary:** HPKE protects the client-to-Aubrai transport and the returned answer. This is **not end-to-end confidential inference**: after Aubrai decrypts the request, literature retrieval and evidence processing use external services. Do not send material that must remain confined to an enclave.\n\n**Scheme:** X25519 ECDH → HKDF-SHA256 → XChaCha20-Poly1305. **Not standard HPKE — do not use an HPKE library.** Same scheme as `/api/chat/encrypted`; info string for requests is still `\"chat-private-request-v1\"`.\n\n**Protocol (plaintext = same fields as POST /api/literature, including optional `scope`, `tags`, `tagMode`, `retrievalProfile`, `privacyMode`, `filterReferences`, `includeRejected`, and `recoveryKey`):** A stable `recoveryKey` enables caller-private retrieval-cache reuse across repeated encrypted requests; it remains inside the sealed payload.\n1. `serverPub = base64decode(GET /api/enclave-key → hpke_public_key)`\n2. `clientEphPriv = random 32 bytes; clientEphPub = X25519.pub(clientEphPriv)`\n3. `reqKey = HKDF-SHA256(ikm = X25519(clientEphPriv, serverPub), salt = clientEphPub, info = \"chat-private-request-v1\")`\n4. `nonce = random 24 bytes; ct = nonce || XChaCha20Poly1305.seal(reqKey, nonce, JSON.stringify(plaintext))`\n5. POST `{ hpke_ciphertext: base64(ct), hpke_ephemeral_public_key: base64(clientEphPub) }` → 202 `{ requestId, pollUrl }`\n6. Long-poll `GET {pollUrl}?timeout=25` until `status: \"completed\"`, then:\n   - `respPub = base64decode(hpke_response_ephemeral_key)`\n   - `respKey = HKDF-SHA256(ikm = X25519(clientEphPriv, respPub), salt = respPub, info = \"chat-private-response-v1\")`\n   - `respCt = base64decode(hpke_response_ciphertext)`\n   - `plaintext = XChaCha20Poly1305.open(respKey, respCt[0:24], respCt[24:])`\n\n**Decrypted response fields:** `answer`, `references[]` (with optional `relevance`), `quality`, `rejectedReferences[]` (when `includeRejected: true`), `resultsByTag`, `retrievalBackend`, `fallbackUsed`, `effectiveSources`, `sourceProfile`, `tagMode`, `tags`, `jobId`, `status`, `sourceErrors`.","operationId":"startEncryptedLiterature","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"x402 payment signature header.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hpke_ciphertext","hpke_ephemeral_public_key"],"properties":{"hpke_ciphertext":{"type":"string","description":"The literature query transport envelope, base64-encoded. Aubrai decrypts it before external literature processing."},"hpke_ephemeral_public_key":{"type":"string","description":"Sender's one-time X25519 public key, base64-encoded."}}}}}},"responses":{"202":{"description":"Queued — poll pollUrl for encrypted result.","content":{"application/json":{"schema":{"type":"object","properties":{"requestId":{"type":"string"},"status":{"type":"string","enum":["pending"]},"pollUrl":{"type":"string","format":"uri","description":"Absolute URL to long-poll for status."}}},"example":{"requestId":"abc123","status":"pending","pollUrl":"https://x402-api.aubr.ai/api/literature/encrypted/status/abc123"}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required.","headers":{"PAYMENT-REQUIRED":{"description":"x402 payment requirements header.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/literature/encrypted/status/{requestId}":{"get":{"tags":["Literature"],"summary":"Long-poll encrypted literature status","description":"Long-poll (up to 25s per call) the status of a queued encrypted literature job. Free — no payment required. When complete, returns HPKE-encrypted answer payload.","operationId":"getEncryptedLiteratureStatus","parameters":[{"name":"requestId","in":"path","required":true,"description":"The requestId returned from POST /api/literature/encrypted.","schema":{"type":"string"}},{"name":"timeout","in":"query","required":false,"description":"Long-poll timeout in seconds (max 25).","schema":{"type":"integer","default":25,"maximum":25}}],"responses":{"200":{"description":"Job status. Completed responses carry the HPKE-encrypted answer; decrypted payload matches LiteratureJobResult (answer, references[].relevance, quality, rejectedReferences when requested, resultsByTag, retrievalBackend, fallbackUsed, effectiveSources, sourceProfile, tagMode, tags).","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["active"]}}},{"type":"object","properties":{"status":{"type":"string","enum":["completed"]},"hpke_response_ciphertext":{"type":"string"},"hpke_response_ephemeral_key":{"type":"string"}}},{"type":"object","properties":{"status":{"type":"string","enum":["failed"]},"error":{"type":"string"}}}]},"examples":{"active":{"summary":"Still processing","value":{"status":"active"}},"completed":{"summary":"Done — encrypted answer","value":{"status":"completed","hpke_response_ciphertext":"<base64>","hpke_response_ephemeral_key":"<base64>"}},"failed":{"summary":"Failed","value":{"status":"failed","error":"upstream error"}}}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/literature":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$0.03"},"tags":["Literature"],"summary":"Start a literature search","description":"Start a literature search across scientific sources. Requires x402 payment of $0.03.\n\nRetrieval runs on one unified research-paper index covering major biomedical journals, repositories, and preprint servers. The legacy `sources` / `perSourceLimit` / `allowSourceExpansion` / `sourceProfile` params are accepted for back-compat but no longer steer retrieval, so a source allowlist has no effect. For deliberate scoping use `scope`: `preprints` (biorxiv/medrxiv/arxiv), `no-preprints` (exclude those), or `trials` (clinicaltrials.gov). Omit `scope` for the full index (best recall).\n\nFor radar-style tracked terms, send separate `tags` with `tagMode: \"fanout\"`; do not concatenate tracked terms into `question` unless you want a combined search. Completed fanout responses include `resultsByTag`; clients should check each tag coverage, not just overall accepted counts.\n\nUpstream applies reference filtering by default (`filterReferences` defaults to true when omitted). Set `includeRejected: true` to receive `rejectedReferences[]` and per-ref `relevance` metadata on completed jobs.\n\n**Async polling:** Both fast and deep modes commonly return `202 { jobId, status: \"queued\" }`. Poll `GET /api/literature/jobs/{jobId}` (free, no second payment) until `status: \"completed\"`. Sync inline answers (HTTP 200) are possible but uncommon.","operationId":"startLiteratureQuery","parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"x402 payment signature header.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiteratureQueryRequest"}}}},"responses":{"200":{"description":"Synchronous search result (uncommon for fast mode).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiteratureJobResult"}}}},"202":{"description":"Job queued — poll GET /api/literature/jobs/{jobId} (free).","content":{"application/json":{"schema":{"type":"object","required":["jobId","status"],"properties":{"jobId":{"type":"string"},"status":{"type":"string","enum":["queued"]}}},"example":{"jobId":"lit_abc123","status":"queued"}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Missing required field: question"}}}},"402":{"description":"Payment required.","headers":{"PAYMENT-REQUIRED":{"description":"x402 payment requirements header.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/literature/jobs/{jobId}":{"get":{"tags":["Literature"],"summary":"Poll literature job","description":"Poll the status and results of a literature search job. Free — no second x402 payment. Completed payloads include upstream reference filtering metadata (`quality`, optional `rejectedReferences`, `references[].relevance`, `retrievalBackend`, `fallbackUsed`).","operationId":"getLiteratureJob","parameters":[{"name":"jobId","in":"path","required":true,"description":"The jobId returned from POST /api/literature.","schema":{"type":"string"}}],"responses":{"200":{"description":"Job status and result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiteratureJobResult"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/health":{"get":{"tags":["System"],"summary":"System health check","description":"Returns the health status of all system components (database, AUBRAI API, x402 facilitator), conversation statistics, and configuration info.\n\nReturns HTTP 503 if any component is `down`.","operationId":"healthCheck","responses":{"200":{"description":"System is healthy or degraded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"503":{"description":"System is down — at least one critical component is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/api/cron":{"get":{"tags":["System"],"summary":"Trigger settlement cron job","description":"Processes all `queued` conversations: checks AUBRAI for completion, settles valid payments, and marks expired ones as `timeout`.\n\nProtected by a Bearer token (`CRON_SECRET`). Typically invoked by Vercel Cron every minute.","operationId":"triggerCron","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Cron job executed successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}},"example":{"ok":true}}}},"401":{"description":"Unauthorized — invalid or missing Bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Unauthorized"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"CRON_SECRET Bearer token for the cron endpoint."}},"schemas":{"ChatReference":{"type":"object","required":["ordinal","id","title","url","source","evidenceRole","evidenceType","verification","confidence","roleReason"],"properties":{"ordinal":{"type":"integer","minimum":1},"id":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"source":{"type":"string"},"year":{"type":"integer","nullable":true},"doi":{"type":"string","nullable":true},"pmid":{"type":"string","nullable":true},"pmcid":{"type":"string","nullable":true},"evidenceRole":{"type":"string","enum":["supporting","context","lead_only"]},"evidenceType":{"type":"string","enum":["randomized_controlled_trial","controlled_trial","single_arm_trial","observational","systematic_review","narrative_review","preclinical","commentary","unknown"]},"verification":{"type":"string","enum":["verified","probable","unknown"]},"confidence":{"type":"number","minimum":0,"maximum":1},"roleReason":{"type":"string"},"duplicateOfOrdinal":{"type":"integer","minimum":1,"nullable":true}}},"ChatRejectedReference":{"type":"object","description":"A screened candidate that was not accepted into the citeable references[] namespace.","required":["candidateOrdinal","id","title","url","source","evidenceRole","evidenceType","verification","confidence","roleReason"],"properties":{"candidateOrdinal":{"type":"integer","minimum":1},"id":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"},"source":{"type":"string"},"year":{"type":"integer","nullable":true},"doi":{"type":"string","nullable":true},"pmid":{"type":"string","nullable":true},"pmcid":{"type":"string","nullable":true},"evidenceRole":{"type":"string","enum":["context","lead_only"]},"evidenceType":{"type":"string","enum":["randomized_controlled_trial","controlled_trial","single_arm_trial","observational","systematic_review","narrative_review","preclinical","commentary","unknown"]},"verification":{"type":"string","enum":["verified","probable","unknown"]},"confidence":{"type":"number","minimum":0,"maximum":1},"roleReason":{"type":"string"},"duplicateOfOrdinal":{"type":"integer","minimum":1,"nullable":true}}},"ChatQuality":{"type":"object","required":["citations","roleCounts","citedSupportingOrdinals","citedContextOrdinals","citedLeadOnlyOrdinals","primaryEvidencePresent","containsNonSupportingCitations","contractValid"],"properties":{"citations":{"type":"object","required":["markers","referenceCount","outOfRangeOrdinals","missingMarkerOrdinals","uncitedReferenceOrdinals","allMarkersResolve","contiguousMarkers"],"properties":{"markers":{"type":"array","items":{"type":"integer"}},"referenceCount":{"type":"integer"},"outOfRangeOrdinals":{"type":"array","items":{"type":"integer"}},"missingMarkerOrdinals":{"type":"array","items":{"type":"integer"}},"uncitedReferenceOrdinals":{"type":"array","items":{"type":"integer"}},"allMarkersResolve":{"type":"boolean"},"contiguousMarkers":{"type":"boolean"}}},"roleCounts":{"type":"object","additionalProperties":{"type":"integer"}},"citedSupportingOrdinals":{"type":"array","items":{"type":"integer"}},"citedContextOrdinals":{"type":"array","items":{"type":"integer"}},"citedLeadOnlyOrdinals":{"type":"array","items":{"type":"integer"}},"primaryEvidencePresent":{"type":"boolean"},"containsNonSupportingCitations":{"type":"boolean"},"contractValid":{"type":"boolean"},"qualification":{"type":"object","nullable":true,"additionalProperties":true}}},"ChatResult":{"type":"object","required":["reply","answer","text","conversationId","references","rejectedReferences","quality"],"properties":{"reply":{"type":"string","description":"Backward-compatible answer field."},"answer":{"type":"string"},"text":{"type":"string","description":"Self-contained answer plus deterministic source list."},"conversationId":{"type":"string"},"messageId":{"type":"string","nullable":true},"references":{"type":"array","items":{"$ref":"#/components/schemas/ChatReference"}},"rejectedReferences":{"type":"array","items":{"$ref":"#/components/schemas/ChatRejectedReference"},"description":"Screened context/lead candidates. These are diagnostics only and are never addressed by inline [N] markers."},"quality":{"$ref":"#/components/schemas/ChatQuality"},"metadata":{"type":"object","nullable":true,"additionalProperties":true}}},"QueuedChatResult":{"allOf":[{"$ref":"#/components/schemas/ChatResult"},{"type":"object","required":["responseTime"],"properties":{"responseTime":{"type":"integer","description":"Upstream processing time in milliseconds."}}}]},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Error message."},"reason":{"type":"string","description":"Machine-readable reason (payment errors).","nullable":true},"message":{"type":"string","description":"Human-readable details (payment errors).","nullable":true}},"required":["error"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","down"]},"timestamp":{"type":"string","format":"date-time"},"uptime":{"type":"integer","description":"Seconds since process start."},"version":{"type":"string"},"components":{"type":"object","properties":{"upstreamApi":{"$ref":"#/components/schemas/ComponentHealth"},"database":{"$ref":"#/components/schemas/ComponentHealth"}}},"config":{"type":"object","properties":{"paymentAddress":{"type":"string"},"upstreamApiBaseUrl":{"type":"string"},"network":{"type":"string"},"pricing":{"type":"object","additionalProperties":{"type":"string"}}}}}},"PaymentRequired":{"type":"object","description":"x402 payment requirements returned when no valid payment is provided.","properties":{"x402Version":{"type":"integer","description":"x402 protocol version.","example":2},"resource":{"type":"object","description":"The resource that requires payment.","properties":{"url":{"type":"string","description":"The resource URL that requires payment.","example":"https://example.com/api/deep-research/start"},"description":{"type":"string","description":"Human-readable description of the paid resource.","example":"AUBRAI API request"},"mimeType":{"type":"string","example":"application/json"}}},"accepts":{"type":"array","description":"List of accepted payment methods.","items":{"type":"object","properties":{"scheme":{"type":"string","description":"Payment scheme identifier.","example":"exact"},"network":{"type":"string","description":"Chain ID in CAIP-2 format.","example":"eip155:8453"},"amount":{"type":"string","description":"Amount in token base units (USDC has 6 decimals, so 200000 = $0.20).","example":"200000"},"asset":{"type":"string","description":"Token contract address (USDC on Base).","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"payTo":{"type":"string","description":"Wallet address to receive payment.","example":"0xa06D...cDa9F"},"maxTimeoutSeconds":{"type":"integer","description":"Maximum seconds before the payment authorization expires. Varies by researchMode: steering (1800), smart (4200), fully-autonomous (29400).","example":1800},"extra":{"type":"object","description":"Additional scheme-specific fields.","properties":{"name":{"type":"string","description":"Token name.","example":"USDC"},"version":{"type":"string","description":"Token contract version.","example":"2"}}}}}},"extensions":{"type":"object","description":"x402 Bazaar discovery extensions. Contains metadata for AI agent discoverability via x402scan.","properties":{"bazaar":{"type":"object","properties":{"info":{"type":"object","description":"Example input/output for the endpoint, used by AI agents to understand how to call it."},"schema":{"type":"object","description":"JSON Schema describing the expected input and output format."}}}}}}},"ComponentHealth":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","down"]},"latencyMs":{"type":"integer","nullable":true},"message":{"type":"string","nullable":true}}},"LiteratureQueryRequest":{"type":"object","required":["question"],"properties":{"question":{"type":"string","minLength":1,"maxLength":8192,"description":"The research question.","example":"What are the latest scientific findings on rapamycin and longevity?"},"mode":{"type":"string","enum":["fast","deep"],"default":"fast","description":"Search depth. Both modes may return 202 + jobId; poll is free."},"sourceProfile":{"type":"string","enum":["fast-default","deep-default","clinical","paperclip","litqa-recall"],"description":"Optional source profile. Omit to preserve old behavior and let Aubrai choose defaults.","example":"clinical"},"tags":{"type":"array","items":{"type":"string"},"description":"Tracked terms for radar-style searches. With tagMode=fanout, Aubrai fans out each tag instead of treating them as one combined query.","example":["NAD+","autophagy"]},"tagMode":{"type":"string","enum":["fanout","combined"],"description":"Use fanout for independent tag searches; use combined only when the user explicitly wants terms searched together.","example":"fanout"},"allowSourceExpansion":{"type":"boolean","deprecated":true,"description":"Deprecated / ignored. Aubrai retrieves from one unified scientific index; there is no per-source expansion to toggle. Use `scope` for deliberate scoping."},"maxResults":{"type":"integer","description":"Maximum number of results."},"perSourceLimit":{"type":"integer","description":"Deprecated / ignored — retrieval uses one unified index, so there is no per-source cap.","deprecated":true},"sources":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated / ignored. Retrieval uses one unified research-paper index, so a source allowlist has no effect. For deliberate scoping use `scope`."},"scope":{"type":"string","enum":["preprints","no-preprints","trials"],"description":"Opt-in retrieval scoping, mapped upstream to include/exclude domains. Omit for the full index (best recall). `preprints` = biorxiv/medrxiv/arxiv only; `no-preprints` = exclude those; `trials` = clinicaltrials.gov only. Restricting scope trades recall for a narrower, deliberate set.","example":"preprints"},"retrievalProfile":{"type":"string","enum":["default","litqa-recall"],"description":"Optional retrieval profile: \"default\" or \"litqa-recall\".","example":"litqa-recall"},"privacyMode":{"type":"string","description":"Optional plaintext privacy mode forwarded to Aubrai when provided."},"year":{"type":"string","description":"Filter by publication year."},"date_from":{"type":"string","format":"date","description":"Start date filter (YYYY-MM-DD)."},"date_to":{"type":"string","format":"date","description":"End date filter (YYYY-MM-DD)."},"filterReferences":{"type":"boolean","default":true,"description":"Default true upstream — drop off-topic refs. Set false for raw/unfiltered refs (debug)."},"includeRejected":{"type":"boolean","default":false,"description":"When true, completed responses include rejectedReferences[] and relevance.reason on rejected refs."}}},"LiteratureReferenceRelevance":{"type":"object","properties":{"accepted":{"type":"boolean"},"score":{"type":"number"},"matchedTerms":{"type":"array","items":{"type":"string"}},"flags":{"type":"array","items":{"type":"string"}},"reason":{"type":"string","nullable":true,"description":"Present on rejected refs when includeRejected is true."}}},"LiteratureReference":{"type":"object","properties":{"id":{"oneOf":[{"type":"number"},{"type":"string"}]},"title":{"type":"string"},"url":{"type":"string"},"source":{"type":"string","nullable":true},"year":{"type":"number","nullable":true},"item_date":{"type":"string","nullable":true,"description":"Publication date in YYYY-MM-DD format."},"relevance":{"$ref":"#/components/schemas/LiteratureReferenceRelevance"}}},"LiteratureQuality":{"type":"object","description":"Reference filtering summary from upstream. Present on completed jobs even when clients omit new request params.","properties":{"filtered":{"type":"boolean"},"rawCount":{"type":"integer"},"acceptedCount":{"type":"integer"},"rejectedCount":{"type":"integer"},"lowConfidence":{"type":"boolean"},"evidenceThin":{"type":"boolean"},"rejectionReasons":{"type":"object","additionalProperties":{"type":"integer"},"description":"e.g. { low_query_overlap: 4, low_relevance: 1 }"}}},"LiteratureResultsByTagEntry":{"type":"object","description":"Per-tag coverage summary for tagMode=fanout literature requests.","properties":{"tag":{"type":"string"},"covered":{"type":"boolean","description":"True when Aubrai found source-grounded accepted evidence for this tag."},"acceptedCount":{"type":"integer"},"rejectedCount":{"type":"integer"},"matchedTerms":{"type":"array","items":{"type":"string"}},"acceptedReferences":{"type":"array","items":{"type":"object"}},"rejectedReferences":{"type":"array","items":{"type":"object"},"nullable":true}}},"LiteratureJobResult":{"type":"object","properties":{"answer":{"type":"string","nullable":true},"formattedAnswer":{"type":"string","nullable":true},"references":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/LiteratureReference"}},"rejectedReferences":{"type":"array","nullable":true,"items":{"type":"object"},"description":"Only when includeRejected was true on the request."},"contextPassages":{"type":"array","items":{"type":"object"},"nullable":true},"jobId":{"type":"string","nullable":true},"status":{"type":"string","nullable":true},"reasoning":{"type":"array","items":{"type":"string"},"nullable":true},"quality":{"$ref":"#/components/schemas/LiteratureQuality"},"retrievalBackend":{"type":"string","nullable":true,"example":"literature-agent"},"fallbackUsed":{"type":"boolean","nullable":true},"effectiveSources":{"type":"array","items":{"type":"string"},"description":"Sources actually used by upstream.","nullable":true},"sourceProfile":{"type":"string","nullable":true,"description":"Source profile applied by upstream."},"tagMode":{"type":"string","nullable":true,"description":"Tag mode applied by upstream."},"tags":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Tags echoed by upstream for radar/fanout requests."},"resultsByTag":{"type":"object","nullable":true,"additionalProperties":{"$ref":"#/components/schemas/LiteratureResultsByTagEntry"},"description":"Per-tag fanout coverage and accepted/rejected references. Check each tag coverage instead of relying only on overall quality counts."}}}}}}