Seat files from vendors are almost always how many they had that day. They are almost never a trustworthy increase column.
If your seat billing reconciliation starts with "why does this delta column not match Sonic," the answer is usually that the delta column was never valid — not that Sonic prorated wrong.
Absolute counts vs delta columns
Increase columns subtract the row above. At a customer boundary the row above is someone else. Peak columns and daily snapshots reconcile. Delta columns do not.
| Column type | What it claims | Why it breaks |
|---|---|---|
| Daily absolute count | "Customer A had 42 seats on 3 March" | Stable at boundaries |
| Peak / MAXIFS | "Highest count in the month" | Good for sanity checks |
| Increase / delta | "Added 3 since yesterday" | Yesterday's row may be a different customer |
Sonic treats each snapshot as an absolute count. It compares that count to the balance on record for that customer and seat type, and it writes a seat event when the number changes. Already-imported rows are skipped by identity while the running count still advances.
From snapshot to billable event
The mental model is simple:
- SeatBalance is what Sonic believes today for customer + seat type.
- Each new snapshot row is a photograph, not a guess.
- Sonic emits a SeatEvent only when the photograph differs from the balance on record.
- Billing reads events and product rules — proration policy, confirmation days, minimum seats on the product — not the raw spreadsheet row.
Templates expand daily values in preview: every calendar day from each customer's earliest to latest snapshot date, with gap days forward-filled from the last known count. Events stay change-only. That preview is how you catch a missing week before you approve an upload.
Confirmation days — real adds, not preview theatre
Confirmation days apply to persisted events (manual create, CSV import, webhook ingest), not to preview-only rows.
An organisation default of N days means an add on date D stays pending until D+N unless a removal cancels it first. Removals are never held. Pending adds are confirmation lots — a later removal cancels pending quantity first (newest add first); what remains pending keeps waiting.
If the sample does not include the last required day, the add is awaiting — not billed as a hope. That is deliberate. Billing a seat because the vendor's export ended mid-window is how you invoice seats the customer later removed.
Overrides exist per customer, or per customer and seat type on the template. Use them when one enterprise buyer negotiated a longer proof window than your org default.
Templates, Process, and the upload path
Seat templates hold customer mapping, timestamp mapping, and one or more seat-meter mappings (seat type + daily value column or formula). Templates are preview until you import elsewhere.
Critical operator rules:
- Uploading a sample does nothing by itself. Process computes uniqueness, filters, and the preview.
- After Process succeeds, mapping edits refresh through their own reprocess controls — they do not re-arm Process unless you replace the file or change the worksheet.
- Timestamps are UTC midnight of the calendar day on a date-only sheet. Converting through a local midnight is how you bill the wrong day.
- Never import a vendor "increase" column. Their MAXIFS peak columns often reconcile; their delta columns do not.
Production uploads on Uploads accept CSV, Excel, and JSON. Approve inserts SeatEvents with snapshot idempotency keys so a re-run does not double-bill.
How this connects to invoices
On the invoice, the Seats panel shows confirmed billable seats_balance from the invoice line — not the last event's raw balance_after. Expanded rows show period events with badges for minimum, confirmation, and valid/invalid states.
If a seat line is surprising, look at the balance on record and the confirmation window before you rewrite the list price. Mid-period adds under Added seats only proration bill remaining calendar units of unit_price_basis — one invoice row per event, not a merged cohort.
Watch out for
- Delta columns at customer boundaries are poison. If the vendor gives you both daily count and increase, use daily count only.
- Confirmation days need coverage in the file. An add on the last day of the export with a 7-day window will sit pending until proof arrives.
- Process is server-owned. A failed Process never reads as processed; only a new file or worksheet clears the gate.
- Seat webhooks are synthetic uploads. Same Process → Approve path; template field mappings must match partner JSON, not leftover Excel formulas.
- Minimum seats on the product still bill the contracted floor. Sonic does not auto-create minimum-seat events on schedule activation — operators enter real headcount; the product pricing enforces the floor.