Skip to main content
The estimate endpoints are the scheduling-time surface of MeetCost. POST /api/v1/estimate is designed to be called on every meaningful edit to a calendar draft — changing the invitee list, adjusting the duration, switching from a one-off to a recurring meeting — and is deliberately a single round trip with no fan-out. POST /api/v1/estimate/commit closes the loop by recording that the organiser actually sent the invite, enabling the “reduced before send” metric that shows whether the nudges are working.

POST /api/v1/estimate

Estimate the payroll cost of a meeting that has not happened yet. Requires authentication; any authenticated role may call this endpoint.

Request body

string[]
required
Email addresses of all meeting invitees, including the organiser. At most 500 addresses. Case differences are normalised and duplicates are collapsed before lookup, so sending Ada@example.com and ada@example.com counts as one person.
number
required
Planned duration in minutes. Must be greater than 0 and at most 1440 (24 hours).
string
default:"one_off"
How often this meeting recurs. Drives annualised_total in the response.
string
default:"unknown"
The calendar platform originating this estimate (google, microsoft, zoom). Used to tag snapshot records. Maximum 20 characters.
string
Client-generated identifier for the draft being edited. When provided, MeetCost links successive estimates for the same draft so the “reduced before send” metric can be computed. Omit it and nothing is recorded. Maximum 120 characters.
string
Email of the meeting organiser. Defaults to the authenticated caller’s email. Used to apply organiser-level disclosure rules.
string
ISO 8601 date (YYYY-MM-DD) determining which pay records apply. Defaults to today. Use this to estimate a meeting scheduled for a future date when pay records may change.

Request example

Response body

object
The cost result, subject to disclosure policy redaction.
string | null
The cost of this meeting over a full year at the given cadence, as a decimal string. null for one_off cadence, because an annualised figure for a one-time meeting would be meaningless.
string
The cadence value from the request, echoed back.
array
Zero or more nudge objects, each with code, message, and threshold. Nudges are triggered when cost, headcount, or duration exceeds the configured thresholds. Messages are safe to display directly to the organiser.
string | null
A human-readable explanation when estimated_headcount is non-zero. Describes how many people were priced at the fallback rate and why the total may be understated. This message is especially prominent when no fallback rate has been configured, because those people contributed nothing to the total at all. Safe to show directly to the organiser. null when all invitees had pay records.
string | null
The ID of the snapshot record created for this estimate. Present only when draft_id was supplied and the cost was visible. null otherwise.

Response example

409 Conflict — mixed-currency invitees

If the invitee list includes people whose pay records are in more than one currency, MeetCost returns 409 Conflict. MeetCost v1 does not perform currency conversion. The error response describes which currencies collided:
When you receive a 409, show the organiser a message explaining that the invitee list spans multiple salary currencies and that the estimate cannot be produced. This is not an error in your integration — it reflects a genuine limitation of the v1 rate engine.

Coverage and fallback rates

When estimated_headcount is greater than zero, some attendees had no pay record and were priced at the org-wide fallback_annual_pay rate. The coverage_note field contains a sentence you can show the organiser directly.
If the admin has not configured a fallback rate, fallback_annual_pay is 0. In this case, every person without a pay record contributes nothing to the total, and coverage_note will say so explicitly. The total shown to the organiser is a genuine underestimate, not just a rounded one.

POST /api/v1/estimate/commit

Mark a draft as sent, closing the measurement loop on the “reduced before send” metric. Call this when the organiser actually issues the calendar invitation — not when the estimate is first shown. Drafts that are never committed count as abandoned, which is itself a meaningful signal. Requires authentication. The caller must be the organiser who created the draft, or a service token. Returns 404 if the draft_id is not found.

Request body

string
required
The draft_id that was passed to POST /api/v1/estimate when the draft was created. Maximum 120 characters.

Request example

Response body

string
The committed draft ID, echoed back.
integer
Total number of estimate snapshots recorded for this draft — one per call to POST /api/v1/estimate with this draft_id.
string
The cost total from the first snapshot, as a decimal string.
string
The cost total from the last snapshot before commit, as a decimal string.
boolean
true if final_total is less than initial_total, meaning the organiser reduced the meeting cost (by removing invitees, shortening the duration, etc.) before sending.

Response example