Itemized bill split calculator
On a 35 food bill with 2.8 tax and a 6.3 tip, Alice, who ordered 20.5 of the food, owes 25.83 and Bob owes 18.27. Assign each dish and drink to a person, and the tax and tip follow what each one actually ordered. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Tax
- 2.8
- Service
- 6.3
- Item count
- 4
- Person count
- 2
- Food total
- 35
- Grand total
- 44.1
Restaurant checks and group orders are rarely fair when everyone pays the same share of a shared total. This itemized bill split calculator lets you assign each dish, drink, or line to a named person, sum that person's food subtotal, and then distribute the check's absolute tax and service charge in proportion to those subtotals so heavier orders carry a larger slice of tax and tip.
How item assignment and proportional tax and service work
Start from the printed or app check as a list of lines rather than a single lump sum. Each line carries an amount in one currency and a person string that identifies who ordered or agreed to pay for that dish. Lines that share the same person string roll into one food subtotal for that diner.
The calculator then takes the absolute tax amount and the absolute service charge or tip written on the check and allocates both charges using the classic proportional rule: each person's share of tax equals tax times that person's subtotal divided by the table food total, and the same ratio multiplies the service amount. Adding the three pieces gives what that person owes: food subtotal plus tax share plus service share.
This is the fair-share pattern people already use on napkins when one guest ordered steak and another ordered only a salad, but without hand-rounding errors that leave a few cents unaccounted for. Equal split of the whole bill, including tax and tip among N heads, is a different product intent covered elsewhere; here the SEO intent is explicitly itemized assignment with proportional overhead.
When the food total is zero and tax or service is still positive, the ratio would divide by zero, so the engine rejects that combination instead of inventing arbitrary shares.
When splitting by item makes sense
Dinner parties, coworking lunches, and shared delivery orders need a neutral breakdown that everyone can audit line by line instead of arguing over equal halves. Hospitality demos and point-of-sale training tools can show how tax and service attach to who actually ordered rather than spreading fixed fees evenly across seats that ordered nothing.
Keep lists within ordinary table sizes, pin the rounded people totals in tests, and you get reproducible settlements for group chats, LMS examples, and edge workers without standing up a spreadsheet or a custom tip engine for every language you ship.
What you can do with it
Restaurant tables with different orders
Assign each entrée and drink to a diner, paste the tax and tip lines from the check, and see exactly what each person owes without equal splitting.
Delivery and group takeout
Map cart lines to housemates or coworkers and distribute delivery tax and service fees proportionally to each person's food subtotal.
FAQ
How does the itemized bill split calculator work?
Send items as {amount, person} lines, plus optional absolute tax and service.
Are tax and service percentages or money amounts?
Absolute money amounts in the same currency as the line items. Copy the tax and tip or service charge from the receipt; they are distributed by food-subtotal ratio, not as equal head counts.
What if two people share one dish?
Split the dish into two lines (half amount each) assigned to each person, or assign the full line to one person and settle the half privately.
Why not just split the bill equally?
An equal split makes the guest who ordered only a salad pay as much as the one who had steak, tax and tip included. Here each person pays their own dishes plus a matching slice of the extras; for an even split, use an equal bill splitter.
How do I enter several dishes for the same person?
Write exactly the same name on each of that person's lines. Lines that share a name are added into one food subtotal, so Alice's burger and fries become a single 20.5 before tax and tip are shared out.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/life/itemized-bill-split \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"items":[{"description":"Burger","amount":14.5,"person":"Alice"},{"description":"Salad","amount":11,"person":"Bob"},{"description":"Fries","amount":6,"person":"Alice"},{"description":"Soda","amount":3.5,"person":"Bob"}]}'const res = await fetch("https://api.kit.forhosting.com/life/itemized-bill-split", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": [
{
"description": "Burger",
"amount": 14.5,
"person": "Alice"
},
{
"description": "Salad",
"amount": 11,
"person": "Bob"
},
{
"description": "Fries",
"amount": 6,
"person": "Alice"
},
{
"description": "Soda",
"amount": 3.5,
"person": "Bob"
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/life/itemized-bill-split",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"items": [
{
"description": "Burger",
"amount": 14.5,
"person": "Alice"
},
{
"description": "Salad",
"amount": 11,
"person": "Bob"
},
{
"description": "Fries",
"amount": 6,
"person": "Alice"
},
{
"description": "Soda",
"amount": 3.5,
"person": "Bob"
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/life/itemized-bill-split", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"items":[{"description":"Burger","amount":14.5,"person":"Alice"},{"description":"Salad","amount":11,"person":"Bob"},{"description":"Fries","amount":6,"person":"Alice"},{"description":"Soda","amount":3.5,"person":"Bob"}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"items":[{"description":"Burger","amount":14.5,"person":"Alice"},{"description":"Salad","amount":11,"person":"Bob"},{"description":"Fries","amount":6,"person":"Alice"},{"description":"Soda","amount":3.5,"person":"Bob"}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/life/itemized-bill-split", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"items": [
{
"description": "Burger",
"amount": 14.5,
"person": "Alice"
},
{
"description": "Salad",
"amount": 11,
"person": "Bob"
},
{
"description": "Fries",
"amount": 6,
"person": "Alice"
},
{
"description": "Soda",
"amount": 3.5,
"person": "Bob"
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "life.itemized_bill_split",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Empty item lists, negative amounts, blank person names, and positive tax or service over a zero food subtotal fail with a clear invalid_input error and are not billed.
How item assignment and proportional tax and service work
When every line is free and both tax and service are zero, every person total is zero and the call still succeeds for completeness.
Input contract, response fields, and validation rules
Each object needs amount as a finite non-negative number and person as a non-empty name or short id; optional description labels the dish in the echoed breakdown. Both overhead fields are absolute money amounts in the same currency as the lines, not percentage points, so you copy the tax and tip lines from the receipt directly. POST a JSON body with a required items array of one to two hundred objects. Aliases lines, line_items, dishes, and orders are accepted for the array when your client already uses those keys. Optional tax defaults to zero and accepts aliases tax_amount, sales_tax, and vat; optional service defaults to zero and accepts service_amount, service_charge, tip, and gratuity. Missing items, empty arrays, negative line amounts, blank person strings, negative tax or service, and non-finite numbers fail with invalid_input naming the problem; those failures never consume prepaid balance. On success the body returns item_count, person_count, the normalized items list with index, description, amount, and person, food_total, tax, service, grand_total, and a people array ordered by first appearance of each person string. Each people row includes person, subtotal, share_ratio, tax_share, service_share, total, and item_count. Money fields use half-up rounding to two decimal places with a residual adjustment on the last positive-subtotal person so rounded tax shares still sum to tax, service shares sum to service, and person totals sum to grand_total. method is itemized_proportional_tax_service and formula restates the proportional rule for display next to the result.
Where an itemized bill split API earns its keep
Expense and reimbursement bots can accept the same structured payload a mobile form collects and return per-person totals ready for a settlement message or a ledger entry. Because the implementation is tier A analytic arithmetic with no model tokens and no outbound network, every successful call costs the published $0.002 base price, and validation failures are free.
Integration use cases
Expense bots and settlement apps
Call a stable prepaid endpoint that returns per-person totals ready for reimbursement messages, ledgers, or split-request UIs.
Technical questions
What errors does the calculator return?
invalid_input for empty items, negative amounts, blank person names, negative tax or service, or positive tax/service when food_total is zero. Those failures are not billed.
What does the itemized bill split calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not charged.