One store's current state, progress and next visit
const url = 'https://data.creatorain.com/partner/v1/locations/store_123';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/locations/store_123 \ --header 'Authorization: Bearer <token>'The store as we hold it, plus this quarter’s progress and the next confirmed creator visit. This is the read the embedded merchant dashboard is built from.
EITHER CREDENTIAL: your partner key (any store of the key), or that store’s own 30 minute
token from POST /locations/{partner_location_id}/dashboard-token, sent as
Authorization: Bearer <token> or ?token=<token>. A store token presented for any other
store answers 401 unauthorized, and it answers the same 401 whether or not that other
store exists.
published_count counts videos filmed at THIS store that are live. Videos published before
2026-09-09 carry no store and are not counted; that is a property of the data, not of the
query.
rules is this store’s matching terms as they now stand, in the same shape PATCH accepts.
This is the read to reconcile against if a PATCH response was ever lost.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”YOUR id for the store, as you sent it to POST /locations.
Example
store_123Responses
Section titled “Responses”The store, its progress and its next visit.
object
OUR id for the store. Stable, and what every other endpoint refers to it by.
Your id, as you sent it (trimmed).
paused means no NEW scheduling: creators are not offered the store and a new booking
is refused, while bookings already confirmed are untouched. Resume opens it again.
terminated means the contract has ended. Terminated wins over paused.
A display label for the local creator pool, for example example-pool. Label only.
The embeddable merchant dashboard for this store, carrying a freshly minted 30 minute
read-only token. Null when this deployment hosts no embedded dashboard, rather than a
plausible URL pointing at nothing: an iframe rendered from a dead URL shows a merchant
a blank panel, which is worse than a field you can branch on. Mint a fresh one with
POST /locations/{partner_location_id}/dashboard-token when you render the embed.
IANA name for the store as we resolve it: the timezone you sent when you sent one,
otherwise derived from the address. Null when neither yields one.
RFC 3339 with the store’s offset.
Whether we hold this store’s real opening hours, and where they came from. A store with
no hours is still active: the contract exists and nothing about the enrolment failed.
What it cannot do yet is take a creator booking, because our two date pickers are built
from the stored week and an absent one disables both. state: missing is a request to
chase the hours at source, which is the one place they actually exist.
object
Where the hours came from. partner means you sent them (opening_hours); the rest
are our own lookups or an operator (manual). Null for a store never checked.
How creators are approved for this store. auto (the default) books matching creators
straight away. sample_review means the merchant first approves a batch of 5 sample
creators (GET /locations/{partner_location_id}/creator-samples); nothing starts until
that decision.
The store’s price for the month it is in: the same block as the quote, LOCKED when the store
was confirmed. A change to plan.videos_per_month or approval_mode re-locks it from the
next month (at the base price and your surcharge at that moment), shown meanwhile as upcoming.
A later surcharge change does not move it. A store confirmed before pricing existed has no
locked price: its block is worked out from the current default terms and marked
locked: false, source: default (nothing is stored for it, and it shows the default
creator cost range). NULL only when pricing is not set up at all.
Read with a merchant’s store token, only the merchant price is returned (creatorain and
surcharge are left out).
object
What we bill the partner per published video. Not a fixed price.
object
Estimate range of the creator cost per video (on a quote, and on a store with no locked price; null on a locked store). The bill uses the actual cost.
object
object
The non-standard plan line, included in merchant. 0 / false for a standard plan.
object
True while the amount is provisional.
object
Per_video x videos per month. Null for a store with no plan.
Per_month x 3.
When the price in force was locked (UTC). Null when locked is false.
False for a store with no locked price, priced from the current defaults.
The price from from_month (the store’s next month), when a re-lock is waiting.
object
What we bill the partner per published video. Not a fixed price.
object
Estimate range of the creator cost per video (on a quote, and on a store with no locked price; null on a locked store). The bill uses the actual cost.
object
object
object
object
Per_video x videos per month. Null for a store with no plan.
Per_month x 3.
The first-visit commitment for this store, in business days (Monday to Friday, store clock, skipping Thanksgiving Day, Christmas Day, New Year’s Day and any weekday the store’s own opening hours say it is closed), as agreed in your contract. Locked when the store is created. Null for a store created before this field existed. Show it as given.
The store-local date the first creator visit is due by: first_visit_business_days
counted from the day after the confirm day (approved_at when you sent it, otherwise
the day the store was created). Locked at creation.
WHAT THIS STORE ASKS OF A CREATOR: the terms you set with PATCH, read back. Always
present, ordered by attribute then operator, and [] for a store that asks nothing -
which is what a store has until you send its first rule.
THIS IS THE SAME ARRAY PATCH ACCEPTS, so the obvious read-modify-write is safe: read
a store, change one entry, send the array back. value is returned in the shape we
STORED it, which is the normalised one - a bare 20000 you sent for follower_count
reads back as {"count": 20000, "platform": null}, and sending that object again
changes nothing.
It is deliberately NOT our internal effective rule set. Terms an operator set on our
own dashboard through the older per-venue columns are not folded in here, because you
can neither send nor clear those through this API and a term you cannot remove is worse
than one you cannot see. Everything this array contains, clear_rules can remove.
One term this store asks of a creator.
ethnicity, age_band and gender are real members of our attribute list and are
REFUSED with 422 validation_error on both this API and our dashboard. Filtering paid work
by a protected characteristic needs a written policy agreed with counsel, and until one
exists we will not store the rule.
follower_count takes gte or lte and a value of {"count": N}, optionally with
"platform" to say WHERE the count is measured - {"count": 20000, "platform": "tiktok"}
means twenty thousand on TikTok, not twenty thousand in total from somebody who also has a
TikTok handle. platform and language take eq with one value or in with a list; over
a creator who works on several, eq means “this is one of hers”, never “this is her only
one”.
home_metro (local creators only) takes in; radius_miles (within N miles of this
store) takes lte and the miles, 25 or {"miles": 25}, from 1 to 500. Both are measured
from this store’s own address, which we resolve when you write the rule and again when the
address moves; an address we cannot place in a US city is a 422.
performance_index (content performance score, 0 to 100) and engagement_rate (percent,
3.5 means 3.5%) take gte and a number. They are floors.
A creator we hold no answer for is decided by the store’s own policy, which passes by
default - so adding a language rule today records your intent and excludes nobody until
we hold languages. The follower bar, the platform, home_metro, radius_miles,
performance_index and engagement_rate are the exception and always exclude a creator we
cannot measure.
object
object
This store’s progress against its plan.
object
Videos per SEASON (three months): videos_per_month x 3, following the plan in
force for each month of the current season (a PATCH applies from the next
month). Null when the store has no plan.
DEPRECATED. The old name of season_target, sent for one more release with the
same value. Read season_target. Before this release it held the whole-term
total.
Videos filmed at this store that are live.
Confirmed visits at this store that are still in the future. Same value as
booked_upcoming, kept so existing readers do not break; new code should read
booked_upcoming. NOT the same as pipeline.booked, which counts every creator
who ever booked this season, including visits already done.
Confirmed visits at this store that are still in the future (upcoming only; done,
cancelled and past visits are not counted). pipeline.booked is the season total
of creators who booked, so it is normally the larger of the two.
The next confirmed creator visit, or null when none is booked.
object
RFC 3339 with the STORE’S offset. The digits are the restaurant’s wall clock.
How the merchant at this store is reached by email. TWO BOOLEANS AND NO ADDRESS: the address a notice goes to is an account holder’s, and this body can be read with a store dashboard token, which is a merchant’s browser credential.
object
Whether there is anybody to write to at all. False means nothing we send about this store’s bookings reaches a human, which is worth seeing before a creator turns up rather than afterwards.
True when the address the notices go to IS the store’s own published inbox: one inbox doing two jobs. It matters because a filter, a holiday auto-responder or a bounce then takes out the booking notice and the marketing conversation together, so the visit-day fallback has to be a different channel rather than a second mail.
What stops this store from recruiting creators. Empty when recruiting can run. A
store recruits only when the campaign is running, its opening hours are known and
it is not paused or terminated. A paused store reports store_paused (resume it and
it clears). A terminated store reports store_terminated and never store_paused:
its contract is over and it cannot be resumed. When recruiting starts we send the
location.recruiting webhook once, with campaign_id and first_visit_due_by.
This season’s creator pipeline for the store, as counts. Cumulative: each creator
is counted once, at her furthest stage, in that stage and every earlier one, so
contacted >= interested >= accepted >= booked >= visited >= posted. declined
(said no, or no answer after follow-ups) is separate and also inside contacted.
Contacted and interested count creators in the store’s metro area; accepted and
later need a signature, booking or video at THIS store.
object
Creators who booked a visit here this season, counted once each at their furthest
stage, done visits included. Not the same as progress.booked_upcoming, which is
only the confirmed visits still to come.
This season’s results (guide 8.1 to 8.4). Updates with each weekly reading of the videos. Null when the store has no season yet.
object
Last day of the season.
Posts behind those videos (a cross-post is 2 posts, 1 video).
The season’s posts that have been read: a reading has written their numbers. At most
season_posts; the rest have not been read yet, so they count toward no play or average.
The read posts whose plays are measured, the posts season_plays adds up. Below
posts_read when a platform did not publish a post’s plays. With 0, season_plays is
0 because nothing was counted, not because the videos got no plays.
Over TikTok posts only. Null with none.
Estimated groups of guests who came because of the videos. Our own model, from each
post’s plays, likes, comments, shares and saves and the share of the creator’s
followers who are local to the store. Updates weekly, fixed at the final reading.
An estimate, not a commitment. Show it with a (?) and estimated_new_guests_help.
Tooltip text for the (?) icon.
The season commitment check (guide 8.4). Status is met, not_met or pending. Before
the final reading a check is met once reached (provisional for averages) or pending;
at the final reading met or not_met. Average shares is not_measured at the final
reading when no post of the season publishes shares. First visit compares the first
visit that has happened with first_visit_due_by.
object
object
object
object
object
object
object
The season before this one. Its final reading comes 2 weeks after it ends; from
then on final is true and the block never changes. Null in the first season.
object
Last day of the season.
Posts behind those videos (a cross-post is 2 posts, 1 video).
The season’s posts that have been read: a reading has written their numbers. At most
season_posts; the rest have not been read yet, so they count toward no play or average.
The read posts whose plays are measured, the posts season_plays adds up. Below
posts_read when a platform did not publish a post’s plays. With 0, season_plays is
0 because nothing was counted, not because the videos got no plays.
Over TikTok posts only. Null with none.
Estimated groups of guests who came because of the videos. Our own model, from each
post’s plays, likes, comments, shares and saves and the share of the creator’s
followers who are local to the store. Updates weekly, fixed at the final reading.
An estimate, not a commitment. Show it with a (?) and estimated_new_guests_help.
Tooltip text for the (?) icon.
The season commitment check (guide 8.4). Status is met, not_met or pending. Before
the final reading a check is met once reached (provisional for averages) or pending;
at the final reading met or not_met. Average shares is not_measured at the final
reading when no post of the season publishes shares. First visit compares the first
visit that has happened with first_visit_due_by.
object
object
object
object
object
object
object
Example
{ "partner_location_id": "store_123", "status": "active", "network": "example-pool", "timezone": "America/Los_Angeles", "created_at": "2026-09-10T13:22:00-07:00", "hours": { "state": "missing", "source": "partner" }, "approval_mode": "auto", "pricing": { "currency": "USD", "billing_unit": "published_video", "creatorain": { "fee_per_video": 10, "creator_cost_per_video": { "min": 20, "max": 40 }, "billed_as": "creator_cost_plus_fee" }, "surcharge": { "per_video": 10 }, "plan_surcharge": { "per_video": 5, "applies": false, "placeholder": true }, "merchant": { "per_video": 100, "per_month": 200, "per_season": 600 }, "season_videos": 6, "source": "locked", "upcoming": { "from_month": "2026-11", "creatorain": { "fee_per_video": 10, "creator_cost_per_video": { "min": 20, "max": 40 }, "billed_as": "creator_cost_plus_fee" }, "merchant": { "per_video": 100, "per_month": 200, "per_season": 600 } } }, "first_visit_due_by": "2026-10-06", "rules": [ { "attribute": "follower_count", "operator": "gte", "value": { "count": 20000, "platform": "tiktok" } }, { "attribute": "platform", "operator": "eq", "value": "tiktok" } ], "progress": { "season_target": 6, "quarter_target": 6, "published_count": 2, "booked_count": 1, "booked_upcoming": 1 }, "next_visit": { "arrive_at": "2026-09-14T19:00:00-07:00", "timezone": "America/Los_Angeles" }, "blocking_reasons": [ "hours_missing" ], "pipeline": { "contacted": 38, "interested": 7, "accepted": 3, "booked": 1, "visited": 0, "posted": 0, "declined": 4 }, "results": { "season_starts_on": "2026-10-01", "season_ends_on": "2026-12-31", "season_videos_published": 3, "season_videos_target": 9, "season_posts": 4, "season_plays": 58400, "posts_read": 4, "season_plays_posts_measured": 4, "average_likes_per_video": 785, "average_shares_per_video": 106, "average_creator_followers": 13070, "estimated_new_guests": 24, "estimated_new_guests_note": "Estimate from video engagement data. Not a commitment.", "commitment": { "videos": { "value": 58400, "target": 60000, "status": "met" }, "average_creator_followers": { "value": 58400, "target": 60000, "status": "met" }, "season_plays": { "value": 58400, "target": 60000, "status": "met" }, "average_likes_per_video": { "value": 58400, "target": 60000, "status": "met" }, "average_shares_per_video": { "value": 58400, "target": 60000, "status": "met" }, "first_visit": { "value": "2026-10-03", "target": "2026-10-06", "status": "met" } }, "measured_at": "2026-11-09T02:00:00Z", "final": false }, "previous_season_results": { "season_starts_on": "2026-10-01", "season_ends_on": "2026-12-31", "season_videos_published": 3, "season_videos_target": 9, "season_posts": 4, "season_plays": 58400, "posts_read": 4, "season_plays_posts_measured": 4, "average_likes_per_video": 785, "average_shares_per_video": 106, "average_creator_followers": 13070, "estimated_new_guests": 24, "estimated_new_guests_note": "Estimate from video engagement data. Not a commitment.", "commitment": { "videos": { "value": 58400, "target": 60000, "status": "met" }, "average_creator_followers": { "value": 58400, "target": 60000, "status": "met" }, "season_plays": { "value": 58400, "target": 60000, "status": "met" }, "average_likes_per_video": { "value": 58400, "target": 60000, "status": "met" }, "average_shares_per_video": { "value": 58400, "target": 60000, "status": "met" }, "first_visit": { "value": "2026-10-03", "target": "2026-10-06", "status": "met" } }, "measured_at": "2026-11-09T02:00:00Z", "final": false }}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" }}location_not_found. No store of this key carries that partner_location_id.
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" }}