TOMO Completion Contract — The Closed-Intent POST
Audience: every TOMO partner. This is the call that tells TOMO an order completed. Get it right and the order — and TOMO's fee on it — is on record. Get it wrong and the closed intent doesn't enter the CPC ledger.
1. When to fire
POST to TOMO's CPC webhook immediately after the intent transitions to a terminal state, success or failure. Terminal states (per intent):
| Intent shape | "Fire CPC" trigger |
|---|---|
| Listing/booking (hotel, flight, package) | check-in confirmed OR booking-cancelled-by-user OR booking-cancelled-by-provider |
| Order delivery (food, grocery) | order-delivered OR order-failed-irrevocably |
| Mobility (ride, intercity, self-drive) | ride-completed (drop reached) OR ride-cancelled |
| Service (salon, gym, doctor) | service-rendered OR service-cancelled |
| Marketplace (used car, electronics) | sale-completed OR sale-cancelled-after-handshake |
| Logistics (parcel, move) | delivered OR failed-delivery-irrevocable |
Don't fire on transient states. Cooking, en-route, pending-confirmation, processing — these are not terminal.
2. The endpoint
POST https://www.automobnxt.com/api/v1/cpc/mcp_provider/<your_account_id>
Headers:
Content-Type: application/json
X-TOMO-Timestamp: <unix epoch ms>
X-TOMO-Signature: sha256=<hex hmac>
Body: the fields in §3 (plus, if you like, the intent-specific fields from your intent's §7).
Signing per WEBHOOK_SIGNING.md. Rejection on signature failure: 401 with {"error":"signature_invalid","reason":"…"}.
3. The body — what TOMO reads today
TOMO reads and stores five fields today (it also stores a supply_path field if one is sent — leave it out):
{
"intent": "<full_intent_id>",
"external_id": "<your_internal_id>",
"amount_inr": <number>,
"closed_at": "<ISO_DATETIME with timezone>",
"notes": "<string, may be empty>"
}
| Field | Constraint | Notes |
|---|---|---|
intent |
REQUIRED, full intent ID | e.g., food.order_delivery, travel.book_hotel |
external_id |
REQUIRED, string | YOUR system's id — booking_ref, order_ref, ride_ref. Keep it unique per completed order. TOMO does not de-duplicate on it yet (see §9). |
amount_inr |
REQUIRED, number ≥ 0 | your NET supplier revenue for the order (see §6). TOMO rounds it to whole rupees. |
closed_at |
optional, ISO_DATETIME with TZ | the moment the order became final in your system. Defaults to when TOMO received the POST. |
notes |
optional | partner-side context, kept with the record. |
Any other field is accepted but not read yet.
4. Intent-specific fields (recommended)
Each intent's spec §7 lists the details that describe a completed order of that kind. TOMO does not check them yet, but sending them now keeps your records ready for when it does. Examples:
travel.book_hotel
{
// ...the five fields above...
"booking_ref": "BOOK-12345",
"check_in": "2026-05-15",
"check_out": "2026-05-17",
"rooms": 1,
"guests": 2,
"fees_breakdown_total_inr": 1200,
"cancellation_until": "2026-05-13T18:00:00+05:30"
}
food.order_delivery
{
// ...the five fields above...
"order_ref": "ORDER-XYZ123",
"restaurant_id": "rest_28342",
"delivered_at": "2026-05-09T20:42:00+05:30",
"items_count": 3,
"fees_breakdown_total_inr": 122
}
mobility.book_intracity_ride
{
// ...the five fields above...
"ride_ref": "RIDE-XYZ",
"started_at": "2026-05-09T08:21:00+05:30",
"completed_at": "2026-05-09T09:02:00+05:30",
"distance_traveled_km": 28.7,
"fare_breakdown_total_inr": 480
}
5. Status (recommended)
Each intent's §7 lists the final status values, for example travel.book_hotel: confirmed | cancelled_by_user | cancelled_by_provider | no_show | failed_payment. TOMO does not read a status yet — a cancelled order with no money changed hands is simply amount_inr: 0. If you send one, use the enum value, never free text.
6. The commission rule
TOMO charges its platform commission on amount_inr for every successfully closed intent. The rate is set platform-wide — the same for every business — and written in your listing agreement.
commission_inr = round(amount_inr × the platform rate)
The commission is TOMO's fee, billed to you separately (§8). It is never taken out of your customer's payment.
Each accepted POST writes a completed-order record and a fee line in TOMO's ledger. (planned: a ledger view in your partner dashboard — not built yet.)
No exceptions. Same rate for every business, from a solo driver to a large chain. There are no enterprise discounts, no volume tiers.
What counts as amount_inr?
Your NET supplier revenue for the order — base price plus any fees and surge you keep. This is the commission base.
Leave out:
- GST (it goes to the government)
- Tips you collect for your driver or staff
- Third-party pass-through fees you don't keep
- Refund-only credits issued to the customer
Promotional discounts you funded are already baked into the final price.
If status is cancelled_by_user or cancelled_by_provider and no money changed hands → amount_inr: 0. TOMO logs the completed order but the fee is 0.
If a cancellation charge applied → amount_inr: <cancellation_charge_inr>. The fee applies to that amount.
7. Refunds and adjustments
There is no adjustment endpoint yet. For a refund, a dispute outcome or a correction, email krishna.gamasany@automobnxt.com with the external_id and the corrected amount; our team adjusts the ledger by hand. (planned: a signed /adjust endpoint.)
8. How you're billed
The customer pays you through your own checkout. TOMO never collects from your customers, never holds the money and never pays out to you — so there is no settlement from TOMO. TOMO records its fee for each completed order you report and bills it to you separately.
9. Retries and duplicates
TOMO does not de-duplicate on external_id yet. Every accepted POST records a new completed order and a new fee line. So:
on network failure with NO response: retry once with the same body
on 401 signature_invalid: fix signing, then retry
on 5xx (cpc_failed): retry later
on 201: stop — never resend after a 201
If you think you posted twice, email krishna.gamasany@automobnxt.com with the external_id and we will correct the ledger. (planned: idempotency on external_id.)
10. Error responses TOMO returns
| HTTP | Body | Meaning | Your action |
|---|---|---|---|
| 201 | {"ok":true,"closed_intent_id":"cls_…","cpc_event_id":"cpc_…","commission_inr":…,"rate":…} |
Completed order + fee line written | done |
| 400 | invalid_supplier_type |
Wrong path | use /cpc/mcp_provider/<your_account_id> |
| 400 | Missing intent / Missing external_id / amount_inr must be a non-negative number |
Body incomplete | fix the body |
| 401 | {"error":"signature_invalid","reason":"…"} |
HMAC verification failed (see WEBHOOK_SIGNING.md) | fix signing |
| 500 | cpc_failed |
TOMO-side failure | retry later — only if you did not get a 201 |
11. Partner-side audit log requirement
You MUST keep your own audit log of every CPC POST you've made. Include:
external_idclosed_at(ISO timestamp)amount_inr- TOMO's response (
closed_intent_id+cpc_event_idfrom the 201 response)
Keep it for as long as your own tax rules require.
If we need to check a disputed entry, we'll ask for your record of it.
12. Common mistakes
POSTing for transient states
"order-accepted" or "ride-en_route" are NOT terminal. Don't fire CPC on these. Only on terminal closure.
Free-text status
"Successfully delivered with minor delay" — wrong. If you send a status, use the enum value: delivered.
Sending currency: "USD"
Amounts are in INR in v1 of this contract. The conversion from any other currency happens before the POST.
Using floats for amount_inr
TOMO rounds amount_inr to whole rupees. Send the rupee amount you mean, already rounded, so your log and TOMO's match.
13. Sample full POST (travel.book_hotel)
POST /api/v1/cpc/mcp_provider/<your_account_id> HTTP/1.1
Host: www.automobnxt.com
Content-Type: application/json
X-TOMO-Timestamp: 1715257923000
X-TOMO-Signature: sha256=ab92f4...
{
"intent": "travel.book_hotel",
"external_id": "STAY-CONFIRMATION-12345",
"amount_inr": 8400,
"closed_at": "2026-05-09T14:35:00+05:30",
"notes": "",
"status": "confirmed",
"booking_ref": "BOOK-12345",
"check_in": "2026-05-15",
"check_out": "2026-05-17",
"rooms": 1,
"guests": 2,
"fees_breakdown_total_inr": 1200,
"cancellation_until": "2026-05-13T18:00:00+05:30"
}
Response (201):
{
"ok": true,
"closed_intent_id": "cls_1715257923000_ab12cd",
"cpc_event_id": "cpc_1715257923000_ef34gh",
"commission_inr": <TOMO's fee for this order>,
"rate": <the platform rate in your listing agreement>
}
14. References
- HMAC details:
WEBHOOK_SIGNING.md - Per-intent §7: every file under
docs/intents/ - Server-side ingest: TOMO's CPC ingest layer (HMAC-verified; not yet idempotent — see §9)
- Server-side ledger: TOMO's CPC ledger (Firestore-backed, append-only)
Built by AUTOMOBNXT · DPIIT Recognised Startup · 2026.