{"openapi":"3.1.0","info":{"title":"POST /api/v1/bills/ai-create","version":"1.0.0","description":"AI-extract draft bills from documents"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/bills/ai-create":{"post":{"tags":["bills"],"summary":"AI-extract draft bills from documents","description":"Upload pasted text, PDFs, images, Excel files, or a CSV to extract draft bill entities using AI. Returns draft bills in 'received' status format ready for user review before creation.","operationId":"ai_create_bill_payload","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillAICreatePayloadRequest"},"example":{"single_bill_s3_keys":["business-id/uuid-bill1.pdf","business-id/uuid-bill2.png"]}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_BillAICreatePayloadResponse_"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: due_date: Input should be a valid date","errors":{"due_date":"Input should be a valid date"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"}}}}},"x-fastapi-operation-id":"ai_create_bill_payload_api_v1_bills_ai_create_post"}}},"components":{"schemas":{"BillAICreatePayloadRequest":{"properties":{"pasted_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pasted Text","description":"Raw text content to extract a bill from. Limit 1 bill per text input. Mutually exclusive with pasted_text_s3_key."},"pasted_text_s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pasted Text S3 Key","description":"S3 key of pasted text content. Limit 1 bill per text input. Mutually exclusive with pasted_text."},"single_bill_s3_keys":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Single Bill S3 Keys","description":"S3 keys of individual bill documents (PDFs, images, Excel). Each file is processed independently."},"multi_bill_s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Multi Bill S3 Key","description":"S3 key of a CSV file containing multiple bills."}},"type":"object","title":"BillAICreatePayloadRequest","description":"Request schema for AI-powered bill extraction from uploaded documents.\n\nProvide one or more source inputs. The AI will analyze each source and\nextract draft bill entities from the content.\n\nSource types:\n- pasted_text: Raw text content to extract a bill from (limit 1 bill)\n- pasted_text_s3_key: S3 key of pasted text content (limit 1 bill)\n- single_bill_s3_keys: S3 keys of individual bill documents (PDFs, images, Excel)\n- multi_bill_s3_key: S3 key of a CSV or Excel file containing multiple bills","example":{"single_bill_s3_keys":["business-id/uuid-bill1.pdf","business-id/uuid-bill2.png"]},"examples":[{"single_bill_s3_keys":["business-id/uuid-bill1.pdf","business-id/uuid-bill2.png"]}]},"BillAICreatePayloadResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DraftBill"},"type":"array","title":"Items","description":"List of draft bill entities extracted by AI."},"errors":{"items":{"$ref":"#/components/schemas/FileProcessingError"},"type":"array","title":"Errors","description":"List of per-file errors for files that could not be processed."}},"type":"object","required":["items"],"title":"BillAICreatePayloadResponse","description":"Response schema for AI-powered bill extraction.\n\nReturns a list of draft bill entities extracted from the uploaded documents.\nEach draft bill contains all fields needed to create a bill in 'received' status.\nFiles that fail are reported in the ``errors`` list rather than causing\nthe entire request to fail.","example":{"errors":[],"items":[{"amount":15000,"bill_number":"INV-12345","confidence":0.92,"currency":"USD","description":"Office supplies","expense_category":"Office Supplies","source":"single_file","type":"one_time","vendor_name":"Office Depot"}]},"examples":[{"errors":[],"items":[{"amount":15000,"bill_number":"INV-12345","confidence":0.92,"currency":"USD","description":"Office supplies","expense_category":"Office Supplies","source":"single_file","type":"one_time","vendor_name":"Office Depot"}]}]},"DraftBill":{"properties":{"vendor_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Name","description":"Vendor/company name extracted by AI. Use to match or create a vendor."},"amount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Amount","description":"Bill amount in cents extracted by AI."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Description of what the bill is for."},"bill_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bill Number","description":"Bill/invoice number from the vendor document."},"bill_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bill Date","description":"Date of the bill (YYYY-MM-DD) extracted by AI."},"expense_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expense Category","description":"Expense category suggested by AI (e.g., 'Office Supplies', 'Rent')."},"vendor_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Id","description":"Matched vendor UUID (if the vendor was found in the system)."},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency","description":"Currency code (USD, CAD, AUD, EUR, or GBP). Defaults to USD.","default":"USD"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"Bill type: 'recurring' or 'one_time'. Defaults to 'one_time'.","default":"one_time"},"received_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Received On","description":"Date bill was received (ISO 8601). Defaults to bill_date if available."},"due_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Due On","description":"Payment due date (ISO 8601). The extracted invoice due date, or — when the business counts terms from the receipt date — upload day plus payment terms (see ``due_date_policy``)."},"due_date_policy":{"anyOf":[{"$ref":"#/components/schemas/DraftBillDueDatePolicy"},{"type":"null"}],"description":"How ``due_on`` was derived when the business's due-date basis is ``received_date``. Null under the default invoice-date basis."},"s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"S3 Key","description":"S3 key of the source document for this bill."},"ledger_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ledger Id","description":"Matched expense ledger UUID (if matched from expense_category)."},"journal_entry_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Journal Entry Date","description":"Date for journal entry (ISO 8601). Defaults to received_on."},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence","description":"AI confidence score for this extraction (0.0-1.0)."},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Source type: 'pasted_text', 'single_file', or 'multi_file'."},"source_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Filename","description":"Original filename or S3 key of the source document."}},"type":"object","title":"DraftBill","description":"A draft bill entity extracted by AI, ready for user review before creation.\n\nAssumes 'received' status — includes all possible params for creating a bill\nin the received status. Fields are optional since AI extraction may not\npopulate every field.","example":{"amount":15000,"bill_date":"2026-02-10","bill_number":"INV-12345","confidence":0.92,"currency":"USD","description":"Office supplies - paper and toner","due_on":"2026-03-12","expense_category":"Office Supplies","received_on":"2026-02-10","source":"single_file","type":"one_time","vendor_name":"Office Depot"},"examples":[{"amount":15000,"bill_date":"2026-02-10","bill_number":"INV-12345","confidence":0.92,"currency":"USD","description":"Office supplies - paper and toner","due_on":"2026-03-12","expense_category":"Office Supplies","received_on":"2026-02-10","source":"single_file","type":"one_time","vendor_name":"Office Depot"}]},"DraftBillDueDatePolicy":{"properties":{"basis":{"type":"string","enum":["invoice_date","received_date"],"title":"Basis","description":"Business due-date basis that produced ``due_on``."},"anchor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Anchor","description":"Date (YYYY-MM-DD) the payment terms were counted from — the receipt date."},"term_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Term Days","description":"Payment-term length in days that was applied."},"term_source":{"anyOf":[{"type":"string","enum":["vendor_default","invoice_span","business_default"]},{"type":"null"}],"title":"Term Source","description":"Where the term length came from: the matched vendor's default term, the span the invoice itself implies (due date minus invoice date), or the business's default term."},"invoice_due_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invoice Due On","description":"Due date as printed on / extracted from the invoice (YYYY-MM-DD), for reference."}},"type":"object","required":["basis"],"title":"DraftBillDueDatePolicy","description":"How a draft bill's ``due_on`` was derived from the business's due-date basis.\n\nPresent only when the business runs payment terms from the receipt date\n(``ap_due_date_basis = received_date``) and a due date was derived; absent\nunder the default invoice-date basis."},"FileProcessingError":{"properties":{"s3_key":{"type":"string","title":"S3 Key","description":"S3 key of the file that failed."},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename","description":"Original filename (if determinable from the S3 key)."},"error":{"type":"string","title":"Error","description":"Human-readable error description."}},"type":"object","required":["s3_key","error"],"title":"FileProcessingError","description":"Error detail for a file that failed during AI extraction."},"SuccessEnvelope_BillAICreatePayloadResponse_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/BillAICreatePayloadResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[BillAICreatePayloadResponse]"},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}