{"openapi":"3.1.0","info":{"title":"GET /api/v1/bills/pay-plan","version":"1.0.0","description":"Pay plan: which bills to pay first"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/bills/pay-plan":{"get":{"tags":["bills"],"summary":"Pay plan: which bills to pay first","description":"Rank open bills by what to pay first — late bills, then open early-pay discounts, then bills due within a week, then the rest — with a reason for each, cash on hand, and counts of the bills left out (on hold, payment initiated, awaiting approval). Read-only and deterministic.","operationId":"get_bill_pay_plan","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"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_SuggestPaymentPriorityResponse_"}}}},"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":"get_bill_pay_plan_api_v1_bills_pay_plan_get"}}},"components":{"schemas":{"PayPlanBucket":{"properties":{"count":{"type":"integer","title":"Count","default":0},"cents":{"type":"integer","title":"Cents","default":0}},"type":"object","title":"PayPlanBucket"},"PaymentPriorityItem":{"properties":{"bill_id":{"type":"string","title":"Bill Id","description":"Bill ID"},"bill_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bill Number","description":"Vendor's bill number"},"vendor_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Id","description":"Vendor ID"},"vendor_name":{"type":"string","title":"Vendor Name","description":"Vendor name"},"amount":{"type":"integer","title":"Amount","description":"Balance due in cents"},"original_amount":{"type":"integer","title":"Original Amount","description":"Bill amount in cents","default":0},"due_date":{"type":"string","title":"Due Date","description":"Due date (YYYY-MM-DD), empty when unset"},"days_until_due":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Until Due","description":"Days from today to the due date; negative when late"},"band":{"type":"string","enum":["overdue","discount","due_soon","later","no_due_date"],"title":"Band","description":"overdue (past due), discount (early-pay discount closes inside the window), due_soon (due inside the window), later, no_due_date","default":"later"},"recommended":{"type":"boolean","title":"Recommended","description":"Pay inside the window (overdue, discount or due_soon)","default":false},"rank":{"type":"integer","title":"Rank","description":"1 = pay first","default":0},"priority_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Priority Score","description":"Priority score 0-1"},"reason":{"type":"string","title":"Reason","description":"Why the bill sits at this rank"},"discount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Discount Cents","description":"Early-pay discount still available, in cents"},"discount_deadline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Discount Deadline","description":"Last day the early-pay discount applies (YYYY-MM-DD)"}},"type":"object","required":["bill_id","vendor_name","amount","due_date","priority_score","reason"],"title":"PaymentPriorityItem"},"SuccessEnvelope_SuggestPaymentPriorityResponse_":{"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/SuggestPaymentPriorityResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[SuggestPaymentPriorityResponse]"},"SuggestPaymentPriorityResponse":{"properties":{"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of","description":"Date the plan was ranked against"},"window_days":{"type":"integer","title":"Window Days","description":"Days ahead that count as due soon","default":7},"recommendations":{"items":{"$ref":"#/components/schemas/PaymentPriorityItem"},"type":"array","title":"Recommendations"},"total_ranked":{"type":"integer","title":"Total Ranked","description":"Payable bills ranked; recommendations holds the first 250","default":0},"cash_available_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cash Available Cents","description":"Cash in bank accounts (bank-reported for linked accounts, book balance otherwise); null when the business has no bank account"},"cash_accounts":{"type":"integer","title":"Cash Accounts","description":"Bank accounts in the cash figure","default":0},"projected_balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Projected Balance","description":"Cash left after paying every recommended bill, in cents"},"pay_now":{"$ref":"#/components/schemas/PayPlanBucket"},"later":{"$ref":"#/components/schemas/PayPlanBucket"},"on_hold":{"$ref":"#/components/schemas/PayPlanBucket"},"in_flight":{"$ref":"#/components/schemas/PayPlanBucket","description":"Payment initiated, waiting for the bank transaction"},"awaiting_approval":{"$ref":"#/components/schemas/PayPlanBucket","description":"Pending-approval bills, not payable until approved"},"drafts":{"$ref":"#/components/schemas/PayPlanBucket","description":"Draft bills, not payable until reviewed and approved"},"discounts_available_cents":{"type":"integer","title":"Discounts Available Cents","description":"Early-pay discounts the recommended bills can still earn","default":0},"held_bills_skipped":{"type":"integer","title":"Held Bills Skipped","description":"Bills left out because they are on payment hold.","default":0}},"type":"object","title":"SuggestPaymentPriorityResponse","description":"Ranked pay plan for open bills, dated and sized against cash on hand."},"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":[]}]}