Bills
Vendor bills (the AP side of invoices). Same shape, same auto-fill, line rates default to item.purchase_price instead of selling price.
Resource shape
{
"bill_id": "bl_xyz",
"bill_number": "BILL-2026-0017",
"vendor_id": "ct_vendor",
"vendor_name": "ACME Supplies",
"date": "2026-05-12T00:00:00",
"due_date": "2026-05-26T00:00:00",
"reference_number": "Invoice #5523",
"place_of_supply": "IN-MH",
"currency_code": "INR",
"exchange_rate": 1.0,
"line_items": [ /* same shape as invoice line_items */ ],
"sub_total": 700,
"tax_total": 126,
"total": 826,
"payment_made": 0,
"balance": 826,
"status": "DRAFT", // DRAFT | OPEN | PARTIALLY_PAID | PAID | OVERDUE
"notes": null,
"created_time": "...",
"last_modified_time": "..."
}GET
/billsList billsAIBooks.bills.READSame query params as GET /invoices but with vendor_id instead of customer_id.
GET
/bills/{bill_id}Get one billAIBooks.bills.READPOST
/billsCreate a bill (DRAFT)AIBooks.bills.CREATERequired: vendor_id, date, place_of_supply, at least one line_items[]. Pass auto_approve: true to post the journal in the same call (status → OPEN).
POST /bills
Authorization: Bearer aibk_pat_…
Content-Type: application/json
{
"vendor_id": "ct_vendor",
"date": "2026-05-12T00:00:00",
"place_of_supply": "IN-MH",
"line_items": [{ "item_id": "it_widget", "quantity": 10 }],
"reference_number": "Invoice #5523",
"auto_approve": true
}PUT
/bills/{bill_id}Update header (DRAFT only)AIBooks.bills.UPDATEPOST
/bills/{bill_id}/approveApprove (DRAFT → OPEN)AIBooks.bills.UPDATEDELETE
/bills/{bill_id}Hard delete (DRAFT only)AIBooks.bills.DELETEAnti-duplicate guard
Creates with the same (vendor_id, date, total) as an existing posted bill are refused with code: validation.invalid_value. Use Idempotency-Key for retry-safety; pass a distinct reference_number to legitimately register multiple bills with the same vendor on the same day.