{"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\nProduction requests are served by the Aubrai production API through its pinned Phala enclave host. Staging is unavailable; preview and local deployments retain the retired staging address and never fall back to production.\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 — **$1.00** per job"},{"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 current Aubrai API accepts the job asynchronously and returns a message and conversation ID. Payment settlement is scheduled after the job is accepted.\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?"},"conversationId":{"type":"string","description":"Optional. Continue an existing conversation by providing its ID."}}}}}},"responses":{"202":{"description":"Research job queued successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"messageId":{"type":"string","description":"Aubrai research run identifier."},"conversationId":{"type":"string","description":"Unique ID to poll for results."},"status":{"type":"string","enum":["queued"]}}},"example":{"messageId":"msg_abc123","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":"Returns the current AUBRAI conversation history. The response contains `status`, `sessionStatus`, `worldState`, optional `activeMessageId`, and `turns`; each completed turn contains its reply and citations. `status`, on the conversation and on each turn, is `queued`, `running` or `cancelling` while research is in progress, then `completed`, `failed` or `cancelled`.","operationId":"getResearch","parameters":[{"name":"conversationId","in":"path","required":true,"description":"The conversation ID returned from `POST /api/deep-research/start`.","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","running","cancelling","completed","failed","cancelled"]},"worldState":{"type":"object","nullable":true},"sessionStatus":{"type":"string"},"activeMessageId":{"type":"string"},"turns":{"type":"array","items":{"type":"object","properties":{"messageId":{"type":"string"},"objective":{"type":"string"},"reply":{"type":"string"},"citations":{"type":"array","items":{"type":"object"}},"status":{"type":"string","enum":["queued","running","cancelling","completed","failed","cancelled"]},"isFinal":{"type":"boolean"}}}}}},"examples":{"queued":{"summary":"Job still processing","value":{"conversationId":"conv_abc123","status":"queued"}},"completed":{"summary":"Job completed with results","value":{"conversationId":"conv_abc123","status":"completed","worldState":null,"sessionStatus":"completed","turns":[{"messageId":"msg_abc123","reply":"Quantum computing has seen...","citations":[],"status":"completed","isFinal":true}]}}}}}},"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":"Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.\n\nStart 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_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"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":{"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"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":"Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.\n\nPoll the sealed encrypted deep-research result. POST the sealed `{recoveryKey}` (same scheme). Response `status` is plaintext; in legacy mode, 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_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"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_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"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/attestation":{"get":{"tags":["System"],"summary":"Fetch nonce-bound Phala attestation evidence","description":"Free, no bearer credential or payment. Supply a fresh canonical base64url encoding of 32 random bytes. The gateway relays raw evidence from its pinned Phala host; the browser must verify the Intel quote, nonce, reviewed deployment measurements, and HPKE key binding locally. No server-reported verification verdict substitutes for these checks. Responses are bounded to 4 MiB and never cached.","operationId":"getPhalaAttestation","security":[],"parameters":[{"name":"nonce","in":"query","required":true,"schema":{"type":"string","minLength":43,"maxLength":43,"pattern":"^[A-Za-z0-9_-]{43}$"},"description":"Canonical base64url without padding; exactly 32 random bytes. No other query parameters are accepted."}],"responses":{"200":{"description":"Raw evidence for local verification.","headers":{"Cache-Control":{"schema":{"type":"string","enum":["no-store"]},"description":"Proof and key responses must not be cached."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhalaAttestationEvidence"}}}},"400":{"description":"Missing, malformed, repeated nonce, or extra query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Attestation is unavailable, malformed, oversized, or timed out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/attestation/confirm":{"post":{"tags":["System"],"summary":"Confirm possession of the attested HPKE private key","description":"Free, no bearer credential or payment. After locally verifying the quote, seal only `{challenge: <fresh 32-byte base64url value>}` to its bound HPKE key. The request is limited to 4096 bytes. Authenticate the response with that same attested key and compare the echoed challenge before sealing confidential content. This endpoint creates no paid work. Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.","operationId":"confirmPhalaAttestationKey","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttestationConfirmationRequest"}}}},"responses":{"200":{"description":"Authenticated encrypted `{challenge}` echo.","headers":{"Cache-Control":{"schema":{"type":"string","enum":["no-store"]},"description":"Proof and key responses must not be cached."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttestationConfirmationResponse"}}}},"400":{"description":"Invalid, oversized, or unsupported confirmation envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Key-possession confirmation unavailable or timed out.","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/deep-research/encrypted`. Free — no payment required. Returned with `Cache-Control: no-store`. This is unverified key discovery; complete the attestation and key-possession handshake before use.\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":"Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.\n\nSubmit 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. The Aubrai API responds synchronously with encrypted output.\n\n**Privacy boundary:** HPKE protects request and response transport. Direct chat generation stays on the private model path. Private runs do not use external literature tools.\n\n**Scheme:** X25519 ECDH → HKDF-SHA256 → XChaCha20-Poly1305. **Not standard HPKE — do not use an HPKE library.**\n\n**Legacy compatibility protocol without the attested marker (plaintext = `{ message, recoveryKey?, conversationId?, attachments? }`; `message` is required; omit `recoveryKey` for stateless requests):**\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. Decrypt the completed response with info string `\"chat-private-response-v1\"`.\n\nFor persistent private chat, the client creates and retains `recoveryKey`; it must use the `aubrai_key_v1_` format documented by Aubrai and remains inside the sealed payload.","x-sealed-plaintext-required":["message"],"x-decrypted-response-schema":"#/components/schemas/ChatResult","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_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"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_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"hpke_response_ciphertext":{"type":"string","description":"Encrypted AI response, base64-encoded."},"hpke_response_ephemeral_key":{"type":"string","description":"Attested static server public key when hpke_protocol is present; otherwise the legacy response ephemeral 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":{"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"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"}}}},"503":{"description":"Private chat is unavailable: the enclave is unreachable or its private mode is not ready. Checked before payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"private_chat_unavailable","reason":"private_mode_not_ready"}}}}}}},"/api/chat/encrypted/status/{requestId}":{"get":{"tags":["Chat"],"summary":"Poll encrypted chat status","description":"Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.\n\nPoll 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":"hpke_protocol","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"description":"Retain the attested mode from the original encrypted request."},{"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_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"hpke_response_ciphertext":{"type":"string","description":"Encrypted AI response, base64-encoded."},"hpke_response_ephemeral_key":{"type":"string","description":"Attested static server public key when hpke_protocol is present; otherwise the legacy response ephemeral 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_protocol":"aubrai-attested-v1","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":"Start an encrypted literature search","description":"Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.\n\nSend an HPKE-sealed literature query (the `/api/literature` body plus optional `recoveryKey`, sealed to the key from `GET /api/enclave-key`) and receive a sealed result. Requires x402 payment of $0.03. The search queries leave the Aubrai enclave for external literature sources (Firecrawl, PubMed and others); the question and the answer stay sealed.\n\nChecked before payment: when the Aubrai API has private literature off this returns `403 private_literature_disabled`, and `503 private_literature_unavailable` when its private-mode status cannot be read.\n\n**Async polling:** returns `202 { requestId, status: \"pending\", pollUrl }`. Poll `GET /api/literature/encrypted/status/{requestId}` (free) until `status: \"completed\"`, then open the sealed result with the ephemeral key that sealed the request.","operationId":"startEncryptedLiterature","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hpke_ciphertext","hpke_ephemeral_public_key"],"properties":{"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"hpke_ciphertext":{"type":"string","description":"Base64 HPKE ciphertext of the JSON literature request."},"hpke_ephemeral_public_key":{"type":"string","description":"Base64 ephemeral public key the request was sealed with."}}}}}},"responses":{"202":{"description":"Accepted; poll pollUrl for the sealed result.","content":{"application/json":{"schema":{"type":"object","properties":{"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"requestId":{"type":"string"},"status":{"type":"string","enum":["pending"]},"pollUrl":{"type":"string","format":"uri","description":"Absolute URL of the free status route."}}},"example":{"requestId":"elit_3f0c2a64-8d1e-4b7a-9c55-2e6f1b0a9d42","status":"pending","pollUrl":"https://x402-api.aubr.ai/api/literature/encrypted/status/elit_3f0c2a64-8d1e-4b7a-9c55-2e6f1b0a9d42"}}}},"400":{"description":"Missing envelope fields, undecryptable envelope, or an invalid literature request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required."},"403":{"description":"The Aubrai API has private literature off; checked before payment verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"private_literature_disabled"}}}},"503":{"description":"The Aubrai private-mode status could not be read; checked before payment verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"private_literature_unavailable"}}}}}}},"/api/literature/encrypted/status/{requestId}":{"get":{"tags":["Literature"],"summary":"Poll an encrypted literature search","description":"Recommended: load `/privacy/genome-private.js` and use `GenomePrivate.createVerifiedClient({ baseUrl: window.location.origin })`. Before sealing confidential content or a recovery key, verify a fresh nonce via GET `/api/attestation` against independently reviewed Phala pins and authenticate POST `/api/attestation/confirm`. Send `hpke_protocol: \"aubrai-attested-v1\"` on the encrypted request; retain it on GET polls as a query parameter or POST polls in the envelope. Authenticated replies carry the same marker and the attested static server public key in `hpke_response_ephemeral_key`; reject missing/mismatched markers or keys. Their KDF info is `\"aubrai-attested-response-v1\"`, with the server public key as salt and the client ephemeral/server static X25519 shared secret. Refresh verification after 120 seconds. Omitting the marker retains the legacy, unauthenticated response mode; key discovery or an HTTP 200 alone is not attestation.\n\nFree. `?timeout=` (seconds, up to 25) waits for the answer. Returns `{status: \"active\"}` while running, `{status: \"completed\", hpke_response_ciphertext, hpke_response_ephemeral_key}` sealed to the request's ephemeral key (the body is the `/api/literature/jobs/{jobId}` result), or `{status: \"failed\", error}`. Results are kept for an hour; an unknown id is `404 {\"status\":\"not_found\"}`.","operationId":"getEncryptedLiteratureStatus","parameters":[{"name":"hpke_protocol","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"description":"Retain the attested mode from the original encrypted request."},{"name":"requestId","in":"path","required":true,"description":"The requestId returned from POST /api/literature/encrypted.","schema":{"type":"string"}}],"responses":{"200":{"description":"Current job state; completed jobs carry the sealed result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","completed","failed"]},"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"hpke_response_ciphertext":{"type":"string"},"hpke_response_ephemeral_key":{"type":"string","description":"Attested static server key in authenticated mode; legacy ephemeral key otherwise."},"error":{"type":"string"}}}}}},"404":{"description":"Encrypted literature status is unavailable.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["not_found"]}}},"example":{"status":"not_found"}}}}}}},"/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":{"AttestedHpkeProtocol":{"type":"string","enum":["aubrai-attested-v1"],"description":"Opt into responses authenticated by the HPKE key bound to locally verified Phala attestation. Optional on legacy encrypted API requests; required for key-possession confirmation."},"PhalaAttestationEvidence":{"type":"object","required":["version","nonce","hpkePublicKey","origin","quote","eventLog","vmConfig","collateral"],"properties":{"version":{"type":"integer","enum":[1]},"nonce":{"type":"string","minLength":43,"maxLength":43},"hpkePublicKey":{"type":"string","format":"byte","description":"32-byte X25519 key bound to the quote report data."},"origin":{"type":"string","format":"uri","description":"Pinned Phala origin; the gateway does not rewrite this to its own origin."},"quote":{"type":"string","maxLength":131072,"description":"Hex-encoded Intel TDX quote."},"eventLog":{"type":"string","maxLength":1048576,"description":"JSON event log replayed against the quoted RTMR measurements."},"vmConfig":{"type":"string","maxLength":65536,"description":"Raw VM configuration JSON."},"collateral":{"type":"object","additionalProperties":true,"description":"DCAP certificate and revocation collateral; verify locally against the Intel production root."}}},"AttestationConfirmationRequest":{"type":"object","additionalProperties":false,"required":["hpke_protocol","hpke_ciphertext","hpke_ephemeral_public_key"],"properties":{"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"hpke_ciphertext":{"type":"string","minLength":1,"maxLength":3500,"description":"Base64 ciphertext sealing only the fresh challenge."},"hpke_ephemeral_public_key":{"type":"string","minLength":44,"maxLength":44,"pattern":"^[A-Za-z0-9+/]{43}=$","description":"Canonical base64 encoding of the client ephemeral X25519 public key."}}},"AttestationConfirmationResponse":{"type":"object","required":["hpke_protocol","hpke_response_ciphertext","hpke_response_ephemeral_key"],"properties":{"hpke_protocol":{"$ref":"#/components/schemas/AttestedHpkeProtocol"},"hpke_response_ciphertext":{"type":"string","description":"Authenticated encrypted challenge echo."},"hpke_response_ephemeral_key":{"type":"string","description":"The attested static server public key, despite the legacy field name."}}},"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.","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."}}}}}}