A REST API for AI agents and integrations to generate catering quotes, retrieve price breakdowns, and download printable invoice PDFs.
Get available menu items and schema
GET /api/invoice/schema -- returns all protein/appetizer/addon IDs, prices, and a full example payload.
POST your order to generate an invoice
POST /api/invoice -- returns JSON price breakdown, BOM (ingredients prep list), and a pdfUrl.
Open the PDF URL to get the printable invoice
GET /api/invoice/pdf?token=<token> -- renders a standalone HTML invoice page. Use browser print / "Save as PDF". Token expires in 30 minutes.
/api/invoice/schemaReturns all available item IDs (proteins, appetizers, add-ons, extras) with prices, the full input schema with field descriptions, and a ready-to-use example payload. No request body needed.
Try it live/api/invoiceSubmit a full InvoiceData JSON body. Returns price breakdown, BOM, and a temporary PDF link.
application/json/api/invoice/pdf?token=<token>Renders a self-contained HTML invoice page for the given token (from the POST response pdfUrl). Optimized for print. Includes a "Save as PDF" button. Token expires in 30 minutes.
| Field | Type | Notes |
|---|---|---|
| contactInfo | object | clientName, email, phone, eventDate, eventTime, eventAddress, specialNotes |
| adultCount | number | Required. Number of adult guests. |
| childCount | number | Number of children (age < 13). Default 0. |
| mode | "detailed" | "quick" | Detailed: per-guest proteins. Quick: aggregate counts. |
| guests[] | GuestRow[] | Required for detailed mode. Each guest has proteins[], name, isChild, etc. |
| quickCountItems[] | QuickCountItem[] | Required for quick mode. itemId, category, qty, childQty. |
| partyWideAddons | string[] | e.g. ["noodles"]. Applied to every guest. |
| partyExtras[] | { id, qty }[] | Party-wide extras like gyoza, edamame. See schema for IDs. |
| paymentMethod | "cash" | "credit_card" | Credit card adds a fee. |
| depositAmount | number | Default $100. Deducted from balance due. |
| promotions[] | { id, label, amount }[] | Discounts. Amount is $ deducted from subtotal. |
| travelFee | object | homeZipcode, ratePerMile (def $2), freeRadiusMiles (def 20), distanceMiles, manualOverride. |
| selectedGratuityRate | number | null | e.g. 0.18 for 18%. null = no gratuity selected. |
Use quick mode when you just need aggregate protein counts rather than per-guest assignments.
{
"contactInfo": {
"clientName": "Jane Doe",
"phone": "555-867-5309",
"eventDate": "2026-05-20",
"eventTime": "6:00 PM",
"eventAddress": "456 Oak Ave, Pasadena, CA 91101"
},
"adultCount": 8,
"childCount": 2,
"mode": "quick",
"guests": [],
"quickCountItems": [
{ "itemId": "chicken", "category": "protein", "qty": 8, "childQty": 2 },
{ "itemId": "shrimp", "category": "protein", "qty": 6, "childQty": 0 },
{ "itemId": "filet_mignon", "category": "protein", "qty": 4, "childQty": 0 }
],
"partyWideAddons": [],
"partyExtras": [],
"paymentMethod": "cash",
"depositAmount": 100,
"promotions": [],
"travelFee": {
"homeZipcode": "91748",
"ratePerMile": 2,
"freeRadiusMiles": 20,
"distanceMiles": null,
"manualOverride": null
},
"selectedGratuityRate": null
}GET /api/invoice/schema to cache available item IDs and prices.InvoiceData JSON body using the IDs from step 1.POST /api/invoice with the JSON body.invoice breakdown to your user. Share the pdfUrl for them to download/print.distanceMiles in travelFee if you can calculate the distance. Otherwise leave it null and set manualOverride to a flat dollar amount.pdfUrl token expires in 30 minutes. Generate a new one by POSTing again if needed.{ ok: false, errors: [...] } with HTTP 400. Use the error messages to fix and retry.bom array in the response is the chef's prep list (bill of materials) -- useful for operational planning.// 400 Bad Request
{
"ok": false,
"errors": [
"adultCount must be a non-negative number.",
"mode must be 'detailed' or 'quick'."
]
}
// 404 Not Found (expired PDF token)
{
"ok": false,
"error": "Token not found or expired (tokens expire after 30 minutes)."
}Real Hibachi Invoice API v1.0 · No authentication required · CORS enabled