Change a store's name, address, plan, dishes, language, hours, time zone or contact
const url = 'https://data.creatorain.com/partner/v1/locations/store_123';const options = { method: 'PATCH', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"name":"Example Noodle House Downtown"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://data.creatorain.com/partner/v1/locations/store_123 \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "name": "Example Noodle House Downtown" }'Every field is optional and AT LEAST ONE is required. Send only what changed.
A changed plan recomputes the store’s total deliverables (videos_per_month x
term_months) and its collaboration end date. The START date is never rewritten: the store
began being offered when it began. A PARTIAL plan is merged with the stored one, so
{"plan": {"videos_per_month": 4}} on a 2 x 3 store means 4 x 3. A new videos_per_month
applies to the monthly pacing from the 1st of the NEXT month, store time (see Monthly
pacing above); the month under way keeps the plan it started with.
An address is replaced WHOLE rather than merged field by field, so send the complete
address object. The store’s time zone is re-derived from it, unless you have sent a
timezone, which keeps winning until you send "timezone": null.
opening_hours REPLACES the store’s week, whatever found the old one, and from then on no
lookup of ours overwrites it. merchant_contact changes only the keys you send; a key sent
as null clears it (a cleared email sends our notices back to your account owner).
rules sets WHICH CREATORS this store will take: an array of
{attribute, operator, value}. It REPLACES the store’s rules for the attributes you send
and leaves the others alone, so sending platform rules does not touch a follower band.
Use clear_rules with a list of attribute names to remove terms outright.
THE RESPONSE CARRIES THE STORE’S RULES AS THEY NOW STAND, read back from storage rather
than echoed from your request, so one call both writes and confirms. Replace-by-attribute
means the array you get back is usually LONGER than the one you sent: send one platform
rule to a store that also has a follower band and the response carries both.
Only follower_count, platform and language may be set. ethnicity, age_band and
gender are refused with 422 validation_error: filtering paid work by a protected
characteristic needs a written policy that does not exist, and we will not store the rule
until it does.
There is no plan_tier field. We store no tier per store, and an unknown field is refused
by name rather than accepted and dropped, so a value can never be silently 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_123Request Bodyrequired
Section titled “Request Bodyrequired”Every field optional, at least one required. plan_tier is deliberately absent: we hold no
tier per store, and an unknown field is refused by name rather than accepted and dropped.
object
Stored as one line, line1, city, state postal_code, country. The store’s time zone is
derived from it, so state and postal_code are worth sending even where they feel
optional.
object
What the merchant bought. We store your numbers as you sent them AND the total they imply
(videos_per_month x term_months), because 2 x 3 and 6 x 1 are the same total and are
not the same contract, and reconciliation is held in your units.
The standard plan is 2 to 10 videos a month and a term of 3, 8 or 12 months (longer is
allowed). A plan below 2 videos a month, or below 3 months, is NOT refused: it is accepted
and carries the plan surcharge on its price (pricing.plan_surcharge).
A value outside the ranges below is refused with 400 validation_error and field set to
plan.videos_per_month or plan.term_months. Only what a request sends is checked: a
store stored earlier with other values keeps working, and a PATCH of another field does not
have to restate its plan.
object
The merchant’s choice, a whole number from 1 to 10 (2 to 10 is standard; 1 adds the plan surcharge). Paced per month (see Monthly pacing).
The contract length in months, 1 to 120 (3 or more is standard; below 3 adds the plan surcharge). The collaboration end date is the start date plus this many months.
object
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.
Send null to clear it; the store goes back to the zone read from its address.
The store’s week from your POS, venue-local. Keys mon to sun; each is a list of
["HH:MM", "HH:MM"] open and close pairs (24 hour), so an afternoon break is two pairs.
A close must be later than its open on the same day; 24:00 means open until midnight,
and a later close goes on the next day as ["00:00", ...]. A day you leave out, or send as
[], is CLOSED. Overlapping pairs are merged. At least one open pair is required.
Creators are offered times inside these hours with our house rules on top (no Saturday,
Friday until 17:00, Sunday from 15:00). A week that is only open when those rules allow no
visit (for example Saturday only) is stored, and the store reports hours.state: missing
with source: partner until the hours change.
object
The person at the restaurant. email receives our store notices (instead of your account
owner); phone receives the visit-day text message. Never shown to creators.
object
E.164, for example +14155550100. Anything else is refused with field: merchant_contact.phone.
Which creators this store will take. REPLACES the store’s rules for the attributes present and leaves the rest alone.
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
Attribute names to remove from this store outright. Needed because an empty rules
array names no attribute and so cannot say what it is clearing.
Examples
A store changed its name
{ "name": "Example Noodle House Downtown"}The merchant bought more videos
{ "plan": { "videos_per_month": 4 }}This store only wants creators with 20k+ on TikTok
{ "rules": [ { "attribute": "follower_count", "operator": "gte", "value": { "count": 20000, "platform": "tiktok" } }, { "attribute": "platform", "operator": "eq", "value": "tiktok" } ]}Drop the follower bar, keep everything else
{ "clear_rules": [ "follower_count" ]}Responses
Section titled “Responses”The store after the change.
The store as we hold it. ONE body for every verb on a location: the create’s 201 (also
returned when a terminated store is added again), an identical repeat’s 200 (plus a warning), the PATCH response, and pause, resume and terminate. Write one
receiver for it. GET /locations/{partner_location_id} returns this plus progress and the
next visit (LocationState).
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
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" } ]}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" }}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" }}location_terminated. A store whose contract has ended cannot be changed.
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" }}