That month's reconciliation detail, per store
const url = 'https://data.creatorain.com/partner/v1/billing/monthly?month=2026-09&limit=50';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://data.creatorain.com/partner/v1/billing/monthly?month=2026-09&limit=50' \ --header 'Authorization: Bearer <token>'One row per store enrolled under your key, except that a TERMINATED store with nothing to
reconcile in the month (no video published, no visit completed and no no-show) is left out
instead of listed as a line of zeros. A terminated store that did have any of those stays,
with status: terminated. A page can therefore hold fewer rows than limit: follow
next_cursor until it is null. Each row: videos published in the month, the plan the
store is on, completed visits and no-shows, and the finished amounts for the month. This
is what an invoice is checked against. You do no price maths: amount_due is what we bill
you for the store, merchant_amount is what the merchant owes with your surcharge included.
THE AMOUNTS. billed_videos = videos_published - makeup_videos (free replacement videos
are never billed). merchant_amount = billed_videos x (the flat merchant price + your
surcharge, both locked on the store for THAT month). amount_due is what we bill you: for
each billed video, that video’s actual creator cost plus our fee per video (fee_per_video
in the pricing block), summed. A video whose creator was paid nothing (comped) still carries
the fee. It is not a fixed price per video. A plan or approval change re-locks from the next
month, so each month uses its own lock. A store with no locked price (confirmed before
pricing) is billed the same way from the current default terms: creator cost plus our fee,
and merchant_amount from the default merchant price. Both are null only when pricing is
not set up at all. While a billed
video’s creator cost is not known yet, amount_due is null and cost_pending_videos says
how many videos are waiting; it is never a 0 that under-bills. See amounts_note. Currency
units, like every price on this API.
THE MONTH IS THE STORE’S MONTH. A video published at 23:30 on 30 September in Los Angeles
is a September video; bucketed in UTC it would be 06:30 on 1 October and would land on the
wrong invoice, with both sides looking at a real timestamp and reading it in different
clocks. Each store’s window is resolved on that store’s own clock, and it is half open:
[local 1st 00:00, local 1st of next month 00:00), so no video is counted twice or lost.
Visits are counted by VISIT DATE, which our reservations already store in the venue’s own calendar, so a visit marked completed in October for a September booking is a September visit.
month is REQUIRED and has no default. “This month” would be the obvious default and is
the wrong one here: a scheduled job whose parameter went missing would silently start
reporting whichever month it ran in, and the first sign of that is a merchant charged
twice.
note states the one limitation of these numbers and is on every response. Our per-store
pin on content landed on 2026-09-09, so anything published before that date carries no
store and is not counted here.
PARTNER KEY ONLY. A store token cannot read this: a chain’s billing is your business, not one merchant’s.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”The month to report, YYYY-MM, in each STORE’S own calendar. Required, with no default.
Example
2026-09The next_cursor from the previous page, sent back UNCHANGED. Omit it for the first page.
It is opaque: do not build one yourself. It names a POSITION in the sort order rather than
a count of rows to skip, which is why a page stays stable when a booking is touched between
two requests. A cursor we did not issue is refused with 400 validation_error, rather than
silently treated as the first page, so a broken client fails loudly instead of looping over
page one for ever.
Rows per page. Default 50, maximum 200. A larger value is CLAMPED to 200 rather than refused, so you never have to guess the ceiling.
Responses
Section titled “Responses”A page of stores, with the month’s counts for each.
object
The month asked for, echoed back, so a stored report says what it is of.
The one limitation of these numbers, on every response rather than in a document somebody has to remember to read.
When the amounts are null, and that make-up videos are never billed. On every response.
When this was computed, RFC 3339 in UTC. A fact about our run rather than a time at any store, so it carries no store offset.
One store’s month. Counts only: there is no personal data anywhere in this report.
object
YOUR id for the store, which is what your own billing is keyed on.
Our id for the same store.
Videos filmed at this store that are LIVE and were published inside the month IN THIS STORE’S OWN CLOCK. See the endpoint description for why that matters. Only videos made on your key’s campaign count: a video another campaign made at the same restaurant is not on your invoice.
The plan in force in THAT month (a plan change applies from the next month), echoed so an invoice line can be checked without a second call.
Visits at this store marked completed, by VISIT DATE in the store’s calendar. Only visits booked on your key’s campaign count.
Visits at this store marked no_show, by the same date and the same campaign.
The store’s state at the moment of the read, so a row of zeroes can be explained without a second call. A terminated store appears only if it had a video or a visit in the month.
Of videos_published, the free replacement videos (after a no-show, or for a video the
merchant rejected). Never billed.
videos_published - makeup_videos: the videos the two amounts are for.
Billed videos whose creator cost is not known yet. While above 0, amount_due is null.
The currency of the amounts. Null when the store has no locked price.
What CreatoRain bills you for this store this month: the sum over billed videos of
(that video’s creator cost + our locked fee per video). Null for a store with no locked
price, or while cost_pending_videos is above 0.
What the merchant owes for the month with your surcharge included, ready for your
invoice: billed_videos x (the flat merchant price + your locked surcharge). Null for a
store with no locked price.
Send this back as cursor for the next page of STORES. The stores are ordered by
partner_location_id ascending rather than by recency, because a reconciliation file
is diffed against last month’s and a stable order is worth more here than newness.
Example
{ "month": "2026-09", "note": "content published before 2026-09-09 carries no store and is not counted", "amounts_note": "amount_due and merchant_amount are null for a store with no locked price (confirmed before pricing); amount_due is also null while a billed video has no known creator cost (see cost_pending_videos); make-up videos are never billed", "items": [ { "partner_location_id": "store_123", "videos_published": 2, "plan_videos_per_month": 2, "plan_term_months": 3, "reservations_completed": 3, "no_shows": 1, "status": "active", "makeup_videos": 0, "billed_videos": 3, "cost_pending_videos": 0, "currency": "USD", "amount_due": 450, "merchant_amount": 1125 } ]}validation_error. field names the offending parameter.
object
object
The stable value to branch on.
A human sentence. Copy, not contract; it may be reworded.
The request field at fault, dotted for a nested one (plan.term_months).
Example
{ "error": { "code": "unauthorized" }}unauthorized. A missing, malformed, unknown or revoked key; or an invalid, expired or
wrong-store dashboard token. One answer for every case on purpose: the holder of a bad
credential learns nothing from the difference.
object
object
The stable value to branch on.
A human sentence. Copy, not contract; it may be reworded.
The request field at fault, dotted for a nested one (plan.term_months).
Example
{ "error": { "code": "unauthorized" }}rate_limited. Over this key’s requests-per-minute ceiling.
object
object
The stable value to branch on.
A human sentence. Copy, not contract; it may be reworded.
The request field at fault, dotted for a nested one (plan.term_months).
Example
{ "error": { "code": "unauthorized" }}