{"service":"ailang-parse","version":"0.9.0","base_url":"https://docparse.ailang.sunholo.com","protocol":"a2a/0.3","auth":{"schemes":[{"id":"api_key","type":"apiKey","in":"body","name":"apiKey","prefix":"dp_","description":"API key for data endpoints (parse, formats, unstructured)"},{"id":"api_key_header","type":"apiKey","in":"header","name":"X-API-Key","prefix":"dp_","description":"The same dp_ key as a header, used when the apiKey argument is omitted. Accepted by parse, convert, edit, upload/url and every keyed MCP tool, so an MCP client can inject the key without the model holding it."},{"id":"api_key_bearer","type":"http","scheme":"bearer","prefix":"dp_","description":"The same dp_ key as Authorization: Bearer dp_..., checked before X-API-Key. A Bearer token without the dp_ prefix is treated as a Firebase ID token, not an API key."},{"id":"firebase_bearer","type":"http","scheme":"bearer","issuer":"ailang-multivac-dev.firebaseapp.com","description":"Firebase ID token for device auth approval"}],"device_flow":{"request_url":"/api/v1/auth/device","poll_url":"/api/v1/auth/device/poll","approve_url":"https://www.sunholo.com/docparse/approve.html"}},"endpoints":[{"id":"parse","path":"/api/v1/parse","method":"POST","description":"Parse any document into structured content blocks. Accepts file upload (multipart/form-data), sample IDs, signed HTTPS URLs (sourceUrl), or GCS refs.","auth":{"required":true,"scheme":"api_key"},"quick_start":{"step_1":"Get an API key: POST /api/v1/auth/device","step_2_sample":"Parse a sample: curl -X POST $BASE/api/v1/parse -H 'Content-Type: application/json' -d '{\"sample_id\":\"sample_docx_basic\",\"outputFormat\":\"markdown\",\"apiKey\":\"dp_...\"}","step_3_upload":"Upload your own file: curl -X POST $BASE/api/v1/parse -F 'filepath=@your-file.docx' -F 'outputFormat=markdown' -F 'apiKey=dp_...'"},"file_upload":{"method":"multipart/form-data","field_name":"filepath","description":"Upload files directly using curl -F 'filepath=@file.docx'. The field name MUST be 'filepath'. All tiers can upload files within their size limits (Free: 10MB, Pro: 25MB, Business: 50MB).","example":"curl -X POST $BASE/api/v1/parse -F 'filepath=@report.docx' -F 'outputFormat=markdown' -F 'apiKey=dp_...'"},"input_schema":{"type":"object","content_types":["application/json","multipart/form-data"],"properties":{"filepath":{"type":"string","description":"File upload (multipart: -F 'filepath=@file.docx') or sample_id string (JSON). All tiers supported."},"sample_id":{"type":"string","description":"Built-in sample ID from GET /api/v1/samples (e.g. 'sample_docx_basic'). Works on all tiers."},"gcsRef":{"type":"string","description":"gs:// URI for pre-uploaded large files (Business tier only). Get upload URL via POST /api/v1/upload/url"},"sourceUrl":{"type":"string","description":"Public or signed https:// URL the server will fetch directly. Available on every tier; per-tier size cap (Free: 10MB, Pro: 25MB, Business: 50MB). Use this to skip the upload-via-your-backend step when files already live in cloud storage."},"outputFormat":{"type":"string","enum":["blocks","markdown","html","a2ui"],"default":"blocks"},"pdfBackend":{"type":"string","enum":["","pdftotext","docling","liteparse","ai"],"default":"","description":"PDF extraction backend. Empty string uses server default (pdftotext). 'pdftotext': fast deterministic text extraction via poppler — no AI cost. 'docling': IBM Docling layout analysis — no AI cost. 'liteparse': run-llama heading inference — no AI cost. 'ai': Gemini multimodal via Vertex AI — required for scanned/image-only PDFs. Explicit non-ai selection returns an error on failure rather than falling back to AI."}},"oneOf":[{"required":["filepath"]},{"required":["sample_id"]}]},"output_schema":{"type":"object","properties":{"result":{"type":"string","description":"JSON-encoded parse output"},"meta":{"$ref":"#/definitions/response_meta"}}},"error_codes":["INVALID_API_KEY","QUOTA_EXCEEDED","INPUT_NOT_FOUND","UNSUPPORTED_FORMAT","FORMAT_NOT_AVAILABLE","PARSE_FAILED","INVALID_ARGUMENT","TIER_UPGRADE_REQUIRED","INVALID_GCS_REF","FORBIDDEN","GCS_DOWNLOAD_FAILED","INVALID_SOURCE_URL","SOURCE_FETCH_FAILED","FILE_TOO_LARGE","WORKBOOK_TOO_COMPLEX","AI_PROVIDER_ERROR","PDF_BACKEND_FAILED"],"response_headers":["X-Request-Id","X-AilangParse-Format","X-AilangParse-Replayable","X-DocParse-Tier","X-DocParse-Quota-Remaining-Day","X-DocParse-Quota-Remaining-Month","X-DocParse-Quota-Remaining-Ai"],"error_envelope":{"error":{"code":"string — machine-readable error code","message":"string — human-readable description","retryable":"bool","suggested_fix":"string","details":"object — error-specific structured context"},"request_id":"string — top-level request_id, also returned as X-Request-Id header"},"cost":{"unit":"request","estimated_class":"small","quota_scope":"daily","ai_required_for":["png","jpg","gif","tiff","webp"],"ai_on_request_for":["pdf"]},"determinism":{"replayable":true,"sources_of_variance":["ai_model_version (images, and PDFs with pdfBackend=ai)"]},"examples":[{"id":"parse_docx_blocks_basic","request":{"sample_id":"sample_docx_formatting","outputFormat":"blocks"},"expected":{"status":200,"response_shape":{"blocks":"array","metadata":"object"},"deterministic":true,"notes":"Office formats always return identical output for same input"}}]},{"id":"convert","path":"/api/v1/convert","method":"POST","description":"Convert a document to another format. Deterministic conversion only — parse to blocks, then generate. Accepts the same input modes as /api/v1/parse (multipart upload, sample IDs, signed HTTPS URLs, GCS refs) plus a target format. DOCX output can be styled from your own template via referenceDoc.","auth":{"required":true,"scheme":"api_key"},"quick_start":{"step_1":"Get an API key: POST /api/v1/auth/device","step_2_sample":"Convert a sample: curl -X POST $BASE/api/v1/convert -H 'Content-Type: application/json' -d '{\"filepath\":\"sample_docx_basic\",\"target\":\"html\",\"apiKey\":\"dp_...\"}'","step_3_upload":"Convert your own file: curl -X POST $BASE/api/v1/convert -F 'filepath=@report.docx' -F 'target=pptx' -F 'apiKey=dp_...'","step_4_decode":"Binary targets return base64: read .encoding, then e.g. jq -r .content resp.json | base64 -d > out.pptx","step_5_template":"Style the docx from your own template: curl -X POST $BASE/api/v1/convert -F 'filepath=@report.md' -F 'target=docx' -F 'referenceDoc=@letterhead.docx' -F 'apiKey=dp_...'"},"file_upload":{"method":"multipart/form-data","field_name":"filepath","description":"Upload files directly using curl -F 'filepath=@file.docx'. The field name MUST be 'filepath'. A DOCX template may be uploaded alongside it in a second file field named 'referenceDoc'. Same per-tier size limits as /api/v1/parse (Free: 10MB, Pro: 25MB, Business: 50MB).","example":"curl -X POST $BASE/api/v1/convert -F 'filepath=@report.docx' -F 'target=odt' -F 'apiKey=dp_...'"},"input_schema":{"type":"object","content_types":["application/json","multipart/form-data"],"properties":{"filepath":{"type":"string","description":"File upload (multipart: -F 'filepath=@file.docx') or sample_id string (JSON). All tiers supported."},"target":{"type":"string","enum":["html","md","qmd","docx","pptx","xlsx","odt","odp","ods"],"description":"Output format. Case-insensitive; a leading dot is accepted, and 'markdown'/'htm'/'quarto' are aliases for md/html/qmd. Anything else returns UNSUPPORTED_TARGET_FORMAT, never a 500."},"gcsRef":{"type":"string","description":"gs:// URI for pre-uploaded large files (Business tier only). Get upload URL via POST /api/v1/upload/url"},"sourceUrl":{"type":"string","description":"Public or signed https:// URL the server will fetch directly. Available on every tier; per-tier size cap."},"pdfBackend":{"type":"string","enum":["","pdftotext","docling","liteparse","ai"],"default":"","description":"PDF extraction backend for the parse half of the conversion. Same semantics as /api/v1/parse."},"referenceDoc":{"type":"string","description":"A template .docx whose LOOK is applied to the generated document: styles, numbering, theme, embedded fonts, headers, footers and page setup. Same three input modes as filepath — multipart upload (-F 'referenceDoc=@letterhead.docx'), an https:// URL, or a gs:// ref (Business tier). DOCX target only; anything else returns REFERENCE_DOC_NOT_APPLICABLE. This is the CLI's --reference-doc (Quarto/Pandoc reference-doc) over HTTP."},"referenceSection":{"type":"string","description":"Which section of the template supplies page setup, headers and footers. 1-based, as Word numbers sections. Omit to take the template's last section — what Pandoc does, and right for single-section templates. Requires referenceDoc."},"tableStyle":{"type":"string","description":"Table style to bind generated tables to, named by styleId or by its Word name (e.g. 'Table Grid'). Must exist in the template; TABLE_STYLE_NOT_FOUND names the ones that do. Omit to use the template's own default table style. Requires referenceDoc."}},"required":["target"]},"output_schema":{"type":"object","description":"The generated document is returned inside JSON, not as a binary body. Branch on `encoding` to decode `content`.","properties":{"status":{"type":"string","const":"success"},"request_id":{"type":"string"},"source_format":{"type":"string","description":"Detected format family of the input document (e.g. 'zip-office')"},"source_subtype":{"type":"string","description":"Concrete input extension (e.g. 'docx')"},"target":{"type":"string","description":"Normalized target format"},"filename":{"type":"string","description":"Suggested filename: input stem + target extension"},"content_type":{"type":"string","description":"MIME type to save the decoded content as"},"encoding":{"type":"string","enum":["base64","utf8"],"description":"'base64' for the ZIP container targets (docx, pptx, xlsx, odt, odp, ods); 'utf8' for the text targets (html, md, qmd). Clients MUST branch on this rather than assume."},"size_bytes":{"type":"integer","description":"Decoded size of the generated document"},"reference_doc_applied":{"type":"boolean","description":"Whether a reference doc was applied. Assert on this rather than inferring templating from the bytes."},"template_parts_carried":{"type":"integer","description":"How many parts were carried over from the template (theme, fonts, headers, footers, images). 0 with reference_doc_applied true is legitimate: a template declaring no theme, headers or fonts has nothing to carry."},"content":{"type":"string","description":"The generated document, encoded per `encoding`"}}},"error_codes":["INVALID_API_KEY","QUOTA_EXCEEDED","UNSUPPORTED_TARGET_FORMAT","UNSUPPORTED_FORMAT","INPUT_NOT_FOUND","FORMAT_NOT_AVAILABLE","CONVERSION_FAILED","PARSE_FAILED","TIER_UPGRADE_REQUIRED","INVALID_GCS_REF","FORBIDDEN","GCS_DOWNLOAD_FAILED","INVALID_SOURCE_URL","SOURCE_FETCH_FAILED","FILE_TOO_LARGE","WORKBOOK_TOO_COMPLEX","AI_PROVIDER_ERROR","PDF_BACKEND_FAILED","REFERENCE_DOC_NOT_APPLICABLE","REFERENCE_DOC_NOT_FOUND","INVALID_REFERENCE_DOC","INVALID_REFERENCE_SECTION","TABLE_STYLE_NOT_FOUND","TABLE_STYLE_REQUIRES_REFERENCE_DOC","REFERENCE_SECTION_REQUIRES_REFERENCE_DOC"],"response_headers":["X-Request-Id","X-AilangParse-Format","X-AilangParse-Target","X-AilangParse-Encoding","X-DocParse-Tier","X-DocParse-Quota-Remaining-Day","X-DocParse-Quota-Remaining-Month","X-DocParse-Quota-Remaining-Ai"],"cost":{"unit":"request","estimated_class":"small","quota_scope":"daily","description":"One request per conversion, on the same counters as /api/v1/parse. Output size does not affect the charge. The AI sub-quota is consumed only when the SOURCE is parsed with AI (images, or a PDF with pdfBackend=ai) — generation itself is pure compute.","ai_required_for":["png","jpg","gif","tiff","webp"],"ai_on_request_for":["pdf"]},"determinism":{"replayable":true,"sources_of_variance":["ai_model_version (PDF/image sources only)"],"notes":"Office-to-Office conversion is pure compute and byte-identical for identical input. AI generation from a prompt is a separate cost profile and is NOT available on this endpoint."},"examples":[{"id":"convert_docx_to_html","request":{"filepath":"sample_docx_formatting","target":"html"},"expected":{"status":200,"response_shape":{"encoding":"utf8","content":"string"},"deterministic":true}},{"id":"convert_docx_with_reference_doc","request":{"filepath":"sample_docx_formatting","target":"docx","referenceDoc":"https://example.com/letterhead.docx"},"expected":{"status":200,"response_shape":{"encoding":"base64","reference_doc_applied":true},"deterministic":true,"notes":"The template supplies styles, theme, fonts and page furniture; the source document supplies the content. Upload the template instead with -F 'referenceDoc=@letterhead.docx'."}},{"id":"convert_docx_to_pptx","request":{"filepath":"sample_docx_formatting","target":"pptx"},"expected":{"status":200,"response_shape":{"encoding":"base64","content":"string"},"deterministic":true,"notes":"Decode content from base64 to get a valid .pptx"}}]},{"id":"formats","path":"/api/v1/formats","method":"GET","description":"List all supported input, output, and generation formats","auth":{"required":false},"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":true,"sources_of_variance":[]}},{"id":"health","path":"/api/v1/health","method":"GET","description":"Service health, version, uptime","auth":{"required":false},"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":true,"sources_of_variance":["uptime_ms"]}},{"id":"unstructured","path":"/general/v0/general","method":"POST","description":"Drop-in Unstructured.io API replacement","auth":{"required":true,"scheme":"api_key"},"input_schema":{"type":"object","properties":{"path":{"type":"string"},"strategy":{"type":"string","enum":["auto","hi_res","fast"],"default":"auto"}},"required":["path"]},"cost":{"unit":"request","quota_scope":"daily"},"determinism":{"replayable":true,"sources_of_variance":[]}},{"id":"samples","path":"/api/v1/samples","method":"GET","description":"List available sample documents for testing","auth":{"required":false},"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":true,"sources_of_variance":[]}},{"id":"estimate","path":"/api/v1/estimate","method":"POST","description":"Estimate cost and latency before parsing — no auth required","auth":{"required":false},"input_schema":{"type":"object","properties":{"filepath":{"type":"string"},"outputFormat":{"type":"string","enum":["blocks","markdown","html","a2ui"]}},"required":["filepath"]},"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":true,"sources_of_variance":[]}},{"id":"pricing","path":"/api/v1/pricing","method":"GET","description":"Machine-readable pricing tiers and credit costs","auth":{"required":false},"cost":{"unit":"none","quota_scope":"none"}},{"id":"keys_usage","path":"/api/v1/keys/usage","method":"POST","description":"Usage counters and quota limits for a key","auth":{"required":true,"scheme":"api_key"},"cost":{"unit":"none","quota_scope":"none"}},{"id":"device_auth","path":"/api/v1/auth/device","method":"POST","description":"Request device authorization code (RFC 8628)","auth":{"required":false},"input_schema":{"type":"object","properties":{"label":{"type":"string","description":"Agent label for identification"},"scope":{"type":"string","default":"parse"}}},"cost":{"unit":"none","quota_scope":"none"}},{"id":"device_poll","path":"/api/v1/auth/device/poll","method":"POST","description":"Poll for device authorization approval","auth":{"required":false},"input_schema":{"type":"object","properties":{"device_code":{"type":"string"}},"required":["device_code"]},"error_codes":["AUTHORIZATION_PENDING","DEVICE_CODE_EXPIRED"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"device_inspect","path":"/api/v1/auth/device/inspect","method":"POST","description":"Inspect a pending device authorization request to see where it came from (IP, User-Agent, Referer, age) before approving. Used by the dashboard /approve.html trust panel. NO authentication — possession of the user_code is the proof.","auth":{"required":false},"input_schema":{"type":"object","properties":{"userCode":{"type":"string","description":"The user_code to inspect (e.g. ABCD-1234)"}},"required":["userCode"]},"output_schema":{"type":"object","properties":{"status":{"type":"string"},"user_code":{"type":"string"},"label":{"type":"string"},"scope":{"type":"string"},"created_at":{"type":"string"},"expires_at":{"type":"string"},"requesting_client":{"type":"object","properties":{"ip":{"type":"string"},"user_agent":{"type":"string"},"referer":{"type":"string"},"classification":{"type":"string"}}}}},"error_codes":["INVALID_ARGUMENT","INPUT_NOT_FOUND","INTERNAL_ERROR"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"device_approve","path":"/api/v1/auth/device/approve","method":"POST","description":"Approve a pending device authorization. Called from the dashboard after the user signs in via Firebase. Requires Firebase ID token in Authorization: Bearer header.","auth":{"required":true,"scheme":"firebase_bearer"},"input_schema":{"type":"object","properties":{"userCode":{"type":"string","description":"The user_code shown by the device (e.g. ABCD-1234)"}},"required":["userCode"]},"error_codes":["INVALID_ARGUMENT","DEVICE_CODE_EXPIRED","AUTH_ERROR"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"keys_list","path":"/api/v1/keys/list","method":"POST","description":"List API keys belonging to the authenticated user. Authenticates via API key in body — returns all keys owned by that key's user.","auth":{"required":true,"scheme":"api_key"},"input_schema":{"type":"object","properties":{"apiKey":{"type":"string","description":"Any active dp_ key owned by the user"}},"required":["apiKey"]},"error_codes":["INVALID_API_KEY"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"keys_revoke","path":"/api/v1/keys/revoke","method":"POST","description":"Revoke an API key. Marks the key inactive in Firestore — subsequent requests with this key will fail.","auth":{"required":true,"scheme":"api_key"},"input_schema":{"type":"object","properties":{"keyId":{"type":"string","description":"The 12-char keyId to revoke"},"apiKey":{"type":"string","description":"Any active key owned by the same user (proves ownership)"}},"required":["keyId","apiKey"]},"error_codes":["INVALID_API_KEY","FORBIDDEN","INPUT_NOT_FOUND"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"keys_rotate","path":"/api/v1/keys/rotate","method":"POST","description":"Rotate an API key: revoke the old one and mint a fresh key with the same label, tier, and userId. The new key is shown once.","auth":{"required":true,"scheme":"api_key"},"input_schema":{"type":"object","properties":{"keyId":{"type":"string","description":"The 12-char keyId to rotate"},"apiKey":{"type":"string","description":"The current key (must match keyId)"}},"required":["keyId","apiKey"]},"error_codes":["INVALID_API_KEY","FORBIDDEN"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"upload_url","path":"/api/v1/upload/url","method":"POST","description":"Get a pre-authenticated GCS upload URL for large files exceeding the 32MB request limit (Business tier only). For files under 32MB, use direct multipart upload: curl -F 'filepath=@file.docx' to POST /api/v1/parse instead.","auth":{"required":true,"scheme":"api_key"},"input_schema":{"type":"object","properties":{"filename":{"type":"string","description":"Original filename"},"mimeType":{"type":"string","description":"MIME type (e.g. application/pdf, image/png)"}},"required":["filename","mimeType"]},"output_schema":{"type":"object","properties":{"upload_url":{"type":"string","description":"PUT file content to this URL"},"gcs_ref":{"type":"string","description":"Pass this to POST /api/v1/parse as gcsRef"},"method":{"type":"string","enum":["PUT"]},"content_type":{"type":"string"}}},"error_codes":["INVALID_API_KEY","TIER_UPGRADE_REQUIRED","SERVICE_UNAVAILABLE","GCS_UPLOAD_INIT_FAILED"],"cost":{"unit":"none","quota_scope":"none"},"tier_required":"business"},{"id":"requests_replay","path":"/api/v1/requests/replay","method":"POST","description":"Replay a previous parse request by request_id. Requires authentication — the authenticated user must own the original request. Requests made while the account had request history turned off keep only metadata and return CONTENT_NOT_STORED (history rows carry content_stored).","auth":{"required":true,"note":"API key or Firebase JWT required; ownership verified"},"input_schema":{"type":"object","properties":{"request_id":{"type":"string","description":"The request_id from a previous parse response meta"}},"required":["request_id"]},"error_codes":["INVALID_ARGUMENT","AUTH_ERROR","INPUT_NOT_FOUND","CONTENT_NOT_STORED"],"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":true,"sources_of_variance":[]}},{"id":"requests_history","path":"/api/v1/requests/history","method":"POST","description":"List parse history for a user. Returns recent parse requests with metadata.","auth":{"required":true,"scheme":"api_key"},"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":false,"sources_of_variance":["new_requests_since_last_call"]}},{"id":"account_history","path":"/api/v1/account/history","method":"POST","description":"Read or change the account's request-history setting. On by default: parsed output (up to 10KB) is kept with each request for replay. Turn it off to keep only request metadata, with the file name reduced to its extension. Applies to every API key on the account, from the next request; the response reports keys_updated, keys_failed and keys_complete. Also available over MCP as mcpAccount actions history, history_on and history_off. Records are kept for the plan's history period (30 days free, 6 months pro, 12 months business).","auth":{"required":true,"note":"API key (args[0]) or Firebase JWT; the setting applies to the authenticated account only"},"input_schema":{"type":"object","properties":{"store_history":{"type":"boolean","description":"Omit to read the current value; true keeps content, false keeps metadata only"}}},"error_codes":["AUTH_ERROR","SETTING_WRITE_FAILED"],"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":false,"sources_of_variance":["account_setting"]}},{"id":"requests_delete","path":"/api/v1/requests/delete","method":"POST","description":"Permanently delete the account's request records (metadata and any stored output): one by request_id, or all of them. Not available over MCP.","auth":{"required":true,"note":"API key (args[0]) or Firebase JWT; only the authenticated account's records can be deleted"},"input_schema":{"type":"object","properties":{"request_id":{"type":"string","description":"Delete this one request (must belong to the caller)"},"all":{"type":"boolean","description":"true deletes every request record on the account"}}},"output_schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","partial"]},"deleted":{"type":"integer"},"failed":{"type":"integer"},"retryable":{"type":"boolean"}}},"error_codes":["AUTH_ERROR","INVALID_ARGUMENT","INPUT_NOT_FOUND"],"cost":{"unit":"none","quota_scope":"none"},"determinism":{"replayable":false,"sources_of_variance":["stored_records"]}},{"id":"referral_claim","path":"/api/v1/referral/claim","method":"POST","description":"Record a referral attribution at sign-in. Called by the dashboard and approve pages when localStorage.docparse_ref is set. The userId and email come only from the verified Firebase token; unknown or malformed codes are a silent no-op; the first successful claim for an account wins permanently and later claims never switch partners. Not available over MCP.","auth":{"required":true,"scheme":"firebase_bearer"},"input_schema":{"type":"object","properties":{"ref":{"type":"string","description":"The referral code from the partner link (localStorage.docparse_ref)"}}},"error_codes":["AUTH_ERROR"],"cost":{"unit":"none","quota_scope":"none"}},{"id":"referral_mine","path":"/api/v1/referral/mine","method":"POST","description":"The data behind the partner page (docparse/partners.html). Matches the caller's verified Firebase email against the referrers collection, then returns each referred account's email, sign-up date, plan, status (signed_up / tried / using / paying, computed server-side) and document counters. Never returns document content or anything from the request audit log. Callers who are not partners get {partner: false}. Not available over MCP.","auth":{"required":true,"scheme":"firebase_bearer"},"output_schema":{"type":"object","properties":{"partner":{"type":"boolean"},"code":{"type":"string"},"label":{"type":"string"},"link":{"type":"string"},"totals":{"type":"object","description":"signedUp / using / paying counts"},"people":{"type":"array","description":"Newest first; says documents*, never requests*"}}},"error_codes":["AUTH_ERROR"],"cost":{"unit":"none","quota_scope":"none"}}],"definitions":{"response_meta":{"type":"object","properties":{"request_id":{"type":"string","description":"Unique request identifier for replay/audit"},"quota_used":{"type":"integer"},"quota_remaining":{"type":"integer"},"replayable":{"type":"boolean"},"sample_id":{"type":"string","description":"If request used a sample, its ID"}}},"error_response":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["INVALID_API_KEY","QUOTA_EXCEEDED","INPUT_NOT_FOUND","UNSUPPORTED_FORMAT","PARSE_FAILED","INVALID_ARGUMENT","INTERNAL_ERROR","AI_UNAVAILABLE","AI_PROVIDER_ERROR","PDF_BACKEND_FAILED","AUTHORIZATION_PENDING","DEVICE_CODE_EXPIRED"]},"message":{"type":"string"},"retryable":{"type":"boolean"},"suggested_fix":{"type":"string"}},"required":["code","message","retryable"]}}}},"tool_definitions":{"mcp":"/mcp/","a2a":"/.well-known/agent.json","openapi":"/api/_meta/openapi.json"}}
