{"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":"Analysis","description":"Aubrai data analysis agent — **$0.05** per request"},{"name":"System","description":"Health and operational endpoints"}],"paths":{"/api/deep-research/start":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"range","minPrice":"$0.20","maxPrice":"$8.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":["steering","smart","fully-autonomous"],"default":"steering","description":"Research depth. Determines pricing: steering ($0.20), smart ($1.00), fully-autonomous ($8.00)."},"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":"200000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0xa06D...cDa9F","maxTimeoutSeconds":1800,"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":"200000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0xa06D...cDa9F","maxTimeoutSeconds":1800,"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/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.\n\n**Modes:**\n- `fast: true` → quick conversational answer (3–6s)\n- `fast: false` or omitted → deep research with citations (15–25s)\n\n**Poll** `/api/chat/status/{requestId}` every ~2s 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":"true → quick conversational answer (3–6s). false/omit → deep research with citations (15–25s)."}}}}}},"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":{"type":"object","nullable":true,"properties":{"text":{"type":"string"},"responseTime":{"type":"integer"}}},"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":{"text":"Response with citations...","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 a Tinfoil TEE. Proxied to the enclave after x402 payment verification. Requires x402 payment of $0.02. Response is 200 with ciphertext inline, or 202 with `pollUrl`.\n\n**Scheme:** X25519 ECDH → HKDF-SHA256 → XChaCha20-Poly1305. **Not standard HPKE — do not use an HPKE library.**\n\n**Protocol (plaintext = `{ \"message\": \"...\" }`):**\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:])`","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","description":"Path to poll for status."}}},"example":{"requestId":"abc123","status":"queued","pollUrl":"/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.","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.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["queued","active"]}}},"examples":{"queued":{"summary":"Still queued","value":{"status":"queued"}},"active":{"summary":"Processing","value":{"status":"active"}}}}}},"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 search (TEE)","description":"Submit an encrypted literature query to the Aubrai research agent running inside a Tinfoil TEE. Always async — long-poll `pollUrl` for the encrypted result. Requires x402 payment of $0.03.\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 = `{ \"question\": \"...\", \"mode\"?: \"fast\"|\"deep\", \"maxResults\"?, \"sources\"?, \"year\"?, \"date_from\"?, \"date_to\"? }`):**\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[]`, `evidenceScore`, `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 encrypted literature query, 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":{"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","description":"Path to long-poll for status."}}},"example":{"requestId":"abc123","status":"pending","pollUrl":"/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 contains { answer, references[], evidenceScore, jobId, status, sourceErrors }.","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 arxiv, pubmed, and clinical-trials. Requires x402 payment of $0.03. For deep mode, poll the returned jobId.","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":{"type":"object","required":["question"],"properties":{"question":{"type":"string","minLength":1,"maxLength":8192,"description":"The research question.","example":"What is the effect of rapamycin on aging?"},"mode":{"type":"string","enum":["fast","deep"],"default":"fast","description":"fast returns immediately; deep is async — poll via jobId."},"maxResults":{"type":"integer","description":"Maximum number of results."},"perSourceLimit":{"type":"integer","description":"Maximum results per source."},"sources":{"type":"array","items":{"type":"string","enum":["arxiv","pubmed","clinical-trials"]},"description":"Filter to specific sources."}}}}}},"responses":{"200":{"description":"Search result (fast mode) or queued job (deep mode).","content":{"application/json":{"schema":{"type":"object","properties":{"answer":{"type":"string","nullable":true},"formattedAnswer":{"type":"string","nullable":true},"references":{"type":"array","nullable":true,"items":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"},"year":{"type":"number","nullable":true},"source":{"type":"string","nullable":true},"item_date":{"type":"string","nullable":true,"description":"Publication date in YYYY-MM-DD format, extracted from source metadata."}}}},"contextPassages":{"type":"array","items":{"type":"object"},"nullable":true},"jobId":{"type":"string","nullable":true,"description":"Poll this via GET /api/literature/jobs/{jobId} when using deep mode."},"status":{"type":"string","nullable":true},"reasoning":{"type":"array","items":{"type":"string"},"nullable":true}}}}}},"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 deep-mode literature search job.","operationId":"getLiteratureJob","parameters":[{"name":"jobId","in":"path","required":true,"description":"The jobId returned from POST /api/literature (deep mode).","schema":{"type":"string"}}],"responses":{"200":{"description":"Job status and result.","content":{"application/json":{"schema":{"type":"object","properties":{"answer":{"type":"string","nullable":true},"formattedAnswer":{"type":"string","nullable":true},"references":{"type":"array","nullable":true,"items":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"},"year":{"type":"number","nullable":true},"source":{"type":"string","nullable":true},"item_date":{"type":"string","nullable":true,"description":"Publication date in YYYY-MM-DD format, extracted from source metadata."}}}},"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}}}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/analysis":{"post":{"x-payment-info":{"protocols":["x402"],"pricingMode":"fixed","price":"$0.05"},"tags":["Analysis"],"summary":"Start a data analysis task","description":"Start an async data analysis task. Requires x402 payment of $0.05. Poll the returned id via GET /api/analysis/tasks/{taskId}.","operationId":"startAnalysisRun","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":["taskDescription"],"properties":{"taskDescription":{"type":"string","minLength":1,"maxLength":8192,"description":"Description of the analysis task.","example":"Analyze the correlation between sleep duration and longevity across the provided datasets."},"fileIds":{"type":"array","items":{"type":"string"},"description":"IDs of previously uploaded files to include."}}}}}},"responses":{"200":{"description":"Task started.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true},"status":{"type":"string","nullable":true},"success":{"type":"boolean","nullable":true},"answer":{"type":"string","nullable":true},"directAnswer":{"type":"string","nullable":true},"reasoning":{"type":"array","items":{"type":"string"},"nullable":true},"artifacts":{"type":"array","items":{"type":"object"},"nullable":true}}}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Missing required field: taskDescription"}}}},"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/analysis/tasks/{taskId}":{"get":{"tags":["Analysis"],"summary":"Poll data analysis task","description":"Poll the status and results of a data analysis task.","operationId":"getAnalysisTask","parameters":[{"name":"taskId","in":"path","required":true,"description":"The task id returned from POST /api/analysis.","schema":{"type":"string"}}],"responses":{"200":{"description":"Task status and result.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true},"status":{"type":"string","nullable":true},"success":{"type":"boolean","nullable":true},"answer":{"type":"string","nullable":true},"directAnswer":{"type":"string","nullable":true},"reasoning":{"type":"array","items":{"type":"string"},"nullable":true},"artifacts":{"type":"array","items":{"type":"object"},"nullable":true}}}}}},"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":{"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}}}}}}