TOMO
BETA Partner connections are in beta and these docs are under review. Anything marked planned is not built yet — we confirm with you what is live before your service goes live.

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_id
  • closed_at (ISO timestamp)
  • amount_inr
  • TOMO's response (closed_intent_id + cpc_event_id from 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.