This is the full developer documentation for CreatoRain API # CreatoRain API > Real creator videos for your restaurants, by API. Not live yet The API is not open on production yet. These docs describe what is built, and mark plainly what is not. ## What the API does CreatoRain sends local food creators to your restaurants. Each creator visits, posts a real video and gets measured. The API lets your own server or AI agent add stores to the CreatoRain Network. It reads back visits, posted videos and their public numbers. It previews what the month will cost. Its video-production reads never charge you. ## Two products * **Video production.** Add stores, and creators visit and post. This is the API’s main feature. Start with [Video production](https://docs.creatorain.com/guides/video-production/). * **Creator data.** Search and enrich public creator profiles. **(Not live yet)** See [Creator data](https://docs.creatorain.com/guides/creator-data/). One USD balance pays for both. See [Pricing and wallet](https://docs.creatorain.com/pricing/). ## Start here * [Quick start](https://docs.creatorain.com/get-started/quick-start/): your first calls, on the sandbox. * [Agent quick start](https://docs.creatorain.com/get-started/agent-quick-start/): how an AI agent gets a key from its human. * [Errors](https://docs.creatorain.com/errors/): every error code, one anchor each. * [API console](https://docs.creatorain.com/reference/console/): browse the spec. * For agents: [llms.txt](https://docs.creatorain.com/llms.txt). Every page also has a markdown copy: add `.md` to its path. # Agent quick start > How an AI agent with no key gets one from its human, with an onboarding session (RFC 8628 style). An AI agent should never ask its human to paste a key into a chat. It opens an **onboarding session** instead. The human approves it in the CreatoRain app, and the agent collects the key once. The flow follows the OAuth device grant (RFC 8628). Not live yet The session calls are built. The approval page in the app (`/settings/api/connect`) is not live yet, and the API is not open on production. ## 1. Open a session (no key) ```sh curl -X POST "$CREATORAIN_API/onboarding_sessions" \ -H "Content-Type: application/json" \ -d '{"client_name":"My agent","requested_scopes":["read","locations:write"],"requested_livemode":false}' ``` The `201` answer carries: * `user_code`: eight letters, such as `BCDF-GHJK`. Show it to your human. * `url`: the app page where your human types the code. * `session_secret` (`crp_obs_...`): shown **once**. It is the only way to poll. Store it like a key. * `interval`: seconds between polls. * `expires_at`: 15 minutes after creation. The scopes and mode you ask for are a request only. The human decides. ## 2. Show your human the code and the link Say what you need and why. The workspace owner signs in, enters the code and approves. They pick the mode and the scopes. ## 3. Poll ```sh curl "$CREATORAIN_API/onboarding_sessions/obs_..." \ -H "Authorization: Bearer $SESSION_SECRET" ``` * Poll every `interval` seconds. Sooner is `429 slow_down`. The interval then grows by 5 seconds, up to 60, and `Retry-After` carries it. * `status` is `pending`, `approved`, `denied` or `expired`. * The **first** poll after approval carries `key.secret`. No later poll does: `key_delivered` turns `true`. * Lost the key? `next_action` is `create_new_session`. Open a new session. * `blockers` say why an approval cannot make a key yet. For example `live_key_requires_top_up`, `key_limit_reached` or `owner_changed`. A wrong secret and an unknown id both answer `404`. Failures count toward the address block, like bad keys. ## Limits 5 sessions an hour per address, plus a global per-minute ceiling. Over it: `429 rate_limited` with `Retry-After`. ## Next Use the key as in the [Quick start](https://docs.creatorain.com/get-started/quick-start/). Read [llms.txt](https://docs.creatorain.com/llms.txt) for the agent instructions. # Authentication and keys > API keys, live and test modes, scopes, IP allowlists and the failed-auth block. Every call sends a key in the `Authorization` header: ```http Authorization: Bearer crp_test_... ``` Never put a key in a URL, a log or client-side code. ## Hosts | Mode | Host | Keys | | ------- | --------------------------------------- | --------------------------------- | | Live | `https://api.creatorain.com/v1` | `crp_live_...`, `crp_rk_live_...` | | Sandbox | `https://sandbox.api.creatorain.com/v1` | `crp_test_...`, `crp_rk_test_...` | Not live yet Neither host answers yet. Until `api.creatorain.com` resolves, the live API will also answer at `https://data.creatorain.com/v1`. ## Key kinds * `crp_live_` and `crp_test_`: standard keys, live and sandbox. * `crp_rk_live_` and `crp_rk_test_`: restricted keys, same modes. * `crp_obs_`: an onboarding session secret. It polls one session and nothing else. See [Agent quick start](https://docs.creatorain.com/get-started/agent-quick-start/). A test key on the live host is `401 test_key_on_live`. A live key on the sandbox is `401 live_key_on_sandbox`. A key is shown once, when it is made. CreatoRain stores only a hash of it. A key acts for **one workspace**. ## Scopes | Scope | Lets the key | | ----------------- | ------------------------------------------------------------- | | `read` | Read the account, locations, visits, videos and bill preview. | | `samples:read` | Read creator samples. **(Not live yet)** | | `locations:write` | Add stores. | | `balance:write` | Top up, refund, lower limits. **(Not live yet)** | | `creators:read` | Creator data. **(Not live yet)** | | `webhooks:write` | Manage webhook endpoints. **(Not live yet)** | A call without the scope it needs is `403 scope_missing`. ## IP allowlist A key may carry an IP allowlist. A request from another address is `403 forbidden_ip`. ## Failed authentication Twenty failed authentications (missing or unknown key) from one address within a minute block that address for 15 minutes. ## Live keys A live key needs one paid top-up on the account first. See [Going live](https://docs.creatorain.com/get-started/going-live/). ## Leaked keys Live key prefixes will be registered with GitHub secret scanning, so a leaked key is revoked on report. **(Not live yet)** # Going live > From test keys to live keys, and the first top-up. Not live yet The API is not open on production yet. Live keys and top-ups are not live. ## Checklist 1. Your code runs end to end on the [sandbox](https://docs.creatorain.com/get-started/sandbox/). 2. You send an `Idempotency-Key` on every POST. See [Conventions](https://docs.creatorain.com/guides/conventions/). 3. You branch on `error.code` and handle `429` with `Retry-After`. See [Errors](https://docs.creatorain.com/errors/). 4. Make a **first top-up** in the app. A live key needs one paid top-up. Without it, key approval answers `live_key_requires_top_up`. 5. Create a live key (`crp_live_...`) with only the scopes you need. 6. Switch your base URL to the live host and your key to the live key. ## What costs money * A posted creator video, at the store’s locked price per video. * Billed creator-data calls. **(Not live yet)** Video-production reads, dry runs and the bill preview never charge. Creator-data reads are billed. See [Pricing and wallet](https://docs.creatorain.com/pricing/). ## Set limits first Set daily and monthly spend limits before you scale. See [Spend limits](https://docs.creatorain.com/pricing/spend-limits/). **(Not live yet)** # Quick start > Your first CreatoRain API calls on the sandbox, in about 15 minutes. Not live yet The sandbox host is not up yet, and the API is not open on production. The steps below are the calls as built. They will run once the sandbox opens. You need a test key (`crp_test_...`) and a terminal. Set two variables once: ```sh export CREATORAIN_API="https://sandbox.api.creatorain.com/v1" export CREATORAIN_KEY="crp_test_..." ``` ## 1. Get a test key A workspace owner creates keys in the app, under **Settings > API**. **(Not live yet)** An AI agent with no key can ask its human for one. See [Agent quick start](https://docs.creatorain.com/get-started/agent-quick-start/). ## 2. Read your account ```sh curl "$CREATORAIN_API/account" -H "Authorization: Bearer $CREATORAIN_KEY" ``` The answer has your account `status`, `counting_locations` and `blockers`. See [States and blockers](https://docs.creatorain.com/guides/states-and-blockers/). ## 3. Quote a store first, with a dry run A dry run checks the request and quotes it. It writes no store. ```sh curl -X POST "$CREATORAIN_API/locations?dry_run=true" \ -H "Authorization: Bearer $CREATORAIN_KEY" \ -H "Idempotency-Key: quickstart-dry-1" \ -H "Content-Type: application/json" \ -d '{"name":"Sexy Crab Duluth","address":"2416 Pleasant Hill Rd, Duluth, GA 30096","videos_per_month":4,"accepted_terms":"network-2026-10"}' ``` The answer shows `price_per_video_cents` and the `deposit` quote. `deposit.charged` is always `false`. ## 4. Add the store Send the same body without `dry_run`, with a new `Idempotency-Key`. The store is created **on hold** (`state: on_hold`). Nothing books it until CreatoRain releases it. ## 5. Watch it work ```sh curl "$CREATORAIN_API/locations" -H "Authorization: Bearer $CREATORAIN_KEY" curl "$CREATORAIN_API/visits" -H "Authorization: Bearer $CREATORAIN_KEY" curl "$CREATORAIN_API/videos" -H "Authorization: Bearer $CREATORAIN_KEY" curl "$CREATORAIN_API/bill/preview" -H "Authorization: Bearer $CREATORAIN_KEY" ``` On the sandbox, a simulator moves a store through its life in minutes. **(Not live yet)** ## Next * [Authentication and keys](https://docs.creatorain.com/get-started/authentication/) * [Conventions](https://docs.creatorain.com/guides/conventions/): ids, times, money, paging, idempotency. * [Going live](https://docs.creatorain.com/get-started/going-live/) # Sandbox > Test keys, fixture data and a fast clock, so a store's whole life runs in minutes with no real spend. Not live yet The sandbox is not up yet. This page describes it as designed. The sandbox runs the same API with **test keys** (`crp_test_...`) at `https://sandbox.api.creatorain.com/v1`. Nothing there costs money, and no real creator is contacted. ## What is different * **Fixtures only.** Test keys read fixture creators, never real ones. Fixture emails end in `sandbox.invalid`. * **Your own sandbox.** Each workspace gets its own sandbox campaign. No other client’s data mixes in. * **A fast clock.** A simulator moves each store through matched, booked, visited, posted and billed in minutes. * **Same shapes.** The rows, ledger entries and webhooks look like live ones, with `livemode: false`. ## Sandbox-only calls Test keys only. A live key gets `404`. * `POST /v1/sandbox/top_ups`: add test money. * `POST /v1/sandbox/locations/{id}/advance`: move a store to a later state. * `POST /v1/sandbox/scenarios`: force a case, such as `no_show`, `video_taken_down`, `balance_low` or `top_up_failed`. * `POST /v1/sandbox/clock`: change the clock mode. * `POST /v1/sandbox/reset`: start over. ## The console The [API console](https://docs.creatorain.com/reference/console/) will send requests to the sandbox only, with test keys. Try-it never reaches a live host. # Conventions > Ids, times, money, pagination, idempotency, dry runs, request ids and versioning. ## Ids Ids are opaque strings with a prefix: `acct_`, `loc_`, `vis_`, `vid_`, `key_`, `obs_`. Do not parse them. ## Times * RFC 3339. * A location’s `created_at` is in UTC. * A visit’s times, and a video’s `published_at`, are on the **store’s** offset: the restaurant’s wall clock. `timezone` carries its IANA zone. * Months are `YYYY-MM`, counted on each store’s own clock. ## Money Integer cents, with `currency: "USD"`. API usage is priced in micro-dollars (1 USD = 1,000,000). **(Not live yet)** ## Pagination Lists take `limit` (1 to 200, default 50) and `cursor`. * Pass the previous page’s `next_cursor` unchanged. Leave it out for the first page. * `next_cursor` is `null` on the last page. * A changed cursor is `400 parameter_invalid` (field `cursor`). * Visits page by last update, so a visit can appear again on a later page. Dedupe on `id`. ## Idempotency Send `Idempotency-Key` on every POST, PATCH and DELETE. It is **required** on money calls and location creates. * Up to 255 printable ASCII characters, no spaces. * A retry with the same key and body gets the stored answer, with `Idempotent-Replayed: true`, for 24 hours. * The same key with a different body is `409 idempotency_conflict`. * A duplicate while the first is still running is `409 idempotency_in_progress`. * A `400` or `5xx` answer is not stored, so a corrected retry may reuse the key. ## Dry runs `dry_run=true` on a create checks and quotes, with the same refusals as a live call. It writes no store. Ids come back `null`. The `Idempotency-Key` is still stored. ## Request ids Every answer has a `Request-Id` header. It equals `error.request_id`. Quote it to support. ## Errors Every error has one envelope: ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "message": "...", "field": "limit", "doc_url": "https://docs.creatorain.com/errors#parameter_invalid", "request_id": "..." } } ``` Branch on `code`. See [Errors](https://docs.creatorain.com/errors/). ## Versioning * The major version is in the path: `/v1`. * Changes inside v1 are additive: new fields, new endpoints, new codes. Ignore fields you do not know. * A breaking change ships as `/v2`, with 6 months of overlap. * A `CreatoRain-Version` header is reserved. **(Not live yet)** See the [Changelog](https://docs.creatorain.com/changelog/). # Errors > Every CreatoRain API v1 error code, its HTTP status and type, and how to fix it. One anchor per code. Every error has one envelope: ```json { "error": { "type": "permission_error", "code": "scope_missing", "message": "...", "field": "...", "doc_url": "https://docs.creatorain.com/errors#scope_missing", "request_id": "..." } } ``` * **Branch on `code`**, never on `message`. Messages may change. * `type` groups codes: `invalid_request_error`, `authentication_error`, `permission_error`, `idempotency_error`, `rate_limit_error`, `api_error`. * `field` names the request field at fault, when one is. * `request_id` equals the `Request-Id` header. Quote it to support. * A `5xx` message never carries a cause. Each code below has its own anchor, `/errors#`. A code marked **Not live yet** is designed, but no live route returns it yet. Note Today an error’s `doc_url` still points at the old www address. It moves to this page at launch. ## 400 Bad request ### `parameter_invalid` HTTP 400, type `invalid_request_error`. A query or body field is wrong. `field` names it. A cursor you changed is this error too. **Fix:** Correct the field named in `field` and retry. ### `invalid_json` HTTP 400, type `invalid_request_error`. The request body is not valid JSON. **Fix:** Send a valid JSON body with `Content-Type: application/json`. ### `idempotency_key_invalid` HTTP 400, type `invalid_request_error`. The `Idempotency-Key` header is empty, longer than 255 characters, or has spaces or non-printable characters. **Fix:** Send 1 to 255 printable ASCII characters, no spaces. ### `idempotency_key_required` HTTP 400, type `invalid_request_error`. This call needs an `Idempotency-Key` header. Location creates and money calls require one. A dry run needs one too. **Fix:** Add a unique `Idempotency-Key` per logical request. ### `customization_not_supported` HTTP 400, type `invalid_request_error`. The request set a creator field, such as `min_followers`, `rules` or `approval_mode`. CreatoRain chooses the creators. **Fix:** Remove every creator field from the request. ### `videos_per_month_out_of_range` HTTP 400, type `invalid_request_error`. `videos_per_month` is outside the plan's range. Paid: 2 to 10. Free: exactly the free plan's videos. **Fix:** Send a value inside the range. ### `batch_invalid` HTTP 400, type `invalid_request_error`. A batch had one or more refused items. Nothing was written. `error.items` lists each refused item by index. **Fix:** Fix every item in `error.items` and send the whole batch again. ### `terms_not_accepted` HTTP 400, type `invalid_request_error`. A new or returning store needs `accepted_terms`, the network terms version accepted. **Fix:** Send `accepted_terms` with the terms version the store accepted. ### `invalid_filter` HTTP 400, type `invalid_request_error`. Not returned: see [`parameter_invalid`](#parameter_invalid). Named in the design for a bad search filter. The API does not return it: a bad filter answers `parameter_invalid`. **Fix:** Handle `parameter_invalid`. ### `invalid_request` HTTP 400, type `invalid_request_error`. Not returned: see [`parameter_invalid`](#parameter_invalid). Named in the design for a bad request field. The API does not return it: a bad field answers `parameter_invalid`. **Fix:** Handle `parameter_invalid`. ### `cursor_expired` HTTP 400, type `invalid_request_error`. Not returned: see [`parameter_invalid`](#parameter_invalid). Named in the design for a cursor that no longer works. The API does not return it: a changed cursor answers `parameter_invalid`. **Fix:** Handle `parameter_invalid`, then start the list again without a cursor. ## 401 Unauthorized ### `invalid_key` HTTP 401, type `authentication_error`. The key is missing, unknown or revoked. **Fix:** Send `Authorization: Bearer ` with an active key. ### `test_key_on_live` HTTP 401, type `authentication_error`. A `crp_test_` key was sent to the live host. **Fix:** Use a live key on live, or call the sandbox. ### `live_key_on_sandbox` HTTP 401, type `authentication_error`. A `crp_live_` key was sent to the sandbox. **Fix:** Use a test key on the sandbox. ## 402 Payment required ### `insufficient_balance` **(Not live yet)** HTTP 402, type `invalid_request_error`. Your balance cannot cover this call. A batch create with `require_funded: true` and a billed creator-data call answer it. A store added without `require_funded` waits in `awaiting_payment` instead. **Fix:** Top up, then retry with a new `Idempotency-Key`. A 402 answer is stored for the old key. ### `spend_limit_reached` **(Not live yet)** HTTP 402, type `invalid_request_error`. Not in the v1 spec yet. A creator-data call would go over the daily or monthly data spend limit. Nothing is billed. **Fix:** Wait for the next day or month, or raise the limit in the app. Retry with a new `Idempotency-Key`. ### `max_cost_exceeded` **(Not live yet)** HTTP 402, type `invalid_request_error`. Not in the v1 spec yet. The call's worst-case cost is above the `max_cost_cents` you sent. It did not run. **Fix:** Raise `max_cost_cents`, or ask for fewer rows. Retry with a new `Idempotency-Key`. ### `reveal_expired` **(Not live yet)** HTTP 402, type `invalid_request_error`. Not in the v1 spec yet. `GET /v1/creators/{id}` came more than 30 days after the last paid read of that creator. A GET never spends money. **Fix:** Call `POST /v1/creators/enrich/handle` to read the creator again (billed). ## 403 Forbidden ### `scope_missing` HTTP 403, type `permission_error`. The key lacks the scope this route needs. **Fix:** Create a key with the scope, or ask the workspace owner. ### `forbidden_ip` HTTP 403, type `permission_error`. The key has an IP allowlist, and this request came from another address. **Fix:** Call from an allowed address, or update the allowlist in the app. ### `forbidden` HTTP 403, type `permission_error`. The action is not allowed for this account. **Fix:** Check the account's state with `GET /account`. ### `live_key_requires_top_up` HTTP 403, type `permission_error`. A live key needs one paid top-up on the account first. **Fix:** Make a first top-up in the app, then approve the key again. ### `limit_raise_requires_dashboard` **(Not live yet)** HTTP 403, type `permission_error`. The API can lower a spend limit, never raise one. **Fix:** Raise the limit in the app. ## 404 Not found ### `not_found` HTTP 404, type `invalid_request_error`. No such object for this account. A malformed id, an unknown id and another account's id all answer the same. **Fix:** Check the id and the key's workspace. ## 409 Conflict ### `idempotency_conflict` HTTP 409, type `idempotency_error`. The same `Idempotency-Key` was sent with a different body. **Fix:** Use a new key for a new request. ### `idempotency_in_progress` HTTP 409, type `idempotency_error`. The first request with this key is still running. **Fix:** Wait, then retry with the same key and body. ### `conflict` HTTP 409, type `invalid_request_error`. The request conflicts with the object's current state. **Fix:** Read the object again, then retry. ### `location_already_in_network` HTTP 409, type `invalid_request_error`. Another team of this account holds the place, or the same place is listed under another name. **Fix:** Use the existing location, or ask the team that holds it. ### `external_id_conflict` **(Not live yet)** HTTP 409, type `invalid_request_error`. Your `external_id` label is already used in this workspace. **Fix:** Use a unique `external_id`. ### `dispute_open` **(Not live yet)** HTTP 409, type `invalid_request_error`. A card dispute is open on this account. **Fix:** Contact support with the `request_id`. ### `job_limit_reached` **(Not live yet)** HTTP 409, type `invalid_request_error`. Not in the v1 spec yet. The account already has 5 active creator-data jobs. **Fix:** Wait for a job to finish, then create the new one. ## 413 Request too large ### `request_too_large` HTTP 413, type `invalid_request_error`. The request body is too large. **Fix:** Send fewer items per request. A batch takes at most 50 locations. ## 422 Unprocessable ### `address_not_verified` **(Not live yet)** HTTP 422, type `invalid_request_error`. The store's address could not be verified. **Fix:** Send the full street address, or a `google_place_id`. ### `not_food_business` **(Not live yet)** HTTP 422, type `invalid_request_error`. The place is not a restaurant or food business. **Fix:** Check the address or place id. ### `metro_not_served` **(Not live yet)** HTTP 422, type `invalid_request_error`. CreatoRain does not serve this metro yet. **Fix:** Try again later, or contact support. ### `package_not_available` HTTP 422, type `invalid_request_error`. The plan asked for is not the account's plan, or a free-plan account tried to bring back a store that already ran its free term. **Fix:** Omit `plan` to use the account's plan. ### `account_location_limit` **(Not live yet)** HTTP 422, type `invalid_request_error`. The account has reached its location limit. **Fix:** Contact support to raise it. ### `commit_limit_exceeded` **(Not live yet)** HTTP 422, type `invalid_request_error`. The call would go over the account's monthly spend limit. **Fix:** Raise the limit in the app, or plan fewer videos. ### `top_up_exceeds_feasible` **(Not live yet)** HTTP 422, type `invalid_request_error`. The top-up is larger than the account can spend soon. **Fix:** Top up a smaller amount. ### `no_saved_card` **(Not live yet)** HTTP 422, type `invalid_request_error`. The call needs a saved card, and the account has none. **Fix:** Save a card in the app. ### `data_price_not_set` **(Not live yet)** HTTP 422, type `invalid_request_error`. Not in the v1 spec yet. A creator-data product has no published price yet, so the call is refused and nothing is billed. **Fix:** Try again after prices are published. ### `min_locations_not_met` **(Not live yet)** HTTP 422, type `invalid_request_error`. Not in the v1 spec yet. Creator data needs an account with enough counting locations and a prepaid balance. `blockers[]` and `next_action` say what is missing. Never billed. **Fix:** Do the `next_action`, then retry. ### `platform_not_supported` **(Not live yet)** HTTP 422, type `invalid_request_error`. Not in the v1 spec yet. The platform is not one CreatoRain holds. At launch: `instagram`, `tiktok`, `youtube`. Never billed. **Fix:** Send one of the supported platforms. ### `audience_not_available` **(Not live yet)** HTTP 422, type `invalid_request_error`. Not in the v1 spec yet. Audience fields are reserved in the schema, but no data is served for them yet. Never billed. **Fix:** Leave the audience fields out of the request. ## 429 Too many requests ### `rate_limited` HTTP 429, type `rate_limit_error`. Over the limit: 600 requests a minute per workspace, the onboarding create limit, or an address blocked after failed sign-ins. **Fix:** Wait `Retry-After` seconds, then retry. ### `quota_exceeded` **(Not live yet)** HTTP 429, type `rate_limit_error`. A usage quota for this period is used up. **Fix:** Wait for the next period, or contact support. ### `slow_down` HTTP 429, type `rate_limit_error`. An onboarding session was polled sooner than its `interval`. The interval grows by 5 seconds, up to 60. **Fix:** Wait `Retry-After` seconds between polls. ## 500 Server error ### `internal_error` HTTP 500, type `api_error`. Something failed on our side. The message never carries a cause. **Fix:** Retry with the same `Idempotency-Key`. Quote the `request_id` to support if it repeats. ## 503 Unavailable ### `service_unavailable` HTTP 503, type `api_error`. The service cannot answer right now. A concurrent write to the same locations also answers this. The bill preview answers it over 2,000 locations. **Fix:** Retry after `Retry-After` with the same key. ### `vendor_unavailable` **(Not live yet)** HTTP 503, type `api_error`. Not in the v1 spec yet. The outside source behind a vendor-backed creator-data field cannot answer right now. Never billed. **Fix:** Retry after `Retry-After`. # Changelog > Changes to the CreatoRain API, and the deprecation policy. The reference on this site is built from the API spec at commit `6555b098ea81`, copied on 2026-10-31. ## 2026-10-31 * First build of this docs site. * v1 spec: account, onboarding sessions, locations (one or a batch, with dry runs), visits, videos, bill preview. A spec diff of each release will be listed here. **(Not live yet)** ## Deprecation policy * Changes inside `/v1` are additive. Ignore fields you do not know. * A breaking change ships as `/v2`. `/v1` keeps working for 6 months after `/v2` ships. * A route being retired will send `Deprecation` and `Sunset` headers first. **(Not live yet)** # Coverage and capacity > Where CreatoRain has creators, how fast a store fills, and how monthly pacing works. Creators are local. A store fills as fast as nearby creators can visit. ## What you can read today * **`network.accepting`** on `GET /locations`: whether the network takes bookings now. * **`state`** on each store. `full_this_month` means the month’s videos are paced and the store waits for next month. `needs_hours` means the store has no bookable hours yet. * **`month`** on `GET /locations/{id}`: `planned`, `allowance`, `booked`, `visited`, `posted`, and `full` with `full_until`. ## Monthly pacing Each store gets its videos a month, spread over its own local month. When a month is full, the store shows `full_this_month` until the next month starts. ## Coverage check `GET /v1/coverage?address=` will answer whether a metro is served, and a first-visit estimate, before you add a store. **(Not live yet)** A store in a metro CreatoRain does not serve will be refused with `422 metro_not_served`. **(Not live yet)** # Creator data > Search and enrich public creator profiles, priced per result in USD. Privacy and opt-out. Not live yet Creator data is not live yet. None of these calls is in the v1 spec today. This page describes it as designed. Creator data is the API’s second product. It reads public creator profiles: their stats, bio and links. ## Calls (as designed) * `POST /v1/creators/search` and `POST /v1/creators/similar`: find creators. Search is free, up to a monthly ceiling. * `POST /v1/creators/enrich/handle` and `POST /v1/creators/enrich/email`: read one creator’s full profile. * `GET /v1/creators/{id}/posts`: a creator’s posts, by page. Each billed call is priced per result, in USD, from your [balance](https://docs.creatorain.com/pricing/wallet/). See [Prices](https://docs.creatorain.com/pricing/). ## Who can buy it Any account with a saved card and a paid top-up. Usage ceilings and the API terms apply. ## What is exposed Only what the creator published: profile and post numbers, bio and links. Contact emails come later, and only ones we can show are public. Never exposed: private emails, street addresses, or personal traits such as gender or ethnicity. ## Opt-out A creator can hide their profile from the data API: * on the creator portal, * on the www opt-out page, * or by email to . An opt-out is applied within one business day. Opting out of the data API does not unsubscribe a creator from CreatoRain’s own outreach. ## Webhooks carry no creator data Data job events hold ids, status and counts only. # Orders > Website, budget per video and total videos in. Finished posted videos out. Not live yet Orders are not live yet. None of these calls is in the v1 spec today. This page describes them as designed. An order is the shortest path: give your website, an average budget per video, and how many videos you need in total. CreatoRain returns finished, posted creator videos. ## How it works 1. `POST /v1/orders` with `website`, `average_budget_per_video_cents` and `total_videos`. CreatoRain finds your stores from the site. 2. The answer is a **quote**: options, a schedule per store, and a time range to finish. Never a single date. 3. `POST /v1/orders/{id}/confirm` writes the stores. It does not charge. 4. Fund it with a top-up. The order then schedules visits. 5. `GET /v1/orders/{id}` shows progress. `GET /v1/orders/{id}/videos` lists the finished videos. ## States `quoted` → `awaiting_funds` → `scheduling` → `in_production` → `delivered`. An order can also end `partially_delivered`, `cancelled`, `refunded` or `expired`. A quote expires after 24 hours. Low balance and capacity are **blockers** on the order, not states. Follow `next_action`. ## Rules * The website decides **where**, never **which creators**. A creator field is `400 customization_not_supported`. * The total stays at or under budget × count. * A finished video is the creator’s own post. You may repost, link and embed it with credit to the creator. # Rate limits > 600 requests a minute per workspace, the headers that report it, and how to back off. ## The limit **600 requests a minute per workspace**, counted across every server that answers. Each answer reports where you stand: | Header | Meaning | | --------------------- | ----------------------------------- | | `RateLimit-Limit` | Requests allowed this minute (600). | | `RateLimit-Remaining` | Requests left this minute. | | `RateLimit-Reset` | Seconds until the window resets. | Over the limit: `429 rate_limited` with `Retry-After` (at least 1 second). Wait that long, then retry with the same `Idempotency-Key`. ## Other limits * **Failed sign-ins:** 20 failed authentications from one address within a minute block that address for 15 minutes. * **Onboarding sessions:** 5 an hour per address, plus a global per-minute ceiling. * **Polling a session:** sooner than its `interval` is `429 slow_down`. The interval grows by 5 seconds, up to 60. ## Good habits * Page with `limit` up to 200 instead of many small calls. * Back off on `429`. Do not retry in a tight loop. * Use [webhooks](https://docs.creatorain.com/guides/webhooks/) instead of polling, once they are live. ## Creator data quotas Creator data will have its own monthly ceilings, answered with `429 quota_exceeded`. **(Not live yet)** # States and blockers > Account status, location states, blockers and next_action. An agent should not parse a state machine. Read `state` and `blockers`, and follow `next_action`. ## Account status `GET /account` returns `status`: | Status | Meaning | | ------------------ | --------------------------------- | | `awaiting_payment` | No payment yet. | | `active` | Running. | | `past_due` | A payment failed. | | `paused` | The client paused all production. | | `stopped` | Closed. | It also returns `counting_locations`, `min_locations` and `max_locations`. Read them; do not hard-code them. ## Location state Each store has one `state`, the same one the app’s Network page shows: | State | Meaning | | ------------------ | ---------------------------------------------------- | | `on_hold` | Added by API. Waits for CreatoRain to release it. | | `awaiting_payment` | Waits for payment. | | `needs_hours` | Has no bookable hours. | | `full_this_month` | This month’s videos are paced. Waits for next month. | | `accepting` | Open to creators. `accepting: true`. | | `paused` | Paused by you. | | `payment_failed` | Paused by a failed payment or a dispute. | | `ended` | Ended. | `status` is the plain lifecycle: `active`, `paused` or `ended`. `held` is `true` while the API hold stands. ## Blockers `blockers` lists why something cannot move yet. * On a location create: `below_minimum` while `counting_locations` is under `min_locations`. * On an onboarding session: `live_key_requires_top_up`, `key_limit_reached`, `owner_changed`. ## next_action `next_action` names the one thing to do next, such as a top-up. Today it is `null` on the account until the features behind each state ship. **(Not live yet)** # Video production > Add stores to the CreatoRain Network, and read back visits, posted videos and the bill. This is the API’s main feature. You add your stores. CreatoRain recruits local food creators, books their visits, and they post real videos. Not live yet These calls are built. The API is not open on production yet. ## The flow 1. **Quote** a store with `POST /locations?dry_run=true`. 2. **Add** it with `POST /locations`, or 1 to 50 at once with `POST /locations/batch`. 3. The store starts **on hold**. CreatoRain releases it to recruiting. 4. **Watch** with `GET /locations/{id}`, `GET /visits` and `GET /videos`. 5. **Preview** the month with `GET /bill/preview`. ## Adding a store Required fields: `name`, `address` (one line, or `line1`, `city`, `state`), `videos_per_month`. Optional: `google_place_id`, `plan`, `opening_hours`, `signature_dishes`. * **`accepted_terms`** is required for a new or returning store. It is the network terms version the store accepted, the meal waiver included. Without it: `400 terms_not_accepted`. * **`Idempotency-Key`** is required. Without it: `400 idempotency_key_required`. * **Paid plan:** `videos_per_month` is 2 to 10, at the account’s locked price per video. * **Free plan:** exactly the free plan’s videos for its term, with no deposit. * **`plan`** left out means the account’s plan. Another plan is `422 package_not_available`. * There is no store maximum. ### You do not choose the creators CreatoRain chooses the creators. Any creator field (`min_followers`, `rules`, `approval_mode`, …) is `400 customization_not_supported`. It is never silently ignored. ### The deposit is a quote On the paid plan, `deposit.cents` quotes half of month one: videos a month × price per video ÷ 2. It is paid later at Checkout. **No API call charges it** (`deposit.charged: false`). ### Repeats and conflicts * The same place again answers `200` with `outcome: repeat` and the **stored** plan. A create never updates a store. * An ended store comes back with `201` and `outcome: revive`. * A place another team of your account holds is `409 location_already_in_network`. ### Batches are all or nothing `POST /locations/batch` takes 1 to 50 stores. If any item is refused, the answer is `400 batch_invalid`, every refused item is in `error.items` by index, and **nothing** is written. ## Reading back * **`GET /locations`**: every store, oldest first, with `state`, `held` and `accepting`. `network.accepting` says whether the network takes bookings at all. * **`GET /locations/{id}`**: adds `month`, this store-local month’s pace: `planned`, `booked`, `visited`, `posted`, `full`. * **`GET /visits`**: newest update first. Filter by `location`, `status`, `from`, `to`. Times are on the **store’s** clock. A visit can appear again on a later page, so dedupe on `id`. * **`GET /videos`**: newest first. `counted_on_bill` is `true` only for a video stated at its store. `stats` is `null` until the public post is first read. Creators appear by public handle only. ## The bill preview `GET /bill/preview?month=YYYY-MM` shows the month’s bill, one line per store, in cents. It never charges (`charged: false`). `total_cents` is `null` when a store has no locked price yet. Over 2,000 stores the answer is `503 service_unavailable` rather than a short bill. ## Stores and creators tell each other A `visit.booked` webhook will tell your system a creator is coming, so you can tell the store. **(Not live yet)** See [Webhooks](https://docs.creatorain.com/guides/webhooks/). # Webhooks > Signed event delivery to your HTTPS endpoint, retries, and the events list. Not live yet Webhooks on v1 are not live yet. This page describes them as designed. Until then, poll the reads. ## Endpoints * `POST /v1/webhook_endpoints` with `{url, events}`. The answer carries a `secret` (`whsec_...`), **once**. * `GET`, `PATCH`, `DELETE /v1/webhook_endpoints/{id}`. * `POST /v1/webhook_endpoints/{id}/rotate_secret`: the old secret stays valid for 24 hours. * `POST /v1/webhook_endpoints/{id}/test`: sends one `ping`. * `GET /v1/events`: a poll fallback, 30 days back. The URL must be `https:` on port 443, on a public address. Redirects count as a failure. ## Envelope ```json { "id": "evt_...", "type": "visit.booked", "created": 1793000000, "livemode": true, "account_id": "acct_...", "data": { "object": {} } } ``` ## Signature Each delivery carries one header: ```http CreatoRain-Signature: t=,v1= ``` Check it with your endpoint secret. Refuse a timestamp more than 300 seconds old. During a secret rotation, two `v1=` values are sent. ## Retries A failed delivery is retried after 1 minute, 5 minutes, 30 minutes, 2, 6 and 12 hours, then 24 hours twice: about 72 hours in all. After 3 days of failures the endpoint is disabled, with a `webhook_endpoint.disabled` event and a banner in the app. Order is not guaranteed. Dedupe on `id`. ## Events * **Locations:** `location.created`, `location.paused`, `location.resumed`, `location.terminated`. * **Production:** `visit.booked`, `visit.rescheduled`, `visit.cancelled`, `visit.completed`, `visit.no_show`, `video.posted`, `video.billed`, `video.taken_down`, `video.stats_updated`. * **Money:** `balance.topped_up`, `balance.top_up_failed`, `balance.low`, `balance.depleted`, `balance.refunded`, `balance.credited`, `balance.disputed`. * **Account:** `api_key.created`, `api_key.revoked`, `webhook_endpoint.disabled`. `visit.booked` is how your system learns a creator is coming, so you can tell the store. # Partner API > The API a POS or ordering platform uses to enrol its merchants' stores with CreatoRain. The Partner API is a separate surface from v1. A POS or ordering platform uses it to enrol its merchants’ stores, then read their reservations, published content and monthly billing. It is live for signed partners. It is not self-serve: CreatoRain issues each partner a key. ## Hosts | Mode | Host | | ------------------------------ | ------------------------------------------- | | Production | `https://data.creatorain.com/partner/v1` | | Sandbox, for integration tests | `https://datadev.creatorain.com/partner/v1` | ## Authentication One long-lived key per partner, sent as `Authorization: Bearer `. Keys look like `crp_live_...` on production and `crp_test_...` elsewhere. * The header is `Authorization` on every route. There is no `x-api-key` header. A key sent in one is not read, and the answer is `401 unauthorized`. * A key is scoped to one account and one campaign. It cannot read another customer’s data. * A key may carry an IP allowlist. Another address is `403 forbidden_ip`. ## Errors ```json { "error": { "code": "location_already_exists", "message": "...", "field": "partner_location_id" } } ``` Branch on `code`, never on `message`. This envelope is frozen for partners. It differs from v1’s. ## Rate limit 600 requests a minute per key by default. Over it: `429 rate_limited`, with `RateLimit-*` headers. ## Reference The [Partner reference](https://docs.creatorain.com/partner-api/reference/) is generated from the partner spec. The raw spec is at [`/partner-openapi.json`](https://docs.creatorain.com/partner-openapi.json). # Prices > API prices in US dollars, per call and per 1,000, from one balance. No credits to convert. One balance pays for videos and API calls. Prices are in US dollars. No monthly fee. No credits to convert. **Prices are published at launch.** They will appear here, read from the same reviewed snapshot as the www pricing page. ## How the numbers get here Prices are set by CreatoRain and served by `GET /v1/prices`. A reviewed snapshot of that answer feeds this page and the www pricing page. No price is typed into a page. **(Not live yet)** A product with no published price is left out, never shown as a dash. ## What you are never billed for * A creator not found. * An empty page. * A re-read of the same creator within 30 days. * A replayed `Idempotency-Key`. * Video-production reads (account, locations, visits, videos), dry runs and the bill preview. ## What each call cost Every billed call will return a `cost` object, `{amount_micros, currency: "USD"}`, and a `CreatoRain-Cost` header. Usage is priced in micro-dollars (1 USD = 1,000,000 micros), so a price per 1,000 is exact. **(Not live yet)** ## Next * [Wallet](https://docs.creatorain.com/pricing/wallet/): the one balance. * [Top-ups, holds and refunds](https://docs.creatorain.com/pricing/top-ups-holds-refunds/) * [Spend limits](https://docs.creatorain.com/pricing/spend-limits/) # Spend limits > Daily and monthly limits, the low-balance alert, and what happens at the limit. Not live yet Spend limits are not live yet. This page describes them as designed. You can cap what the API spends. * **Daily** and **monthly** limits, set in the app. * A **low-balance threshold**. When “$X left” falls below it, you get a `balance.low` event and a banner in the app. It is your own setting, and it starts empty. ## Lower by API, raise in the app `PATCH /v1/balance/settings` can **lower** a limit. It can never raise one. A raise by API answers `403 limit_raise_requires_dashboard`, with a link to the app. So a leaked key cannot lift your caps. ## At the limit What happens depends on the product. * **Creator data.** A billed call that would pass the daily or monthly data limit is refused. It answers `402 spend_limit_reached`, and nothing is charged. * **Video production.** Nothing is refused. A video slot that would pass the daily limit or the monthly commit limit does not open. The store waits and shows `awaiting_payment` until the limit has room. See [Errors](https://docs.creatorain.com/errors/#spend_limit_reached). # Top-ups, holds and refunds > Adding money, how a video holds its price, how API usage is booked, refunds and statements. Not live yet Top-ups, holds, refunds and statements are not live yet. This page describes them as designed. ## Top-ups * Top up in the app, with a card, by Stripe Checkout. * By API: `POST /v1/balance/top_ups` returns a `checkout_url`. A human finishes the payment. * The smallest top-up is set by CreatoRain and published with the [prices](https://docs.creatorain.com/pricing/). It is a payment floor, not a spend minimum. * Each top-up shows a receipt link on the Balance page. ## Holds When a creator visit is booked, a **hold** sets aside the store’s locked price per video. When the video goes live, the hold becomes a charge. If the visit does not happen, the hold is released. Held money still belongs to you. It just is not in “$X left”. ## API usage Each billed call is priced in micro-dollars. Usage is written to your statement in small batches, and at the end of each UTC day. The rest carries over. No call is rounded up to a whole cent. ## Refunds * **Cash** is refundable on request, less the card fee. Or wait 30 days or more and get it back in full. * **Granted** money is never refunded. * Nothing expires. ## Statements A monthly statement lists the opening balance, top-ups, video charges, API usage, grants, refunds and the closing balance. **(Not live yet)** ## Auto-recharge Top up automatically when the balance falls below a level you set. **(Not live yet)** # Wallet > One USD balance, shared by creator videos and API calls. You see "$X left". No credits. Not live yet The wallet is not live yet. This page describes it as designed. Your workspace has **one balance, in US dollars**. Creator videos and API calls both draw from it. The app shows it as **“$X left”**. There are no credits and no exchange rate. ## What “$X left” means > left = cash + granted − held − usage not yet booked * **Cash** is money you topped up. It never expires. * **Granted** is money CreatoRain gave you. It shows as “Granted by CreatoRain (not refundable)”. Granted money is spent first. * **Held** is money set aside for videos already booked. See [holds](https://docs.creatorain.com/pricing/top-ups-holds-refunds/#holds). * **Usage not yet booked** is API usage priced but not yet written to your statement. ## $5 to start A new account gets **$5, once**, when it saves a card. It is granted money: not refundable, and one per card. **(Not live yet)** ## When the balance is below zero Stores that joined through the app’s Join flow keep running if the balance runs out. The app then says “You owe $Y. It goes on your card at month end.” Stores added by API need enough balance to open each video slot. If the balance is short, new video slots wait. Each store shows `awaiting_payment`, and the account carries the blocker `insufficient_balance`. A batch create with `require_funded: true` answers `402 insufficient_balance` instead. **(Not live yet)** ## Reading it by API Not live yet * `GET /v1/balance`: `available_cents`, `cash_cents`, `granted_cents`, `held_cents`. * `GET /v1/balance/entries`: every money event, one line each. * `GET /v1/balance/holds`: open holds. Amounts are integer cents in USD. ## Who sees it Owners and billing roles see the balance and top up. A plain member does not. # SDKs and tools > The OpenAPI spec, TypeScript and Python SDKs, and the CreatoRain MCP server for AI agents. ## OpenAPI spec The v1 spec is public here: [`/openapi.json`](https://docs.creatorain.com/openapi.json). It is the same file this site’s reference is generated from. Feed it to any OpenAPI tool. The Partner API spec is at [`/partner-openapi.json`](https://docs.creatorain.com/partner-openapi.json). ## TypeScript A TypeScript client generated from the spec, on npm. **(Not live yet)** ## Python A Python client generated from the spec, on PyPI. **(Not live yet)** ## MCP server An MCP server for AI agents at `https://api.creatorain.com/mcp`, with your API key. It will also search these docs. **(Not live yet)** ## For agents today * [llms.txt](https://docs.creatorain.com/llms.txt): an index, with instructions for agents. * [llms-full.txt](https://docs.creatorain.com/llms-full.txt): every guide in one file. * Every page has a markdown copy: add `.md` to its path. # Status > Where to see whether the CreatoRain API is up. Not live yet There is no public status page yet, and no `GET /v1/health`. This page will link to them. Until then: * Every answer carries a `Request-Id`. Quote it when you report a problem. * A `503 service_unavailable` with `Retry-After` is safe to retry with the same `Idempotency-Key`. * Report a problem to . # API reference Every generated endpoint page, v1 then Partner API. ## v1 API reference overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### CreatoRain API 1.0.0 A client’s own server or AI agent, holding a key for ONE workspace, uses this API to run restaurant video production. Every response carries a `Request-Id` header; every error has the envelope `{error:{type, code, message, field?, doc_url, request_id}}`. Rate limit: 600 requests a minute per workspace, across every server that answers. Above it, `429 rate_limited` with `Retry-After`. Twenty failed authentications (missing or unknown key) from one address within a minute block that address for 15 minutes. Information - OpenAPI version: `3.0.3` ### Operations GET [/account](https://docs.creatorain.com/reference/operations/getaccount/) POST [/onboarding\_sessions](https://docs.creatorain.com/reference/operations/createonboardingsession/) GET [/onboarding\_sessions/{id}](https://docs.creatorain.com/reference/operations/getonboardingsession/) GET [/locations](https://docs.creatorain.com/reference/operations/listlocations/) POST [/locations](https://docs.creatorain.com/reference/operations/createlocation/) POST [/locations/batch](https://docs.creatorain.com/reference/operations/createlocationsbatch/) GET [/locations/{id}](https://docs.creatorain.com/reference/operations/getlocation/) GET [/visits](https://docs.creatorain.com/reference/operations/listvisits/) GET [/videos](https://docs.creatorain.com/reference/operations/listvideos/) GET [/bill/preview](https://docs.creatorain.com/reference/operations/getbillpreview/) ### Authentication #### bearerAuth Authorization: Bearer crp\_live\_… or crp\_rk\_live\_… (live), crp\_test\_… or crp\_rk\_test\_… (sandbox). **Security scheme type:** http #### sessionSecret Authorization: Bearer crp\_obs\_… (the session\_secret from POST /onboarding\_sessions). Polls one session only. **Security scheme type:** http Source: https://docs.creatorain.com/reference/ (markdown: https://docs.creatorain.com/reference.md) ## Add one location to the CreatoRain Network **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). POST /locations Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/locations?dry_run=false'; const options = { method: 'POST', headers: { 'Idempotency-Key': 'example', Authorization: 'Bearer ', 'Content-Type': 'application/json' }, body: '{"name":"Sexy Crab Duluth","address":"2416 Pleasant Hill Rd, Duluth, GA 30096","google_place_id":"example","plan":"paid","videos_per_month":4,"accepted_terms":"network-2026-10","opening_hours":{},"signature_dishes":[{"name":"example"}]}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url 'https://api.creatorain.com/v1/locations?dry_run=false' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: example' \ --data '{ "name": "Sexy Crab Duluth", "address": "2416 Pleasant Hill Rd, Duluth, GA 30096", "google_place_id": "example", "plan": "paid", "videos_per_month": 4, "accepted_terms": "network-2026-10", "opening_hours": {}, "signature_dishes": [ { "name": "example" } ] }' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `locations:write`. The store is created ON HOLD (`state: on_hold`): nothing recruits or books it until CreatoRain releases it. The plan is the account’s: on the paid plan `videos_per_month` is 2 to 10 at the locked price per video, and `deposit` quotes the half of month one (paid later at Checkout, never charged here); on the free plan it is exactly the free plan’s videos for its term, with no deposit. There is no store maximum. Creator selection is CreatoRain’s: a creator field (`min_followers`, `rules`, `approval_mode`, …) is `400 customization_not_supported`. The same place again answers `200` with `outcome: repeat` and the STORED plan (a create never updates one); a place another team of this account holds is `409 location_already_in_network`. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Header Parameters **Idempotency-Key** required string \>= 1 characters <= 255 characters /^\[\\x21-\\x7E\]+$/ As `Idempotency-Key`, and required here (a location create). Without it the answer is `400 idempotency_key_required`. A dry run needs one too: it writes no store row; the Idempotency-Key is still stored. #### Query Parameters **dry\_run** boolean `true` validates and quotes: the same refusals as a live call, and writes no store row; the Idempotency-Key is still stored. Ids are null. ### Request Bodyrequired Media typeapplication/json object **name** required string \>= 1 characters <= 300 characters #### Example ``` Sexy Crab Duluth ``` **address** required One of: - [string](#tab-panel-0-0) - [object](#tab-panel-0-1) string \>= 5 characters <= 400 characters #### Example ``` 2416 Pleasant Hill Rd, Duluth, GA 30096 ``` object **line1** required string <= 300 characters **city** required string <= 120 characters **state** required string <= 120 characters **postal\_code** string nullable <= 40 characters **country** string nullable <= 120 characters **google\_place\_id** string nullable <= 300 characters **plan** Absent means the account’s plan; another plan is 422 package\_not\_available. string Allowed values: paid free **videos\_per\_month** required Paid: 2 to 10. Free: exactly the free plan’s videos. Otherwise 400 videos\_per\_month\_out\_of\_range. integer #### Example ```json 4 ``` **accepted\_terms** The network terms version accepted string nullable /^\[a-z0-9\]\[a-z0-9.-\]{2,59}$/ #### Example ``` network-2026-10 ``` **opening\_hours** The store’s week object **signature\_dishes** Array <= 50 items One of: - [string](#tab-panel-1-0) - [object](#tab-panel-1-1) string <= 300 characters object **name** required string <= 300 characters ### Responses #### 200 A repeat of a live store (nothing written), or a dry run. Media typeapplication/json object **object** required string Allowed values: location **id** required Null on a dry run. string nullable **outcome** required string Allowed values: create repeat revive **livemode** required boolean **name** required string nullable **address** required string nullable **plan** required string Allowed values: paid free **videos\_per\_month** required integer nullable **term\_months** required Free: the free term. Paid: null, until stopped. integer nullable **price\_per\_video\_cents** required integer nullable **currency** required string Allowed values: USD **deposit** required object **cents** required The half of month one: videos\_per\_month x price\_per\_video\_cents / 2. Free: 0. integer nullable **charged** required Never charged by this call. boolean **state** required The network state; null on a dry run. string nullable **dry\_run** required boolean **account** required object **counting\_locations** required Live stores of this account after the call (a dry run - as it would be). integer **min\_locations** required integer **blockers** required Below\_minimum while counting\_locations is under min\_locations. Array ##### Example ```json { "object": "location", "id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "outcome": "create", "plan": "paid", "price_per_video_cents": 30000, "currency": "USD", "deposit": { "charged": false }, "state": "on_hold", "account": { "min_locations": 3 } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Idempotent-Replayed** string Allowed values: true True when this answer is the stored response to an earlier request with the same Idempotency-Key. #### 201 Created, or an ended store brought back (`outcome: revive`); on hold either way. Media typeapplication/json object **object** required string Allowed values: location **id** required Null on a dry run. string nullable **outcome** required string Allowed values: create repeat revive **livemode** required boolean **name** required string nullable **address** required string nullable **plan** required string Allowed values: paid free **videos\_per\_month** required integer nullable **term\_months** required Free: the free term. Paid: null, until stopped. integer nullable **price\_per\_video\_cents** required integer nullable **currency** required string Allowed values: USD **deposit** required object **cents** required The half of month one: videos\_per\_month x price\_per\_video\_cents / 2. Free: 0. integer nullable **charged** required Never charged by this call. boolean **state** required The network state; null on a dry run. string nullable **dry\_run** required boolean **account** required object **counting\_locations** required Live stores of this account after the call (a dry run - as it would be). integer **min\_locations** required integer **blockers** required Below\_minimum while counting\_locations is under min\_locations. Array ##### Example ```json { "object": "location", "id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "outcome": "create", "plan": "paid", "price_per_video_cents": 30000, "currency": "USD", "deposit": { "charged": false }, "state": "on_hold", "account": { "min_locations": 3 } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Idempotent-Replayed** string Allowed values: true True when this answer is the stored response to an earlier request with the same Idempotency-Key. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 409 Location\_already\_in\_network (another team of this account holds the place, or the same place under another name), idempotency\_conflict or idempotency\_in\_progress. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 422 Package\_not\_available (a plan other than the account’s, or a free-plan account bringing back a store that already ran its free term). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. A concurrent request wrote one of these locations; retry after `Retry-After` with the same key (it was not stored). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). Source: https://docs.creatorain.com/reference/operations/createlocation/ (markdown: https://docs.creatorain.com/reference/operations/createlocation.md) ## Add 1 to 50 locations at once, all or nothing **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). POST /locations/batch Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/locations/batch?dry_run=false'; const options = { method: 'POST', headers: { 'Idempotency-Key': 'example', Authorization: 'Bearer ', 'Content-Type': 'application/json' }, body: '{"locations":[{"name":"Sexy Crab Duluth","address":"2416 Pleasant Hill Rd, Duluth, GA 30096","google_place_id":"example","plan":"paid","videos_per_month":4,"accepted_terms":"network-2026-10","opening_hours":{},"signature_dishes":[{"name":"example"}]}]}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url 'https://api.creatorain.com/v1/locations/batch?dry_run=false' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: example' \ --data '{ "locations": [ { "name": "Sexy Crab Duluth", "address": "2416 Pleasant Hill Rd, Duluth, GA 30096", "google_place_id": "example", "plan": "paid", "videos_per_month": 4, "accepted_terms": "network-2026-10", "opening_hours": {}, "signature_dishes": [ { "name": "example" } ] } ] }' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Each location as in `POST /locations`. All or nothing: any refused item is `400 batch_invalid` with every refused item in `error.items` by index, and nothing is written; a write that fails part way writes nothing either. `201` when any store was created or brought back, `200` when every one was a repeat (or a dry run). ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Header Parameters **Idempotency-Key** required string \>= 1 characters <= 255 characters /^\[\\x21-\\x7E\]+$/ As `Idempotency-Key`, and required here (a location create). Without it the answer is `400 idempotency_key_required`. A dry run needs one too: it writes no store row; the Idempotency-Key is still stored. #### Query Parameters **dry\_run** boolean `true` validates and quotes: the same refusals as a live call, and writes no store row; the Idempotency-Key is still stored. Ids are null. ### Request Bodyrequired Media typeapplication/json object **locations** required Array \>= 1 items <= 50 items object **name** required string \>= 1 characters <= 300 characters #### Example ``` Sexy Crab Duluth ``` **address** required One of: - [string](#tab-panel-0-0) - [object](#tab-panel-0-1) string \>= 5 characters <= 400 characters #### Example ``` 2416 Pleasant Hill Rd, Duluth, GA 30096 ``` object **line1** required string <= 300 characters **city** required string <= 120 characters **state** required string <= 120 characters **postal\_code** string nullable <= 40 characters **country** string nullable <= 120 characters **google\_place\_id** string nullable <= 300 characters **plan** Absent means the account’s plan; another plan is 422 package\_not\_available. string Allowed values: paid free **videos\_per\_month** required Paid: 2 to 10. Free: exactly the free plan’s videos. Otherwise 400 videos\_per\_month\_out\_of\_range. integer #### Example ```json 4 ``` **accepted\_terms** The network terms version accepted string nullable /^\[a-z0-9\]\[a-z0-9.-\]{2,59}$/ #### Example ``` network-2026-10 ``` **opening\_hours** The store’s week object **signature\_dishes** Array <= 50 items One of: - [string](#tab-panel-1-0) - [object](#tab-panel-1-1) string <= 300 characters object **name** required string <= 300 characters ### Responses #### 200 Every location was a repeat, or a dry run. Media typeapplication/json object **object** required string Allowed values: list **dry\_run** required boolean **locations** required Array object **object** required string Allowed values: location **id** required Null on a dry run. string nullable **outcome** required string Allowed values: create repeat revive **livemode** required boolean **name** required string nullable **address** required string nullable **plan** required string Allowed values: paid free **videos\_per\_month** required integer nullable **term\_months** required Free: the free term. Paid: null, until stopped. integer nullable **price\_per\_video\_cents** required integer nullable **currency** required string Allowed values: USD **deposit** required object **cents** required The half of month one: videos\_per\_month x price\_per\_video\_cents / 2. Free: 0. integer nullable **charged** required Never charged by this call. boolean **state** required The network state; null on a dry run. string nullable **dry\_run** required boolean **deposit\_total\_cents** required integer **account** required object **counting\_locations** required Live stores of this account after the call (a dry run - as it would be). integer **min\_locations** required integer **blockers** required Below\_minimum while counting\_locations is under min\_locations. Array ##### Example ```json { "object": "list", "locations": [ { "object": "location", "id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "outcome": "create", "plan": "paid", "price_per_video_cents": 30000, "currency": "USD", "deposit": { "charged": false }, "state": "on_hold" } ], "account": { "min_locations": 3 } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Idempotent-Replayed** string Allowed values: true True when this answer is the stored response to an earlier request with the same Idempotency-Key. #### 201 At least one location was created or brought back. Media typeapplication/json object **object** required string Allowed values: list **dry\_run** required boolean **locations** required Array object **object** required string Allowed values: location **id** required Null on a dry run. string nullable **outcome** required string Allowed values: create repeat revive **livemode** required boolean **name** required string nullable **address** required string nullable **plan** required string Allowed values: paid free **videos\_per\_month** required integer nullable **term\_months** required Free: the free term. Paid: null, until stopped. integer nullable **price\_per\_video\_cents** required integer nullable **currency** required string Allowed values: USD **deposit** required object **cents** required The half of month one: videos\_per\_month x price\_per\_video\_cents / 2. Free: 0. integer nullable **charged** required Never charged by this call. boolean **state** required The network state; null on a dry run. string nullable **dry\_run** required boolean **deposit\_total\_cents** required integer **account** required object **counting\_locations** required Live stores of this account after the call (a dry run - as it would be). integer **min\_locations** required integer **blockers** required Below\_minimum while counting\_locations is under min\_locations. Array ##### Example ```json { "object": "list", "locations": [ { "object": "location", "id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "outcome": "create", "plan": "paid", "price_per_video_cents": 30000, "currency": "USD", "deposit": { "charged": false }, "state": "on_hold" } ], "account": { "min_locations": 3 } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Idempotent-Replayed** string Allowed values: true True when this answer is the stored response to an earlier request with the same Idempotency-Key. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 409 Location\_already\_in\_network (another team of this account holds the place, or the same place under another name), idempotency\_conflict or idempotency\_in\_progress. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 422 Package\_not\_available (a plan other than the account’s, or a free-plan account bringing back a store that already ran its free term). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. A concurrent request wrote one of these locations; retry after `Retry-After` with the same key (it was not stored). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). Source: https://docs.creatorain.com/reference/operations/createlocationsbatch/ (markdown: https://docs.creatorain.com/reference/operations/createlocationsbatch.md) ## Open an onboarding session (no key) **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). POST /onboarding\_sessions Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/onboarding_sessions'; const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"client_name":"example","requested_scopes":["read"],"requested_livemode":true}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://api.creatorain.com/v1/onboarding_sessions \ --header 'Content-Type: application/json' \ --data '{ "client_name": "example", "requested_scopes": [ "read" ], "requested_livemode": true }' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) No API key: this is how an agent without one starts. Show the human `user_code` and `url`. `session_secret` is returned ONCE and is the only way to poll; store it like a key. The requested scopes and mode are a request only: the approving human decides. 5 sessions an hour per address, and a global per-minute ceiling, then `429 rate_limited` with `Retry-After`. ### Request Body Media typeapplication/json object **client\_name** Shown to the human as an unverified name. string nullable <= 100 characters **requested\_scopes** Array nullable Allowed values: read samples:read locations:write balance:write creators:read webhooks:write **requested\_livemode** boolean nullable ### Responses #### 201 The session. Poll it every `interval` seconds until it is approved, denied or expired. Media typeapplication/json object **id** required string **object** required string Allowed values: onboarding\_session **status** required string Allowed values: pending **url** required string format: uri **user\_code** required Eight letters; the human types it in the app. string **session\_secret** required Shown once. The only way to poll this session. string **expires\_at** required 15 minutes after creation. string format: date-time **interval** required Seconds between polls. integer ##### Example ```json { "id": "obs_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "object": "onboarding_session", "status": "pending", "url": "https://app.creatorain.com/settings/api/connect?code=BCDF-GHJK", "user_code": "BCDF-GHJK", "session_secret": "crp_obs_...", "interval": 5 } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Cache-Control** string Allowed values: no-store No-store. The answer may carry a secret. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/createonboardingsession/ (markdown: https://docs.creatorain.com/reference/operations/createonboardingsession.md) ## The account this key acts for **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /account Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/account'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://api.creatorain.com/v1/account \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `read`. `blockers` is empty and `next_action` is null until the issues that own each account state ship. `counting_locations` counts the live stores of this workspace only. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Responses #### 200 The account. Media typeapplication/json object **id** required string **name** required string **livemode** required boolean **status** required string Allowed values: awaiting\_payment active past\_due paused stopped **counting\_locations** required integer **min\_locations** required integer **max\_locations** required integer **blockers** required Array **next\_action** required object **created\_at** required string format: date-time ##### Example ```json { "id": "acct_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "status": "awaiting_payment", "min_locations": 3, "max_locations": 50 } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **RateLimit-Limit** integer ###### Example ```json 600 ``` Requests allowed in the current minute for this workspace (600). **RateLimit-Remaining** integer Requests left in the current minute for this workspace. **RateLimit-Reset** integer Seconds until the current window resets. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 404 Not\_found. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/getaccount/ (markdown: https://docs.creatorain.com/reference/operations/getaccount.md) ## What a month costs, as a preview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /bill/preview Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/bill/preview?month=2026-11'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://api.creatorain.com/v1/bill/preview?month=2026-11' \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `read`. Read only: nothing is charged (`charged: false`). The month’s bill as the app shows it, one line per location counted on each store’s own clock, in cents; a comped account reads 0 throughout. `total_cents` is null when a line has no locked price yet. `deposit` is the half of month one Checkout would ask today, for the stores that joined in the app and still await payment (stores added through this API are not in it). Over 2000 locations the answer is `503 service_unavailable` rather than a short bill. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Query Parameters **month** string /^\\d{4}-(0\[1-9\]|1\[0-2\])$/ ##### Example ``` 2026-11 ``` YYYY-MM. Defaults to the current UTC month. ### Responses #### 200 The preview. Media typeapplication/json A preview. Never charged. Over 2000 locations the route answers 503 instead of a short bill. object **object** required string Allowed values: bill\_preview **livemode** required boolean **month** required string **currency** required string Allowed values: USD **preview** required boolean **charged** required boolean **comped** required boolean **lines** required Array object **location\_id** required string **name** required string nullable **status** required string Allowed values: active paused terminated **plan\_videos\_per\_month** required integer nullable **visits\_completed** required integer **no\_shows** required integer **videos\_published** required integer **makeup\_videos** required integer **billed\_videos** required Excludes free-plan videos (TASK-2916): they are counted, never billed. integer **amount\_cents** required Null when the location has no locked price; 0 when comped. integer nullable **total\_cents** required Null when any line is null. integer nullable **deposit** required object **cents** required The half of month one Checkout would ask today. integer **location\_ids** required Array **charged** required boolean **generated\_at** required string format: date-time ##### Example ```json { "object": "bill_preview", "month": "2026-11", "currency": "USD", "preview": true, "charged": false, "lines": [ { "status": "active" } ], "deposit": { "charged": false } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **RateLimit-Limit** integer ###### Example ```json 600 ``` Requests allowed in the current minute for this workspace (600). **RateLimit-Remaining** integer Requests left in the current minute for this workspace. **RateLimit-Reset** integer Seconds until the current window resets. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. The read is unavailable right now (for the bill preview, an account over 2000 locations). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/getbillpreview/ (markdown: https://docs.creatorain.com/reference/operations/getbillpreview.md) ## One location, with this month's pace **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /locations/{id} Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/locations/loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://api.creatorain.com/v1/locations/loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `read`. The location as in the list, plus `month`: this store-local month’s planned videos, the visits booked and done, and the videos posted (stated at the store, the ones the bill counts). `month` is null when it cannot be counted. A malformed id, an unknown one and another account’s location are the same `404 not_found`. No query parameters. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Path Parameters **id** required string /^loc\_\[0-9a-f\]{32}$/ ##### Example ``` loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e ``` ### Responses #### 200 The location. Media typeapplication/json object **object** required string Allowed values: location **id** required string **livemode** required boolean **name** required string nullable **address** required string nullable **plan** required string Allowed values: paid free **videos\_per\_month** required integer nullable **term\_months** required integer nullable **price\_per\_video\_cents** required integer nullable **currency** required string Allowed values: USD **deposit** required object **cents** required The quote at create (half of month one; free 0). Not what is due now. integer nullable **charged** required boolean **state** required The network state the app’s Network page shows. string Allowed values: payment\_failed ended paused needs\_hours on\_hold awaiting\_payment full\_this\_month accepting **status** required string Allowed values: active paused ended **held** required Held by the API hold until CreatoRain releases it to recruiting. boolean **accepting** required True exactly when state is accepting. boolean **term\_ends\_on** required string format: date nullable **created\_at** required RFC 3339, UTC. string format: date-time **month** required object **month** required The store-local month. string **planned** required Videos a month in force this month. integer nullable **allowance** required integer nullable **booked** required Visits this month that are booked or done. integer **visited** required Visits this month that happened. integer **posted** required Videos stated at this location that went live this month. integer **full** required Held back until next month by the pacing. boolean **full\_until** required string format: date-time nullable ##### Example ```json { "object": "location", "id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "plan": "paid", "currency": "USD", "deposit": { "charged": false }, "state": "payment_failed", "status": "active", "month": { "month": "2026-11" } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **RateLimit-Limit** integer ###### Example ```json 600 ``` Requests allowed in the current minute for this workspace (600). **RateLimit-Remaining** integer Requests left in the current minute for this workspace. **RateLimit-Reset** integer Seconds until the current window resets. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 404 Not\_found. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. The read is unavailable right now (for the bill preview, an account over 2000 locations). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/getlocation/ (markdown: https://docs.creatorain.com/reference/operations/getlocation.md) ## Poll an onboarding session (session secret, no key) **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /onboarding\_sessions/{id} Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/onboarding_sessions/obs_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://api.creatorain.com/v1/onboarding_sessions/obs_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) `Authorization: Bearer `. The first poll after the human approves carries `key.secret`; no later poll does (`key_delivered: true`, `next_action: create_new_session` if it was lost). Polling sooner than `interval` is `429 slow_down`: the interval grows by 5 seconds, up to 60, and `Retry-After` carries it. A wrong secret and an unknown id are the same `404`; failures count toward the address block like bad keys. ### Authorizations - **[sessionSecret](https://docs.creatorain.com/reference/#sessionsecret)** ### Parameters #### Path Parameters **id** required string ##### Example ``` obs_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e ``` ### Responses #### 200 The session. Media typeapplication/json object **id** required string **object** required string Allowed values: onboarding\_session **status** required string Allowed values: pending approved denied expired **expires\_at** required string format: date-time **interval** required integer **key\_delivered** required boolean **key** required object **id** required string **secret** On the first poll after approval only. string **prefix** required string **last4** required string nullable **livemode** required boolean **scopes** required Array **next\_action** required {type: human\_approval, url} while pending; {type: create\_new\_session} once expired or collected. object **type** string Allowed values: human\_approval create\_new\_session **url** string format: uri **blockers** required Why the approval cannot produce a key yet (for example live\_key\_requires\_top\_up, key\_limit\_reached, owner\_changed). Array ##### Example ```json { "object": "onboarding_session", "status": "pending", "key": { "id": "key_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "prefix": "crp_test_AbCd" }, "next_action": { "type": "human_approval" } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Cache-Control** string Allowed values: no-store No-store. The answer may carry a secret. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 404 Not\_found. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/getonboardingsession/ (markdown: https://docs.creatorain.com/reference/operations/getonboardingsession.md) ## This account's locations, oldest first **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /locations Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/locations?limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://api.creatorain.com/v1/locations?limit=50' \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `read`. Every store of this account on the CreatoRain Network, each with the state the app’s Network page shows (`state`), its plan and videos a month, and whether it is held (`held`, the API hold until CreatoRain releases it) or accepting creators (`accepting`). The same `loc_` id `POST /locations` returned. `deposit` is the quote at create; what Checkout would ask today is `GET /bill/preview`’s `deposit`. `account` is as on the create; `network` says whether the network takes bookings at all. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Query Parameters **cursor** string <= 512 characters The `next_cursor` of the previous page, unchanged. Omit it for the first page. Anything else is `400 parameter_invalid` (field `cursor`). **limit** integer default: 50 \>= 1 <= 200 Items a page, 1 to 200. ### Responses #### 200 One page of locations. Media typeapplication/json object **object** required string Allowed values: list **data** required Array A location as the reads answer it. The fields it shares with LocationItem carry the same names and meanings. object **object** required string Allowed values: location **id** required string **livemode** required boolean **name** required string nullable **address** required string nullable **plan** required string Allowed values: paid free **videos\_per\_month** required integer nullable **term\_months** required integer nullable **price\_per\_video\_cents** required integer nullable **currency** required string Allowed values: USD **deposit** required object **cents** required The quote at create (half of month one; free 0). Not what is due now. integer nullable **charged** required boolean **state** required The network state the app’s Network page shows. string Allowed values: payment\_failed ended paused needs\_hours on\_hold awaiting\_payment full\_this\_month accepting **status** required string Allowed values: active paused ended **held** required Held by the API hold until CreatoRain releases it to recruiting. boolean **accepting** required True exactly when state is accepting. boolean **term\_ends\_on** required string format: date nullable **created\_at** required RFC 3339, UTC. string format: date-time **next\_cursor** required string nullable **account** required object **counting\_locations** required Live stores of this account after the call (a dry run - as it would be). integer **min\_locations** required integer **blockers** required Below\_minimum while counting\_locations is under min\_locations. Array **network** required object **accepting** required The network takes bookings now. boolean **join\_enabled** required boolean **comped** required The account is on the free plan. boolean **renew\_to\_free** required boolean nullable ##### Example ```json { "object": "list", "data": [ { "object": "location", "id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "plan": "paid", "currency": "USD", "deposit": { "charged": false }, "state": "payment_failed", "status": "active" } ], "account": { "min_locations": 3 } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **RateLimit-Limit** integer ###### Example ```json 600 ``` Requests allowed in the current minute for this workspace (600). **RateLimit-Remaining** integer Requests left in the current minute for this workspace. **RateLimit-Reset** integer Seconds until the current window resets. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 404 Not\_found. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. The read is unavailable right now (for the bill preview, an account over 2000 locations). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/listlocations/ (markdown: https://docs.creatorain.com/reference/operations/listlocations.md) ## The videos posted from this account's locations, newest first **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /videos Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/videos?limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://api.creatorain.com/v1/videos?limit=50' \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `read`. Live videos only. A video is this account’s when it is stated at one of its locations, or, stated at none, linked to a visit at one, or its creator was booked at one. `counted_on_bill` is true only for a video stated at its location: those are what the month’s pace and the bill count, so the list can hold videos not counted on the bill. `stats` is null until the public post was first read. Creators appear by public handle only. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Query Parameters **location** string /^loc\_\[0-9a-f\]{32}$/ Only this location’s items. Another account’s location is `404 not_found` (field `location`). **cursor** string <= 512 characters The `next_cursor` of the previous page, unchanged. Omit it for the first page. Anything else is `400 parameter_invalid` (field `cursor`). **limit** integer default: 50 \>= 1 <= 200 Items a page, 1 to 200. ### Responses #### 200 One page of videos. Media typeapplication/json object **object** required string Allowed values: list **data** required Array object **object** required string Allowed values: video **id** required string **livemode** required boolean **location\_id** required string **visit\_id** required The visit this video is linked to, at the same location; else null. string nullable **platform** required string nullable **url** required string format: uri nullable **published\_at** required On the store’s offset. string format: date-time nullable **timezone** required string nullable **status** required string Allowed values: live **counted\_on\_bill** required Stated at its location, so counted by the month’s pace and the bill. A linked or booked-creator video is listed with false. boolean **creator** required object **handle** required string nullable **is\_collab** required The store’s account is a co-author of the public post. boolean **stats** required Null until the public post was first read. object **views** required integer nullable **likes** required integer nullable **comments** required integer nullable **measured\_at** required object **views** required string format: date-time nullable **likes** required string format: date-time nullable **comments** required string format: date-time nullable **next\_cursor** required string nullable ##### Example ```json { "object": "list", "data": [ { "object": "video", "id": "vid_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "platform": "tiktok", "status": "live" } ] } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **RateLimit-Limit** integer ###### Example ```json 600 ``` Requests allowed in the current minute for this workspace (600). **RateLimit-Remaining** integer Requests left in the current minute for this workspace. **RateLimit-Reset** integer Seconds until the current window resets. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 404 Not\_found. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. The read is unavailable right now (for the bill preview, an account over 2000 locations). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/listvideos/ (markdown: https://docs.creatorain.com/reference/operations/listvideos.md) ## The creator visits at this account's locations, newest update first **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). GET /visits Select code sampleFetchcURL ```js const url = 'https://api.creatorain.com/v1/visits?status=booked&limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://api.creatorain.com/v1/visits?status=booked&limit=50' \ --header 'Authorization: Bearer ' ``` - Live (crp\_live\_ keys) - Sandbox (crp\_test\_ keys) Scope `read`. CreatoRain Network visits only: a store’s bookings on another campaign of its own are not listed, and neither are bookings not yet confirmed or declined. `?location=` of another account is `404 not_found` (field `location`). Visits page by their last update, so dedupe on `id` across a walk. ### Authorizations - **[bearerAuth](https://docs.creatorain.com/reference/#bearerauth)** ### Parameters #### Query Parameters **location** string /^loc\_\[0-9a-f\]{32}$/ Only this location’s items. Another account’s location is `404 not_found` (field `location`). **status** string Allowed values: booked completed no\_show cancelled **from** string format: date The first visit day, YYYY-MM-DD, in the store’s own calendar. **to** string format: date The last visit day, YYYY-MM-DD, inclusive. **cursor** string <= 512 characters The `next_cursor` of the previous page, unchanged. Omit it for the first page. Anything else is `400 parameter_invalid` (field `cursor`). **limit** integer default: 50 \>= 1 <= 200 Items a page, 1 to 200. ### Responses #### 200 One page of visits. Media typeapplication/json object **object** required string Allowed values: list **data** required Array Times are RFC 3339 on the STORE’s offset (the restaurant’s wall clock), unlike a location’s created\_at. object **object** required string Allowed values: visit **id** required string **livemode** required boolean **location\_id** required string **status** required string Allowed values: booked completed no\_show cancelled **arrive\_at** required string format: date-time nullable **timezone** required string nullable **party\_size** required integer **dish** required string nullable **creator** required object **handle** required The creator’s public handle. string nullable **followers** required integer nullable **platforms** required Array **acknowledged\_at** required When someone at the store first confirmed seeing it. string format: date-time nullable **acknowledged\_kind** required string nullable **created\_at** required string format: date-time nullable **updated\_at** required string format: date-time nullable **next\_cursor** required string nullable ##### Example ```json { "object": "list", "data": [ { "object": "visit", "id": "vis_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "location_id": "loc_3f2a9c1e5b7d4a6f8e0c2b4d6f8a0c2e", "status": "booked" } ] } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **RateLimit-Limit** integer ###### Example ```json 600 ``` Requests allowed in the current minute for this workspace (600). **RateLimit-Remaining** integer Requests left in the current minute for this workspace. **RateLimit-Reset** integer Seconds until the current window resets. #### 400 Parameter\_invalid (with `field`) or invalid\_json. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 401 Invalid\_key, test\_key\_on\_live or live\_key\_on\_sandbox. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 403 Scope\_missing or forbidden\_ip. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 404 Not\_found. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 429 Rate\_limited (600 a minute per workspace, an onboarding create limit, or an address blocked after failed authentication), or slow\_down (an onboarding session polled too fast). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. **Retry-After** integer \>= 1 Seconds to wait before retrying (at least 1). #### 500 Internal\_error (500) or service\_unavailable (503). The message never carries a cause. Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. #### 503 Service\_unavailable. The read is unavailable right now (for the bill preview, an account over 2000 locations). Media typeapplication/json object **error** required object **type** required string Allowed values: invalid\_request\_error authentication\_error permission\_error idempotency\_error rate\_limit\_error api\_error **code** required string Allowed values: parameter\_invalid invalid\_json idempotency\_key\_invalid idempotency\_key\_required customization\_not\_supported videos\_per\_month\_out\_of\_range batch\_invalid terms\_not\_accepted invalid\_key test\_key\_on\_live live\_key\_on\_sandbox insufficient\_balance scope\_missing forbidden\_ip forbidden live\_key\_requires\_top\_up limit\_raise\_requires\_dashboard not\_found idempotency\_conflict idempotency\_in\_progress conflict location\_already\_in\_network external\_id\_conflict dispute\_open request\_too\_large address\_not\_verified not\_food\_business metro\_not\_served package\_not\_available account\_location\_limit commit\_limit\_exceeded top\_up\_exceeds\_feasible no\_saved\_card rate\_limited quota\_exceeded slow\_down internal\_error service\_unavailable **message** required string **field** The request field at fault string **doc\_url** required string format: uri **request\_id** required string format: uuid **items** Batch\_invalid only. Every refused location, by its index in the request. Array object **index** required integer **code** required One of the error codes above. string **field** string **message** required string ##### Example ```json { "error": { "type": "invalid_request_error", "code": "parameter_invalid", "doc_url": "https://www.creatorain.com/api/errors#scope_missing", "items": [ { "field": "locations.1.videos_per_month" } ] } } ``` ##### Headers **Request-Id** string format: uuid This request’s id. Equal to error.request\_id; quote it to support. Source: https://docs.creatorain.com/reference/operations/listvisits/ (markdown: https://docs.creatorain.com/reference/operations/listvisits.md) ## Overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### Account The workspace this key acts for. ### Operations GET [/account](https://docs.creatorain.com/reference/operations/getaccount/) Source: https://docs.creatorain.com/reference/operations/tags/account/ (markdown: https://docs.creatorain.com/reference/operations/tags/account.md) ## Overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### Billing What this month will cost, as a preview. Nothing here charges. ### Operations GET [/bill/preview](https://docs.creatorain.com/reference/operations/getbillpreview/) Source: https://docs.creatorain.com/reference/operations/tags/billing/ (markdown: https://docs.creatorain.com/reference/operations/tags/billing.md) ## Overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### Locations Add stores to the CreatoRain Network, one or many, or ask first what a call would write and cost (dry\_run). Read them back with their network state and this month’s pace. ### Operations GET [/locations](https://docs.creatorain.com/reference/operations/listlocations/) POST [/locations](https://docs.creatorain.com/reference/operations/createlocation/) POST [/locations/batch](https://docs.creatorain.com/reference/operations/createlocationsbatch/) GET [/locations/{id}](https://docs.creatorain.com/reference/operations/getlocation/) Source: https://docs.creatorain.com/reference/operations/tags/locations/ (markdown: https://docs.creatorain.com/reference/operations/tags/locations.md) ## Overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### Onboarding How an AI agent with no key gets one (RFC 8628 style). The agent opens a session and shows its human the `user_code` and `url`; the workspace owner signs in to the app, enters the code and approves, choosing the mode and scopes themselves; the agent polls and collects the key once. ### Operations POST [/onboarding\_sessions](https://docs.creatorain.com/reference/operations/createonboardingsession/) GET [/onboarding\_sessions/{id}](https://docs.creatorain.com/reference/operations/getonboardingsession/) Source: https://docs.creatorain.com/reference/operations/tags/onboarding/ (markdown: https://docs.creatorain.com/reference/operations/tags/onboarding.md) ## Overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### Videos The videos creators posted from this account’s stores, with their public numbers. ### Operations GET [/videos](https://docs.creatorain.com/reference/operations/listvideos/) Source: https://docs.creatorain.com/reference/operations/tags/videos/ (markdown: https://docs.creatorain.com/reference/operations/tags/videos.md) ## Overview **Not live yet:** the v1 API and its hosts are not open. See [Sandbox](https://docs.creatorain.com/get-started/sandbox/). ### Visits The creator visits booked at this account’s stores. ### Operations GET [/visits](https://docs.creatorain.com/reference/operations/listvisits/) Source: https://docs.creatorain.com/reference/operations/tags/visits/ (markdown: https://docs.creatorain.com/reference/operations/tags/visits.md) ## Partner API reference overview ### CreatoRain Partner API 1.0.0 The surface an outside system (a POS or ordering platform) uses to enrol its merchants’ stores with CreatoRain, and later to read those stores’ reservations and published content. ### Authentication One long-lived API key per partner, sent as `Authorization: Bearer `. Keys look like `crp_live_...` on production and `crp_test_...` everywhere else; the tag is a label for humans and is not what grants access. A key may also carry an IP allowlist, in which case a request from any other address is refused with `403 forbidden_ip`. A key is scoped to ONE account and ONE campaign. It cannot read another customer’s data, and it is not an administrative credential. THE HEADER IS `Authorization`, on every route and for both credentials. There is no `x-api-key` header on this API and a key sent in one is not read, so a request carrying only that answers `401 unauthorized`. Said plainly because it is the wrong guess an integrator makes once and then spends an afternoon on: the refusal looks identical to a bad key. ### Errors Every failing response carries the same envelope, with a stable machine-readable `code`: ``` { "error": { "code": "location_already_exists", "message": "...", "field": "partner_location_id" } } ``` Branch on `code`, never on `message`. `field` is present when one request field is at fault. ### Rate limit 600 requests per minute per key by default, over a 60 second window. Over the ceiling the answer is `429` with `code: rate_limited` and the standard `RateLimit-*` headers. ### Time Every time value is RFC 3339 with the STORE’S offset (`2026-09-11T15:00:00-07:00`), and the object carries a sibling `timezone` field holding the IANA name (`America/Los_Angeles`). Stores span time zones, so a UTC-only value renders “3 pm today” wrongly in a merchant UI. ### Monthly pacing A store’s plan is paced by the month. Months are calendar months on the STORE’S clock, and a season is three of them, counted from the month that holds the season start (the store-local day of `approved_at`). In each month a store is offered to creators until the season’s slots booked or in flight reach `videos_per_month` for each month of the season so far (so a month that booked fewer than its share leaves the rest to the next month of the same season), never more than the season total. Then the store is not offered again until the 1st of the next month, store time. Nothing carries across a season boundary. A `plan` change by PATCH applies from the 1st of the next month. The whole-term total (`videos_per_month` x `term_months`) still applies on top. ### Deprecations `quarter_target` is renamed `season_target` (videos per season: `videos_per_month` x 3) in `GET /locations/{id}` `progress` and in the `location.activated` webhook. On the `location.quarter_summary` webhook the target is sent as `season_target`, and the old `target` field carries the same value. For ONE release both names are sent with the same value; read `season_target`. Before this release `quarter_target` and `target` held the whole-term total. Information - OpenAPI version: `3.0.3` ### Operations POST [/locations](https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocation/) PATCH [/locations/{partner\_location\_id}](https://docs.creatorain.com/partner-api/reference/operations/patchpartnerlocation/) POST [/locations/{partner\_location\_id}/pause](https://docs.creatorain.com/partner-api/reference/operations/pausepartnerlocation/) POST [/locations/{partner\_location\_id}/resume](https://docs.creatorain.com/partner-api/reference/operations/resumepartnerlocation/) POST [/locations/{partner\_location\_id}/terminate](https://docs.creatorain.com/partner-api/reference/operations/terminatepartnerlocation/) POST [/locations/{partner\_location\_id}/creator-samples/{batch\_id}/decision](https://docs.creatorain.com/partner-api/reference/operations/decidepartnercreatorsamples/) GET [/locations/{partner\_location\_id}](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocation/) POST [/locations/{partner\_location\_id}/dashboard-token](https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocationdashboardtoken/) GET [/locations/{partner\_location\_id}/reservations](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationreservations/) GET [/locations/{partner\_location\_id}/content](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcontent/) GET [/locations/{partner\_location\_id}/creators](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcreators/) GET [/locations/{partner\_location\_id}/creator-samples](https://docs.creatorain.com/partner-api/reference/operations/getpartnercreatorsamples/) GET [/reservations](https://docs.creatorain.com/partner-api/reference/operations/getpartnerreservations/) GET [/summary](https://docs.creatorain.com/partner-api/reference/operations/getpartnersummary/) POST [/reservations/{reservation\_id}/acknowledge](https://docs.creatorain.com/partner-api/reference/operations/acknowledgepartnerreservation/) GET [/billing/monthly](https://docs.creatorain.com/partner-api/reference/operations/getpartnermonthlybilling/) GET [/pricing/quote](https://docs.creatorain.com/partner-api/reference/operations/getpartnerpricingquote/) GET [/settings](https://docs.creatorain.com/partner-api/reference/operations/getpartnersettings/) PUT [/settings](https://docs.creatorain.com/partner-api/reference/operations/putpartnersettings/) ### Authentication #### partnerApiKey The partner API key, issued out of band. `Authorization: Bearer crp_live_...`. Not a JWT: it is an opaque credential and carries no claims. **Security scheme type:** http #### storeTokenHeader A PER-STORE, 30 minute, READ-ONLY token from `POST /locations/{partner_location_id}/dashboard-token`, sent as `Authorization: Bearer `. Accepted by the three `GET /locations/{partner_location_id}...` routes and NOWHERE ELSE. Presented anywhere else, or for any other store, it answers `401 unauthorized`. This is what lets a merchant’s browser read their own store without ever holding your master key. **Security scheme type:** http #### storeTokenQuery The same per-store token in the query string, because an embedded iframe cannot set a header. When both are present the query string wins, since that is the URL the page was loaded with. **Security scheme type:** apiKey **Query parameter name:** token Source: https://docs.creatorain.com/partner-api/reference/ (markdown: https://docs.creatorain.com/partner-api/reference.md) ## The merchant saw this booking POST /reservations/{reservation\_id}/acknowledge Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/reservations/7f1c2b64-6f6a-4a7d-9a0e-1c2b647f1c2b/acknowledge'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"kind":"forwarded_to_manager"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/reservations/7f1c2b64-6f6a-4a7d-9a0e-1c2b647f1c2b/acknowledge \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "kind": "forwarded_to_manager" }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Called when the merchant presses confirm in YOUR UI. Tell us which action it was: `forwarded_to_manager` (they passed it to whoever is on the floor) or `acknowledged_self` (they dealt with it themselves). This is the one thing in the whole chain we cannot see. We know the notice went out, we know the creator confirmed, and we find out afterwards whether anybody arrived. Whether a person at the restaurant actually read it is yours to tell us, and it is the link that turns out to have been broken when a visit goes wrong. IDEMPOTENT PER `(reservation_id, kind)`. A retry answers `200` with the instant we ALREADY HOLD, never a new one: that instant is when the merchant pressed the button, and a lost response must not be able to move it. The two kinds are independent, so a booking that was forwarded AND acknowledged carries both, each with its own time. PARTNER KEY ONLY. A per-store dashboard token cannot write here, which is the reason it stays a browser-safe credential: send the acknowledgement from your own backend. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **reservation\_id** required string format: uuid OUR id for the booking, as it reached you in a `reservation.*` webhook or in a reservations list. A uuid: anything else is refused with `400 validation_error` naming `reservation_id`, which tells you to look at your code rather than at your data. ##### Example ``` 7f1c2b64-6f6a-4a7d-9a0e-1c2b647f1c2b ``` ### Request Bodyrequired Media typeapplication/json What the merchant did. Two values and no third: this is the whole product question, and a value we accepted but had no meaning for would leave both sides believing something had been recorded. object **kind** required `forwarded_to_manager`: they passed the booking to whoever is on the floor. `acknowledged_self`: they dealt with it themselves. string Allowed values: forwarded\_to\_manager acknowledged\_self #### Examples Exampleforwarded Passed to the manager on duty ```json { "kind": "forwarded_to_manager" } ``` ### Responses #### 200 Recorded. The same body on the first call and on every repeat. Media typeapplication/json What we now hold. On a repeat this is the FIRST acknowledgement’s time, not the retry’s. No personal data: an acknowledgement says a booking was seen, not who is coming. object **reservation\_id** required string format: uuid **kind** required string Allowed values: forwarded\_to\_manager acknowledged\_self **acknowledged\_at** required RFC 3339 with the STORE’S offset, because “the manager saw this at 4 pm” only means anything at the restaurant. string nullable **timezone** required string nullable ##### Example ```json { "kind": "forwarded_to_manager", "acknowledged_at": "2026-09-11T16:04:12-07:00", "timezone": "America/Los_Angeles" } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `reservation_not_found`. No store enrolled under this key holds that booking. One answer whether the booking belongs to another partner, to another account, or to nobody: a caller who could tell those apart could count our bookings by walking ids. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/acknowledgepartnerreservation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/acknowledgepartnerreservation.md) ## Enrol a store POST /locations Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"partner_location_id":"store_123","name":"Example Noodle House","address":{"line1":"100 Main St","city":"San Jose","state":"CA","postal_code":"95113","country":"US"},"plan":{"videos_per_month":2,"term_months":3},"signature_dishes":[{"name":"Signature tempura platter","image_url":"https://cdn.example.com/tempura.jpg"}],"preferred_language":"zh","approved_at":"2026-09-09T18:22:00Z","approved_by":"ops@example.com","approval_mode":"auto","timezone":"America/Los_Angeles","opening_hours":{"mon":[["11:00","15:00"],["17:00","21:30"]],"tue":[["11:00","21:30"]],"wed":[["11:00","21:30"]],"thu":[["11:00","21:30"]],"fri":[["11:00","22:00"]],"sat":[["11:00","22:00"]],"sun":[["11:00","21:00"]]},"merchant_contact":{"name":"Alex Kim","phone":"+14155550100","email":"owner@example.com"}}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/locations \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "partner_location_id": "store_123", "name": "Example Noodle House", "address": { "line1": "100 Main St", "city": "San Jose", "state": "CA", "postal_code": "95113", "country": "US" }, "plan": { "videos_per_month": 2, "term_months": 3 }, "signature_dishes": [ { "name": "Signature tempura platter", "image_url": "https://cdn.example.com/tempura.jpg" } ], "preferred_language": "zh", "approved_at": "2026-09-09T18:22:00Z", "approved_by": "ops@example.com", "approval_mode": "auto", "timezone": "America/Los_Angeles", "opening_hours": { "mon": [ [ "11:00", "15:00" ], [ "17:00", "21:30" ] ], "tue": [ [ "11:00", "21:30" ] ], "wed": [ [ "11:00", "21:30" ] ], "thu": [ [ "11:00", "21:30" ] ], "fri": [ [ "11:00", "22:00" ] ], "sat": [ [ "11:00", "22:00" ] ], "sun": [ [ "11:00", "21:00" ] ] }, "merchant_contact": { "name": "Alex Kim", "phone": "+14155550100", "email": "owner@example.com" } }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Called once when a merchant approves joining. `partner_location_id` is YOUR id for the store and is the idempotency key, so a retry is safe: State when the call arrives Answer No store with this `partner_location_id` `201` and the store is created It exists with the same name and address `200` with the same body plus a `warning` It exists with a different name or address `409 location_already_exists` It exists and its contract was terminated `201`, the store is re-activated A repeat of a store that is still live is never an error for an identical body: it answers `200` with the same body and a top-level `warning` object, `{"code": "location_already_exists", "message": "This location already exists"}`, so your system can tell a repeat from a first create. Nothing is written. A different name or address for a live store is `409` with the same `code` and `message`. A store whose contract was terminated is added again directly with the same call: it is re-activated (the same store and history, not a second one), it gets a NEW price lock from the plan you send, it is offered to creators again, and `location.activated` is sent again. There is no warning. Its hours and timezone are kept (change them with PATCH). A changed `partner_location_id` is a DIFFERENT store, so the id must be stable in your system. Use `PATCH /locations/{partner_location_id}` to change a store’s name, address or plan; a create with changed details is refused rather than silently applied. ### Store facts worth sending - **`timezone`**: the store’s IANA zone. When sent it wins over the zone we derive from the address state, which is an hour off in states with two zones (El Paso, the Florida panhandle). Every time we give you for the store, every reminder and the visit-day text use it. - **`opening_hours`**: the week from your POS. When sent we use it and do not look the store up; `hours.source` reads `partner`, and the store is never held for missing hours. When not sent we look the hours up ourselves as before. - **`merchant_contact`**: who at the restaurant hears from us. Its email receives our store notices instead of your account owner, and its phone receives the visit-day text. - **`approval_mode`**: `auto` (default) or `sample_review`. A repeat of a create (same id, name and address) is `200` and writes nothing, whatever extra fields it carries. To change any of these on an existing store, use `PATCH`. ### What a new store starts with, without you sending it - **Creator bookings are AUTO-CONFIRMED.** A creator who books a slot at your store has a confirmed visit immediately; there is no approval step waiting on somebody at the restaurant, and per-booking review is a later product. Your merchant hears about the booking through the notice we send and, if you have wired it, through the `reservation.confirmed` webhook. - **A creator visit window inside the store’s opening hours**, with our house rules on top: no Saturday visits, Friday visits end at 17:00, Sunday visits start at 15:00. A break in the day (an afternoon closure) is kept, so no creator is offered a time when the door is shut. An operator can change the window per store afterwards. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Request Bodyrequired Media typeapplication/json Deliberately small. Social accounts, cuisine, blackout dates and daily visit caps are NOT accepted: every extra field slows onboarding and is one more thing to get wrong, and we fill those ourselves. `timezone`, `opening_hours` and `merchant_contact` are optional but worth sending: they remove the three most common reasons a store waits or a notice is missed. An unrecognised field is refused rather than ignored, so a value can never be silently dropped. object **partner\_location\_id** required Your id for the store. The idempotency key, and the store’s identity. Must be stable. string <= 200 characters **name** required string <= 300 characters **address** 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 **line1** string nullable <= 300 characters **city** string nullable <= 120 characters **state** string nullable <= 120 characters **postal\_code** string nullable <= 40 characters **country** string nullable <= 120 characters **plan** 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 **videos\_per\_month** 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). integer \>= 1 <= 10 **term\_months** 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. integer \>= 1 <= 120 **signature\_dishes** Array <= 50 items object **name** required string <= 300 characters **image\_url** An http(s) link to the dish photo. Stored with the dish. string format: uri nullable <= 2000 characters **preferred\_language** The language the MERCHANT is addressed in. Omit when you do not know; it is not defaulted to en. string Allowed values: zh en **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **timezone** The store’s IANA time zone, `Area/Location` (for example `America/Los_Angeles`). When set it wins over the zone we derive from the address. Fixed offsets (`+05:00`), `UTC` and abbreviations (`PST`) are refused with `400 validation_error`, `field: timezone`: a restaurant’s clock needs daylight saving rules. string <= 64 characters **opening\_hours** 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 \>= 1 properties **mon** Array> <= 6 items **tue** Array> <= 6 items **wed** Array> <= 6 items **thu** Array> <= 6 items **fri** Array> <= 6 items **sat** Array> <= 6 items **sun** Array> <= 6 items **merchant\_contact** 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 \>= 1 properties **name** string nullable <= 100 characters **phone** E.164, for example `+14155550100`. Anything else is refused with `field: merchant_contact.phone`. string nullable <= 20 characters **email** string format: email nullable <= 100 characters **approved\_at** When your back office approved this store, RFC 3339. The store’s collaboration start date is the STORE-LOCAL day of this instant, so an evening approval on the US west coast does not start the store a day early. Defaults to now when omitted. string format: date-time **approved\_by** Who approved it on your side. Opaque to us; never resolved against our own accounts. string <= 300 characters #### Examples Exampleexample A store joining ```json { "partner_location_id": "store_123", "name": "Example Noodle House", "address": { "line1": "100 Main St", "city": "San Jose", "state": "CA", "postal_code": "95113", "country": "US" }, "plan": { "videos_per_month": 2, "term_months": 3 }, "signature_dishes": [ { "name": "Signature tempura platter", "image_url": "https://cdn.example.com/tempura.jpg" } ], "preferred_language": "zh", "approved_at": "2026-09-09T18:22:00Z", "approved_by": "ops@example.com", "approval_mode": "auto", "timezone": "America/Los_Angeles", "opening_hours": { "mon": [ [ "11:00", "15:00" ], [ "17:00", "21:30" ] ], "tue": [ [ "11:00", "21:30" ] ], "wed": [ [ "11:00", "21:30" ] ], "thu": [ [ "11:00", "21:30" ] ], "fri": [ [ "11:00", "22:00" ] ], "sat": [ [ "11:00", "22:00" ] ], "sun": [ [ "11:00", "21:00" ] ] }, "merchant_contact": { "name": "Alex Kim", "phone": "+14155550100", "email": "owner@example.com" } } ``` ### Responses #### 200 The store already existed with the same name and address. The body is the same as the one the original create returned, plus a top-level `warning` (`location_already_exists`, “This location already exists”). Nothing was written. Media typeapplication/json object **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-0-0) - [string](#tab-panel-0-1) - [Array](#tab-panel-0-2) - [object](#tab-panel-0-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook **warning** object **code** string Allowed values: location\_already\_exists **message** string ##### Example ```json { "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" } ], "warning": { "code": "location_already_exists", "message": "This location already exists" } } ``` #### 201 The store was created. Media typeapplication/json 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 **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-1-0) - [string](#tab-panel-1-1) - [Array](#tab-panel-1-2) - [object](#tab-panel-1-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook ##### Example ```json { "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" } ] } ``` #### 400 `validation_error`. `field` names the offending path, for example `plan.term_months`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `unauthorized`. Missing, malformed, unknown or revoked key. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 403 `forbidden_ip`. A valid key presented from an address outside its allowlist. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `location_already_exists` when this `partner_location_id` already names a live store with a different name or address. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Examples Examplealready\_exists ```json { "error": { "code": "location_already_exists", "message": "This location already exists", "field": "partner_location_id" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 500 `internal_error`. Never carries a cause; quote the reference in the message. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocation.md) ## Mint a 30 minute read-only token for one store POST /locations/{partner\_location\_id}/dashboard-token Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/dashboard-token'; const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/locations/store_123/dashboard-token \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Issues a credential whose entire authority is ONE store, for 30 minutes, read only. This is what makes the embedded merchant dashboard possible: the merchant’s browser holds this token and never your master key. Mint one when you render the embed. It cannot be refreshed and it cannot mint another one: this route requires the PARTNER KEY, so a leaked merchant URL expires rather than renewing. The token is accepted by the three `GET /locations/{partner_location_id}...` routes and nowhere else, as `Authorization: Bearer ` or `?token=`. `dashboard_url` is omitted when this deployment hosts no embedded dashboard. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Responses #### 200 A fresh token. Media typeapplication/json object **token** required A read-only credential for ONE store. Send it as a Bearer header or as `?token=`. string **expires\_at** required 30 minutes from minting, in UTC. This is a fact about the credential, not a time at the store. string format: date-time **dashboard\_url** The embeddable dashboard for this store with the token already in it. OMITTED entirely when this deployment hosts no embedded dashboard. string ##### Example generated ```json { "token": "example", "expires_at": "2026-04-15T12:00:00Z", "dashboard_url": "example" } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `location_terminated`. No token is minted for a store with no contract. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 503 `internal_error`. The store token feature is not enabled on this deployment. A configuration state, not a fault: tell us and we will switch it on. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocationdashboardtoken/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocationdashboardtoken.md) ## Approve the samples, or ask for a new batch POST /locations/{partner\_location\_id}/creator-samples/{batch\_id}/decision Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/creator-samples/smp_1b4e28ba-2fa1-4d3b-a3f5-ef19b5a7633b/decision'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"decision":"approve","note":"prefers Chinese-speaking creators"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/locations/store_123/creator-samples/smp_1b4e28ba-2fa1-4d3b-a3f5-ef19b5a7633b/decision \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "decision": "approve", "note": "prefers Chinese-speaking creators" }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) `approve`: recruiting starts, and `location.recruiting` follows when it does. `new_batch`: we prepare a new set that never repeats earlier samples, and send `location.samples_ready` again when it is ready. After two new batches our CSM calls the merchant. The same decision again answers 200 with the same body. The other decision on a batch already decided is 409, as is a decision on a batch that was replaced. PARTNER KEY ONLY. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` **batch\_id** required string ##### Example ``` smp_1b4e28ba-2fa1-4d3b-a3f5-ef19b5a7633b ``` The `batch_id` from the samples read or the `location.samples_ready` event. ### Request Bodyrequired Media typeapplication/json object **decision** required string Allowed values: approve new\_batch **note** Optional, with new\_batch. What the merchant wants instead. string nullable <= 500 characters #### Example ``` prefers Chinese-speaking creators ``` ### Responses #### 200 The decision as recorded. Media typeapplication/json object **batch\_id** string **batch\_number** integer **decision** string Allowed values: approve new\_batch **note** string nullable **decided\_at** string format: date-time nullable **next** string Allowed values: recruiting new\_batch\_preparing ##### Example ```json { "decision": "approve", "next": "recruiting" } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`, or `sample_batch_not_found` when no batch of this store has that id. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `conflict` (already decided the other way, replaced, or not a sample review store) or `location_terminated`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/decidepartnercreatorsamples/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/decidepartnercreatorsamples.md) ## The current batch of sample creators (sample review stores) GET /locations/{partner\_location\_id}/creator-samples Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/creator-samples'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://data.creatorain.com/partner/v1/locations/store_123/creator-samples \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) For a store with `approval_mode: sample_review`: 5 sample creators that show the range of creators the store will get, and a summary (follower range, common topics, audience). Samples are not the final list. We send `location.samples_ready` when a batch is ready. `status` is `preparing` (a batch is being prepared, `creators` is empty), `ready` (waiting for your decision) or `approved` (recruiting follows; `location.recruiting` when it starts). Public profile only: no email, phone, name or rates. EITHER CREDENTIAL: the partner key or that store’s own token. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** - **[storeTokenHeader](https://docs.creatorain.com/partner-api/reference/#storetokenheader)** - **[storeTokenQuery](https://docs.creatorain.com/partner-api/reference/#storetokenquery)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Responses #### 200 The current batch. Media typeapplication/json object **batch\_id** required string nullable **batch\_number** required integer nullable **status** required string Allowed values: preparing ready approved **prepared\_at** string format: date-time nullable **decided\_at** string format: date-time nullable **summary** object **followers\_min** integer nullable **followers\_max** integer nullable **followers\_average** integer nullable **common\_topics** Array **audience** string nullable **creators** required Array One sample creator. Public profile only. object **handle** string nullable **platforms** Array **followers** integer nullable **city** string nullable **average\_views** integer nullable **topics** Array **recent\_posts** Array object **post\_url** string **views** integer nullable ##### Example ```json { "batch_id": "smp_1b4e28ba-2fa1-4d3b-a3f5-ef19b5a7633b", "batch_number": 1, "status": "preparing", "summary": { "followers_min": 7900, "followers_max": 24800, "followers_average": 14380, "common_topics": [ "food", "travel" ], "audience": "local (San Jose)" }, "creators": [ { "handle": "example_creator_2", "platforms": [ "instagram", "tiktok" ], "followers": 18200, "city": "San Jose", "average_views": 12400, "topics": [ "food" ], "recent_posts": [ { "post_url": "https://www.instagram.com/p/...", "views": 12000 } ] } ] } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `conflict`. The store does not use sample review. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnercreatorsamples/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnercreatorsamples.md) ## One store's current state, progress and next visit GET /locations/{partner\_location\_id} Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://data.creatorain.com/partner/v1/locations/store_123 \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) 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 ` or `?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 - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** - **[storeTokenHeader](https://docs.creatorain.com/partner-api/reference/#storetokenheader)** - **[storeTokenQuery](https://docs.creatorain.com/partner-api/reference/#storetokenquery)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Responses #### 200 The store, its progress and its next visit. Media typeapplication/json object **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-0-0) - [string](#tab-panel-0-1) - [Array](#tab-panel-0-2) - [object](#tab-panel-0-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook **progress** This store’s progress against its plan. object **season\_target** 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. integer nullable **quarter\_target** 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. integer nullable **published\_count** Videos filmed at this store that are live. integer **booked\_count** 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. integer **booked\_upcoming** 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. integer **next\_visit** The next confirmed creator visit, or null when none is booked. object **reservation\_id** string format: uuid **arrive\_at** RFC 3339 with the STORE’S offset. The digits are the restaurant’s wall clock. string nullable **timezone** string nullable **notices** 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 **contact\_present** 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. boolean **single\_channel** 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. boolean **blocking\_reasons** 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`. Array Allowed values: hours\_missing campaign\_not\_running store\_paused store\_terminated **pipeline** 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 **contacted** integer **interested** integer **accepted** integer **booked** 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. integer **visited** integer **posted** integer **declined** integer **results** 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 **season\_starts\_on** string format: date **season\_ends\_on** Last day of the season. string format: date **season\_videos\_published** integer **season\_videos\_target** integer nullable **season\_posts** Posts behind those videos (a cross-post is 2 posts, 1 video). integer **season\_plays** integer **posts\_read** 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. integer **season\_plays\_posts\_measured** 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. integer **average\_likes\_per\_video** integer nullable **average\_shares\_per\_video** Over TikTok posts only. Null with none. integer nullable **average\_creator\_followers** integer nullable **estimated\_new\_guests** 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`. integer **estimated\_new\_guests\_note** string **estimated\_new\_guests\_help** Tooltip text for the (?) icon. string **commitment** 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 **videos** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **average\_creator\_followers** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **season\_plays** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **average\_likes\_per\_video** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **average\_shares\_per\_video** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **first\_visit** object **value** string format: date nullable **target** string format: date nullable **status** string Allowed values: met not\_met pending **measured\_at** string format: date-time nullable **final** boolean **previous\_season\_results** 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 **season\_starts\_on** string format: date **season\_ends\_on** Last day of the season. string format: date **season\_videos\_published** integer **season\_videos\_target** integer nullable **season\_posts** Posts behind those videos (a cross-post is 2 posts, 1 video). integer **season\_plays** integer **posts\_read** 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. integer **season\_plays\_posts\_measured** 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. integer **average\_likes\_per\_video** integer nullable **average\_shares\_per\_video** Over TikTok posts only. Null with none. integer nullable **average\_creator\_followers** integer nullable **estimated\_new\_guests** 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`. integer **estimated\_new\_guests\_note** string **estimated\_new\_guests\_help** Tooltip text for the (?) icon. string **commitment** 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 **videos** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **average\_creator\_followers** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **season\_plays** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **average\_likes\_per\_video** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **average\_shares\_per\_video** object **value** integer nullable **target** integer nullable **status** string Allowed values: met not\_met pending not\_measured **first\_visit** object **value** string format: date nullable **target** string format: date nullable **status** string Allowed values: met not\_met pending **measured\_at** string format: date-time nullable **final** boolean ##### Example ```json { "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 } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocation.md) ## One store's published videos GET /locations/{partner\_location\_id}/content Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/content?limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://data.creatorain.com/partner/v1/locations/store_123/content?limit=50' \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Videos filmed at this store that are LIVE on a platform, newest first. Approved but unpublished work is not listed: a merchant’s dashboard counts what is on the internet. `metrics` is `null` until the video’s numbers have first been read from the public post, which is deliberate: `{"views": 0}` would be a claim that a video got no views, and `null` says nobody counted. Once it has been read, `metrics` is an object and any single number the platform does not publish is `null`, never 0. `metrics_measured_at` gives the time each number was read, and is null beside a number that was never read. EITHER CREDENTIAL: the partner key or that store’s own token. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** - **[storeTokenHeader](https://docs.creatorain.com/partner-api/reference/#storetokenheader)** - **[storeTokenQuery](https://docs.creatorain.com/partner-api/reference/#storetokenquery)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` #### Query Parameters **cursor** string The `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. **limit** integer default: 50 \>= 1 <= 200 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 #### 200 A page of published videos. Media typeapplication/json object **items** required Array One published video filmed at the store. object **content\_id** string format: uuid **post\_url** string nullable **platform** string nullable **published\_at** RFC 3339 with the store’s offset. string nullable **timezone** string nullable **is\_collab** Whether the store’s own account is a co-author of the post, read from the post’s co-author list when the video’s numbers are read. `false` when we could not tell, which includes every TikTok post (that feed has no co-author list) and any post not yet read. boolean **content\_reuse** Whether the creator allowed the brand to reuse this content, as she chose it when she signed her agreement. `true` allowed; `false` declined, so the video is for her own post only; `null` when no choice was recorded (agreements signed before the option existed). boolean nullable **creator** object **handle** string nullable **metrics** NULL until the video’s numbers have first been read from the public post. After that it is an object, and a number the platform does not publish is null, never 0 (for example Instagram shares and saves). object **views** Plays. integer nullable **likes** integer nullable **comments** integer nullable **shares** integer nullable **saves** integer nullable **metrics\_measured\_at** When each number in `metrics` was read. Null exactly when `metrics` is null. object **views** string format: date-time nullable **likes** string format: date-time nullable **comments** string format: date-time nullable **shares** string format: date-time nullable **saves** string format: date-time nullable **next\_cursor** required string nullable ##### Example ```json { "items": [ { "post_url": "https://www.instagram.com/reel/abc123/", "platform": "instagram", "published_at": "2026-09-12T17:00:00-07:00", "timezone": "America/Los_Angeles", "metrics_measured_at": { "views": "2026-11-09T02:00:00Z", "likes": "2026-11-09T02:00:00Z", "comments": "2026-11-09T02:00:00Z", "shares": null, "saves": null } } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcontent/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcontent.md) ## One store's named creators (accepted or later) GET /locations/{partner\_location\_id}/creators Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/creators?limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://data.creatorain.com/partner/v1/locations/store_123/creators?limit=50' \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) The creators of this store’s current season who are at stage `accepted` or later, newest accepted first. Creators still being contacted are not named; they are counts in `pipeline` on `GET /locations/{partner_location_id}`, and `pipeline.accepted` is the length of this list. No email, phone, rates or notes: a merchant should never need to contact a creator directly. EITHER CREDENTIAL: the partner key or that store’s own token. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** - **[storeTokenHeader](https://docs.creatorain.com/partner-api/reference/#storetokenheader)** - **[storeTokenQuery](https://docs.creatorain.com/partner-api/reference/#storetokenquery)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` #### Query Parameters **cursor** string The `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. **limit** integer default: 50 \>= 1 <= 200 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 #### 200 A page of named creators. Media typeapplication/json object **items** required Array One named creator of a store. Public profile only. object **handle** string nullable **platforms** Array **followers** integer nullable **city** string nullable **stage** string Allowed values: accepted booked visited posted **next\_visit** Her next confirmed visit at this store, RFC 3339 with the store’s offset. string nullable **next\_cursor** required string nullable ##### Example ```json { "items": [ { "handle": "example_creator", "platforms": [ "instagram", "tiktok" ], "followers": 18200, "city": "San Jose", "stage": "accepted", "next_visit": "2026-10-03T15:00:00-07:00" } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcreators/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcreators.md) ## One store's creator bookings GET /locations/{partner\_location\_id}/reservations Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/reservations?from=2026-09-01&to=2026-09-30&status=pending&acknowledged=false&limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://data.creatorain.com/partner/v1/locations/store_123/reservations?from=2026-09-01&to=2026-09-30&status=pending&acknowledged=false&limit=50' \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) The main query behind a merchant’s dashboard. Newest touched first. EITHER CREDENTIAL: the partner key or that store’s own token. `acknowledged=false` narrows it to the bookings nobody at the restaurant has confirmed seeing, which is what a merchant’s own “still to confirm” panel filters on. NO PERSONAL DATA IS RETURNED, and there is no free-text search parameter, because our reservation search index is built from exactly the fields this projection withholds. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** - **[storeTokenHeader](https://docs.creatorain.com/partner-api/reference/#storetokenheader)** - **[storeTokenQuery](https://docs.creatorain.com/partner-api/reference/#storetokenquery)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` #### Query Parameters **from** string format: date Earliest VISIT DATE to include, `YYYY-MM-DD` in the store’s own calendar. A value we cannot read is refused rather than ignored: a reconciliation run whose window was silently dropped would read the whole book and report it as one month. ##### Example ``` 2026-09-01 ``` **to** string format: date Latest VISIT DATE to include, `YYYY-MM-DD`, inclusive. ##### Example ``` 2026-09-30 ``` **status** string Allowed values: pending confirmed rejected cancelled completed no\_show Return only bookings in this state. **acknowledged** boolean `true` for bookings a human at the restaurant has confirmed seeing (you told us so with `POST /reservations/{reservation_id}/acknowledge`), `false` for the ones nobody has. Omit it for both. `1` and `0` are accepted as well. ANY OTHER VALUE IS REFUSED with `400 validation_error` rather than ignored, and that is on purpose: a follow-up list that silently returned every booking would show your desk a queue of work that has already been done. ##### Example ```json false ``` **cursor** string The `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. **limit** integer default: 50 \>= 1 <= 200 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 #### 200 A page of bookings. Media typeapplication/json object **items** required Array One creator booking. NO PERSONAL DATA: no guest name, email or phone, no internal notes, and no free-text party note (those routinely carry dietary and medical detail). object **booked\_by** Who made the booking. Every booking on this API is a CreatoRain creator visit, so this is always `creatorain`. Also on the reservation webhook events. string Allowed values: creatorain **no\_charge** Always `true`: the visit is at no charge to the store (show it as “CreatoRain, no charge”). Also on the reservation webhook events. boolean **reservation\_id** string format: uuid **status** string Allowed values: pending confirmed rejected cancelled completed no\_show **arrive\_at** RFC 3339 with the STORE’S offset. The digits are the restaurant’s wall clock, so render them as they are; do not convert. string nullable **timezone** string nullable **party\_size** How many people are coming, the creator included. Always a number: 2 (the creator plus one guest) when the booking does not state one. The same value the webhook events send. integer **creator** As much of the creator as an outside system may see. Their contact details are never returned on this API. object **handle** Their public handle. string nullable **followers** Cross-platform follower total, not one platform’s count. integer nullable **platforms** The platforms they publish on. Always an array, never null. Array **dish** The dish chosen for this booking, or null when none was chosen. Never a guess from the store’s menu. The same value the webhook events send. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **updated\_at** RFC 3339 with the store’s offset. This is the sort key of the list. string nullable **acknowledged\_at** When a human at the restaurant told us they had seen this booking, RFC 3339 with the STORE’S offset. Null when nobody has, which is what `acknowledged=false` filters on. THE EARLIEST ACKNOWLEDGEMENT, not the latest. A booking can carry both kinds (forwarded to the manager, and acknowledged), and the question this answers is “has anybody seen this yet, and when”. string nullable **acknowledged\_kind** Which kind that earliest acknowledgement was. Null when there is none. string nullable Allowed values: forwarded\_to\_manager acknowledged\_self **partner\_location\_id** Present only on `GET /reservations`, where a row has to say which store it belongs to. string **location\_id** Present only on `GET /reservations`. string format: uuid **next\_cursor** required Send this back as `cursor` for the next page. NULL means this was the last page, and it is honest about that: we read one row beyond your `limit` to answer the question, so a page that happens to be exactly full does not cost you an extra empty request. string nullable ##### Example ```json { "items": [ { "booked_by": "creatorain", "no_charge": true, "status": "pending", "arrive_at": "2026-09-14T19:00:00-07:00", "timezone": "America/Los_Angeles", "party_size": 2, "creator": { "handle": "example_creator", "followers": 48213, "platforms": [ "instagram", "tiktok" ] }, "acknowledged_at": "2026-09-11T16:04:12-07:00", "acknowledged_kind": "forwarded_to_manager" } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationreservations/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationreservations.md) ## That month's reconciliation detail, per store GET /billing/monthly Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/billing/monthly?month=2026-09&limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://data.creatorain.com/partner/v1/billing/monthly?month=2026-09&limit=50' \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) 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 - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Query Parameters **month** required string /^\\d{4}-(0\[1-9\]|1\[0-2\])$/ The month to report, `YYYY-MM`, in each STORE’S own calendar. Required, with no default. ##### Example ``` 2026-09 ``` **cursor** string The `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. **limit** integer default: 50 \>= 1 <= 200 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 #### 200 A page of stores, with the month’s counts for each. Media typeapplication/json object **month** required The month asked for, echoed back, so a stored report says what it is of. string **note** required The one limitation of these numbers, on every response rather than in a document somebody has to remember to read. string **amounts\_note** required When the amounts are null, and that make-up videos are never billed. On every response. string **generated\_at** required 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. string format: date-time **items** required Array One store’s month. Counts only: there is no personal data anywhere in this report. object **partner\_location\_id** YOUR id for the store, which is what your own billing is keyed on. string **location\_id** Our id for the same store. string format: uuid **videos\_published** 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. integer **plan\_videos\_per\_month** 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. integer nullable **plan\_term\_months** integer nullable **reservations\_completed** Visits at this store marked completed, by VISIT DATE in the store’s calendar. Only visits booked on your key’s campaign count. integer **no\_shows** Visits at this store marked no\_show, by the same date and the same campaign. integer **status** 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. string Allowed values: active paused terminated **makeup\_videos** Of `videos_published`, the free replacement videos (after a no-show, or for a video the merchant rejected). Never billed. integer **billed\_videos** `videos_published` - `makeup_videos`: the videos the two amounts are for. integer **cost\_pending\_videos** Billed videos whose creator cost is not known yet. While above 0, `amount_due` is null. integer **currency** The currency of the amounts. Null when the store has no locked price. string nullable **amount\_due** 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. number nullable **merchant\_amount** 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. number nullable **next\_cursor** required 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. string nullable ##### Example ```json { "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 } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnermonthlybilling/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnermonthlybilling.md) ## The finished price for a merchant's choices, before a store exists GET /pricing/quote Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/pricing/quote?videos_per_month=2&term_months=3&approval_mode=auto&postal_code=95050'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://data.creatorain.com/partner/v1/pricing/quote?videos_per_month=2&term_months=3&approval_mode=auto&postal_code=95050' \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Ask for a quote on the apply screen and the Confirm screen. You do NO price maths: every number is ready to show. Show `merchant.*` on the merchant’s screens, and `creatorain` and `surcharge` on your sales screen. Change a choice and ask again; the answer reflects it. - `merchant.per_video` is the price per published video you charge the merchant, with your surcharge and any plan surcharge already included (base price + `surcharge.per_video` + `plan_surcharge.per_video`). It is the same for every city. `per_month` = per video x videos per month, `per_season` = per month x 3. `season_videos` = videos per month x 3. - `creatorain` is what we bill you, per published video: the creator’s actual cost plus our fee. `fee_per_video` is our fee. The creator cost varies per video, so it is not a fixed price: `creator_cost_per_video` is an estimate range (or null), the bill uses the actual cost. - `surcharge.per_video` is your surcharge (`PUT /settings`; a default applies until you set one, so editing it changes what merchants see). It is shown so you can see your share, and is already included in `merchant.per_video` (do not add it again). - `plan_surcharge` is its own line for a non-standard plan: fewer than 2 videos a month, or a term below 3 months (send `term_months` to include it). Such a plan is accepted, and `plan_surcharge.per_video` is added to the merchant price so you can show why it costs more (`applies` is true; 0 and false for a standard plan). `placeholder: true` means the amount is provisional and may change. - `valid_until` is the last day (UTC) the quote holds. A store confirmed by then is locked at the price in force when it is confirmed. We bill by published video. `postal_code` is optional; when sent it is checked as a US ZIP (a bad one is rejected), but there is no per-area pricing, so it does not change the price. PARTNER KEY ONLY. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Query Parameters **videos\_per\_month** required integer \>= 1 <= 10 1 to 10. The standard plan is 2 to 10; 1 is accepted and adds the plan surcharge. ##### Example ```json 2 ``` **term\_months** integer \>= 1 <= 120 Contract length in months, 1 to 120. The standard terms are 3, 8 and 12 (longer is allowed); below 3 adds the plan surcharge. ##### Example ```json 3 ``` **approval\_mode** string default: auto Allowed values: auto sample\_review **postal\_code** string /^\\d{5}(-\\d{4})?$/ ##### Example ```json 95050 ``` ### Responses #### 200 The quote. Media typeapplication/json object **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **valid\_until** required string format: date ##### Example ```json { "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, "valid_until": "2026-10-31" } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnerpricingquote/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnerpricingquote.md) ## Every store's bookings, for your operations desk GET /reservations Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/reservations?from=2026-09-01&to=2026-09-30&status=pending&acknowledged=false&limit=50'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url 'https://data.creatorain.com/partner/v1/reservations?from=2026-09-01&to=2026-09-30&status=pending&acknowledged=false&limit=50' \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) The same rows as the per-store list, across every store enrolled under your key, each row also carrying `partner_location_id` and `location_id` so it can be attributed. YOUR “NEEDS FOLLOW-UP” LIST IS THIS CALL WITH FOUR PARAMETERS: ``` GET /partner/v1/reservations?status=confirmed&from=2026-09-11&to=2026-09-12&acknowledged=false ``` Those are the visits arriving that nobody at the restaurant has confirmed seeing, and they are the same bookings `unacknowledged_upcoming` on `GET /summary` counts, so a desk can go from the number straight to the rows. PARTNER KEY ONLY. A store token cannot read this: a merchant’s browser must never be able to read the whole chain’s schedule, which is the reason the per-store credential exists. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Query Parameters **from** string format: date Earliest VISIT DATE to include, `YYYY-MM-DD` in the store’s own calendar. A value we cannot read is refused rather than ignored: a reconciliation run whose window was silently dropped would read the whole book and report it as one month. ##### Example ``` 2026-09-01 ``` **to** string format: date Latest VISIT DATE to include, `YYYY-MM-DD`, inclusive. ##### Example ``` 2026-09-30 ``` **status** string Allowed values: pending confirmed rejected cancelled completed no\_show Return only bookings in this state. **acknowledged** boolean `true` for bookings a human at the restaurant has confirmed seeing (you told us so with `POST /reservations/{reservation_id}/acknowledge`), `false` for the ones nobody has. Omit it for both. `1` and `0` are accepted as well. ANY OTHER VALUE IS REFUSED with `400 validation_error` rather than ignored, and that is on purpose: a follow-up list that silently returned every booking would show your desk a queue of work that has already been done. ##### Example ```json false ``` **cursor** string The `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. **limit** integer default: 50 \>= 1 <= 200 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 #### 200 A page of bookings across every store of this key. Media typeapplication/json object **items** required Array One creator booking. NO PERSONAL DATA: no guest name, email or phone, no internal notes, and no free-text party note (those routinely carry dietary and medical detail). object **booked\_by** Who made the booking. Every booking on this API is a CreatoRain creator visit, so this is always `creatorain`. Also on the reservation webhook events. string Allowed values: creatorain **no\_charge** Always `true`: the visit is at no charge to the store (show it as “CreatoRain, no charge”). Also on the reservation webhook events. boolean **reservation\_id** string format: uuid **status** string Allowed values: pending confirmed rejected cancelled completed no\_show **arrive\_at** RFC 3339 with the STORE’S offset. The digits are the restaurant’s wall clock, so render them as they are; do not convert. string nullable **timezone** string nullable **party\_size** How many people are coming, the creator included. Always a number: 2 (the creator plus one guest) when the booking does not state one. The same value the webhook events send. integer **creator** As much of the creator as an outside system may see. Their contact details are never returned on this API. object **handle** Their public handle. string nullable **followers** Cross-platform follower total, not one platform’s count. integer nullable **platforms** The platforms they publish on. Always an array, never null. Array **dish** The dish chosen for this booking, or null when none was chosen. Never a guess from the store’s menu. The same value the webhook events send. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **updated\_at** RFC 3339 with the store’s offset. This is the sort key of the list. string nullable **acknowledged\_at** When a human at the restaurant told us they had seen this booking, RFC 3339 with the STORE’S offset. Null when nobody has, which is what `acknowledged=false` filters on. THE EARLIEST ACKNOWLEDGEMENT, not the latest. A booking can carry both kinds (forwarded to the manager, and acknowledged), and the question this answers is “has anybody seen this yet, and when”. string nullable **acknowledged\_kind** Which kind that earliest acknowledgement was. Null when there is none. string nullable Allowed values: forwarded\_to\_manager acknowledged\_self **partner\_location\_id** Present only on `GET /reservations`, where a row has to say which store it belongs to. string **location\_id** Present only on `GET /reservations`. string format: uuid **next\_cursor** required Send this back as `cursor` for the next page. NULL means this was the last page, and it is honest about that: we read one row beyond your `limit` to answer the question, so a page that happens to be exactly full does not cost you an extra empty request. string nullable ##### Example ```json { "items": [ { "booked_by": "creatorain", "no_charge": true, "status": "pending", "arrive_at": "2026-09-14T19:00:00-07:00", "timezone": "America/Los_Angeles", "party_size": 2, "creator": { "handle": "example_creator", "followers": 48213, "platforms": [ "instagram", "tiktok" ] }, "acknowledged_at": "2026-09-11T16:04:12-07:00", "acknowledged_kind": "forwarded_to_manager" } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnerreservations/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnerreservations.md) ## Your settings GET /settings Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/settings'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://data.creatorain.com/partner/v1/settings \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Your surcharge per video (a default applies until you set one; `updated_at` is null then), its currency, and when it was last set. PARTNER KEY ONLY. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Responses #### 200 Your settings. Media typeapplication/json object **surcharge\_per\_video** required number **currency** required string **updated\_at** required string nullable ##### Example ```json { "surcharge_per_video": 10, "currency": "USD", "updated_at": "2026-10-01T09:00:00Z" } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnersettings/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnersettings.md) ## Your whole estate, in one call GET /summary Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/summary'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request GET \ --url https://data.creatorain.com/partner/v1/summary \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) The morning screen for your operations desk: how many stores are running, how many are paused, what has been published this month, what is arriving over the next fortnight, how many bookings a human at a restaurant confirmed seeing, and how many visits arrive within 24 hours that NOBODY has acknowledged. That last number is what this endpoint exists for. Every one of those bookings is a creator who may walk into a restaurant that is not expecting them, and the list behind the number is `GET /reservations?status=confirmed&from=&to=&acknowledged=false`. NO PARAMETERS, deliberately. Every window here is fixed (this month, the next 14 days, the next 24 hours) so that today’s screen can be compared with yesterday’s. When you need a window of your own, the lists take one. ### Which clock each number is on Your stores span time zones, so there is no single clock this body could be stated on and it does not pretend otherwise. `published_this_month` and `reminders_acknowledged_this_month` are bucketed in EACH STORE’S OWN local month, exactly as `GET /billing/monthly` buckets them, so a tile and an invoice can never disagree. `visits_next_14_days` and `unacknowledged_upcoming` are measured on each store’s own wall clock, which matters most for the 24 hour window: measured in UTC, a third of a US west coast day would fall in or out of it. `generated_at` is the only TIME on this body. It is an instant about our run rather than a time at any restaurant, and `timezone` is its zone, which is always `UTC`. PARTNER KEY ONLY. A store token cannot read this: the state of the whole chain is your business, not one merchant’s. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Responses #### 200 The estate as it stands. Media typeapplication/json Your estate as it stands. Counts only: there is no personal data anywhere in this body. object **active\_stores** required Stores with a live contract that are being offered to creators. integer **paused\_stores** required Stores with a live contract that are paused: no NEW scheduling, confirmed bookings untouched. Terminated stores are in NEITHER number, so these two do not necessarily add up to every store you have ever sent us. integer **published\_this\_month** required Videos live on a platform, published inside each store’s OWN local month. The same definition `GET /billing/monthly` uses, so this tile and that invoice cannot differ. integer **visits\_next\_14\_days** required Confirmed creator visits arriving in the next 14 days, on each store’s own wall clock. Counted across EVERY store of the key including terminated ones, because ending a contract does not cancel a visit a creator has already been promised. integer **reminders\_acknowledged\_this\_month** required Bookings a human at a restaurant confirmed seeing this month, counted ONCE each. A booking that was both forwarded to the manager and acknowledged is one booking somebody dealt with, not two. integer **unacknowledged\_upcoming** required THE NUMBER TO ACT ON: confirmed visits arriving within 24 hours that nobody at the restaurant has acknowledged. The rows behind it are `GET /reservations?status=confirmed&from=&to=&acknowledged=false`. integer **generated\_at** required When this was computed, RFC 3339 in UTC. A fact about our run, not a time at any store. string format: date-time **timezone** required The zone of `generated_at`, which is the only time on this body. Always `UTC`. The COUNTS are on each store’s own clock; see the endpoint description. string Allowed values: UTC ##### Example ```json { "active_stores": 42, "paused_stores": 3, "published_this_month": 17, "visits_next_14_days": 9, "reminders_acknowledged_this_month": 12, "unacknowledged_upcoming": 2, "generated_at": "2026-09-11T09:00:00Z", "timezone": "UTC" } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/getpartnersummary/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/getpartnersummary.md) ## Change a store's name, address, plan, dishes, language, hours, time zone or contact PATCH /locations/{partner\_location\_id} Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123'; const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', '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); } ``` ```sh curl --request PATCH \ --url https://data.creatorain.com/partner/v1/locations/store_123 \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "name": "Example Noodle House Downtown" }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) 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 - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Request Bodyrequired Media typeapplication/json 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 \>= 1 properties **name** string <= 300 characters **address** 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 **line1** string nullable <= 300 characters **city** string nullable <= 120 characters **state** string nullable <= 120 characters **postal\_code** string nullable <= 40 characters **country** string nullable <= 120 characters **plan** 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 **videos\_per\_month** 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). integer \>= 1 <= 10 **term\_months** 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. integer \>= 1 <= 120 **signature\_dishes** Array <= 50 items object **name** required string <= 300 characters **image\_url** string format: uri nullable <= 2000 characters **preferred\_language** string Allowed values: zh en **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **timezone** Send `null` to clear it; the store goes back to the zone read from its address. string <= 64 characters **opening\_hours** 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 \>= 1 properties **mon** Array> <= 6 items **tue** Array> <= 6 items **wed** Array> <= 6 items **thu** Array> <= 6 items **fri** Array> <= 6 items **sat** Array> <= 6 items **sun** Array> <= 6 items **merchant\_contact** 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 \>= 1 properties **name** string nullable <= 100 characters **phone** E.164, for example `+14155550100`. Anything else is refused with `field: merchant_contact.phone`. string nullable <= 20 characters **email** string format: email nullable <= 100 characters **rules** Which creators this store will take. REPLACES the store’s rules for the attributes present and leaves the rest alone. Array <= 24 items 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-0-0) - [string](#tab-panel-0-1) - [Array](#tab-panel-0-2) - [object](#tab-panel-0-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook **clear\_rules** 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. Array <= 12 items Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate #### Examples Select examplerenameupgradematchingmatching\_cleared A store changed its name ```json { "name": "Example Noodle House Downtown" } ``` The merchant bought more videos ```json { "plan": { "videos_per_month": 4 } } ``` This store only wants creators with 20k+ on TikTok ```json { "rules": [ { "attribute": "follower_count", "operator": "gte", "value": { "count": 20000, "platform": "tiktok" } }, { "attribute": "platform", "operator": "eq", "value": "tiktok" } ] } ``` Drop the follower bar, keep everything else ```json { "clear_rules": [ "follower_count" ] } ``` ### Responses #### 200 The store after the change. Media typeapplication/json 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 **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-1-0) - [string](#tab-panel-1-1) - [Array](#tab-panel-1-2) - [object](#tab-panel-1-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook ##### Example ```json { "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" } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `location_terminated`. A store whose contract has ended cannot be changed. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/patchpartnerlocation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/patchpartnerlocation.md) ## Pause scheduling at a store POST /locations/{partner\_location\_id}/pause Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/pause'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"reason":"Kitchen refit"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/locations/store_123/pause \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "reason": "Kitchen refit" }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Stops us offering this store to creators from the moment of the call. CONFIRMED BOOKINGS ARE NOT CANCELLED. One cancellation usually loses that creator permanently, and creator supply is shared across a city. If the store cannot host a visit that is already booked, ask us to reschedule it. IDEMPOTENT: a store that is already paused answers `200` with its current state, writes nothing, and keeps the instant of the FIRST pause, which is what a merchant’s “paused since” line is made of. WEBHOOK: a pause that changes the store sends one `location.paused` event (`data`: `location_id`, `partner_location_id`, `reason`, `effective_at`, `timezone`, `initiated_by`). A repeat sends nothing. A pause or resume made by our own team sends the same event with `initiated_by: creatorain`. `resume` sends `location.resumed` and `terminate` sends `location.terminated` the same way (once per change). ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Request Body Media typeapplication/json object **reason** Why, in your words. Kept on the store so an operator reading it later can tell a partner pause from one of ours. Defaults to `Paused by partner`. string nullable <= 500 characters #### Example ``` Kitchen refit ``` ### Responses #### 200 The store, now `paused`. Media typeapplication/json 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 **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-0-0) - [string](#tab-panel-0-1) - [Array](#tab-panel-0-2) - [object](#tab-panel-0-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook ##### Example ```json { "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" } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `location_terminated`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/pausepartnerlocation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/pausepartnerlocation.md) ## Set your surcharge per video, once for all stores PUT /settings Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/settings'; const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"surcharge_per_video":10}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request PUT \ --url https://data.creatorain.com/partner/v1/settings \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "surcharge_per_video": 10 }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) A JSON number from 0 to 10000, in whole cents (`10` or `10.5`, not `"10"`). It replaces the default surcharge. It applies to new quotes and to stores confirmed after it. Stores already confirmed keep the price they were confirmed with until their plan changes. PARTNER KEY ONLY. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Request Bodyrequired Media typeapplication/json object **surcharge\_per\_video** required number <= 10000 #### Example ```json 10 ``` ### Responses #### 200 The stored settings. Media typeapplication/json object **surcharge\_per\_video** required number **currency** required string **updated\_at** required string nullable ##### Example ```json { "surcharge_per_video": 10, "currency": "USD", "updated_at": "2026-10-01T09:00:00Z" } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/putpartnersettings/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/putpartnersettings.md) ## Resume scheduling at a store POST /locations/{partner\_location\_id}/resume Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/resume'; const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/locations/store_123/resume \ --header 'Authorization: Bearer ' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Offers the store to creators again and clears the pause reason. IDEMPOTENT: a store that is already active answers `200` and writes nothing. A TERMINATED store is never resumed; it answers `409 location_terminated`. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Responses #### 200 The store, now `active`. Media typeapplication/json 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 **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-0-0) - [string](#tab-panel-0-1) - [Array](#tab-panel-0-2) - [object](#tab-panel-0-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook ##### Example ```json { "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" } ] } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 409 `location_terminated`. A terminated contract cannot be resumed. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/resumepartnerlocation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/resumepartnerlocation.md) ## Overview ### Acknowledgement Telling us a human at the restaurant saw a booking ### Operations POST [/reservations/{reservation\_id}/acknowledge](https://docs.creatorain.com/partner-api/reference/operations/acknowledgepartnerreservation/) Source: https://docs.creatorain.com/partner-api/reference/operations/tags/acknowledgement/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/tags/acknowledgement.md) ## Overview ### Billing The monthly reconciliation detail, per store ### Operations GET [/billing/monthly](https://docs.creatorain.com/partner-api/reference/operations/getpartnermonthlybilling/) Source: https://docs.creatorain.com/partner-api/reference/operations/tags/billing/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/tags/billing.md) ## Overview ### Locations Enrolling a merchant’s store and keeping its state ### Operations POST [/locations](https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocation/) PATCH [/locations/{partner\_location\_id}](https://docs.creatorain.com/partner-api/reference/operations/patchpartnerlocation/) POST [/locations/{partner\_location\_id}/pause](https://docs.creatorain.com/partner-api/reference/operations/pausepartnerlocation/) POST [/locations/{partner\_location\_id}/resume](https://docs.creatorain.com/partner-api/reference/operations/resumepartnerlocation/) POST [/locations/{partner\_location\_id}/terminate](https://docs.creatorain.com/partner-api/reference/operations/terminatepartnerlocation/) POST [/locations/{partner\_location\_id}/creator-samples/{batch\_id}/decision](https://docs.creatorain.com/partner-api/reference/operations/decidepartnercreatorsamples/) Source: https://docs.creatorain.com/partner-api/reference/operations/tags/locations/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/tags/locations.md) ## Overview ### Pricing Finished prices (you do no price maths) and your surcharge setting ### Operations GET [/pricing/quote](https://docs.creatorain.com/partner-api/reference/operations/getpartnerpricingquote/) GET [/settings](https://docs.creatorain.com/partner-api/reference/operations/getpartnersettings/) PUT [/settings](https://docs.creatorain.com/partner-api/reference/operations/putpartnersettings/) Source: https://docs.creatorain.com/partner-api/reference/operations/tags/pricing/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/tags/pricing.md) ## Overview ### Reads What a store looks like now, its bookings and its published videos ### Operations GET [/locations/{partner\_location\_id}](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocation/) POST [/locations/{partner\_location\_id}/dashboard-token](https://docs.creatorain.com/partner-api/reference/operations/createpartnerlocationdashboardtoken/) GET [/locations/{partner\_location\_id}/reservations](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationreservations/) GET [/locations/{partner\_location\_id}/content](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcontent/) GET [/locations/{partner\_location\_id}/creators](https://docs.creatorain.com/partner-api/reference/operations/getpartnerlocationcreators/) GET [/locations/{partner\_location\_id}/creator-samples](https://docs.creatorain.com/partner-api/reference/operations/getpartnercreatorsamples/) GET [/reservations](https://docs.creatorain.com/partner-api/reference/operations/getpartnerreservations/) GET [/summary](https://docs.creatorain.com/partner-api/reference/operations/getpartnersummary/) Source: https://docs.creatorain.com/partner-api/reference/operations/tags/reads/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/tags/reads.md) ## End a store's contract POST /locations/{partner\_location\_id}/terminate Select code sampleFetchcURL ```js const url = 'https://data.creatorain.com/partner/v1/locations/store_123/terminate'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"effective_at":"2026-10-31T00:00:00Z","reason":"Merchant closed"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```sh curl --request POST \ --url https://data.creatorain.com/partner/v1/locations/store_123/terminate \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "effective_at": "2026-10-31T00:00:00Z", "reason": "Merchant closed" }' ``` - Production (live stores; a live key is issued per partner) - Sandbox, for integration testing (test keys, test stores) Records that the contract has ended, stops the store being offered, and keeps every row. Nothing is deleted: the visits completed and videos published at the store are what its final invoice is made of. `effective_at` is when the CONTRACT ends and may be in the future (notice given in advance) or in the past (it ended before anybody told us). It is a different fact from when you told us, which we record separately. FINAL. A second call answers `200` with the same body and writes nothing, so a retry cannot rewrite the record. There is no un-terminate over the API; ask us if a contract has to be reinstated. ### Authorizations - **[partnerApiKey](https://docs.creatorain.com/partner-api/reference/#partnerapikey)** ### Parameters #### Path Parameters **partner\_location\_id** required string <= 200 characters YOUR id for the store, as you sent it to `POST /locations`. ##### Example ``` store_123 ``` ### Request Body Media typeapplication/json object **effective\_at** When the CONTRACT ends, RFC 3339. May be in the future or the past. Defaults to now. Different from when you told us, which we record separately. string format: date-time #### Example ``` 2026-10-31T00:00:00Z ``` **reason** string nullable <= 500 characters #### Example ``` Merchant closed ``` ### Responses #### 200 The store, now `terminated`. Media typeapplication/json 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 **location\_id** OUR id for the store. Stable, and what every other endpoint refers to it by. string format: uuid **partner\_location\_id** Your id, as you sent it (trimmed). string **status** `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. string Allowed values: active paused terminated **network** A display label for the local creator pool, for example `example-pool`. Label only. string nullable **dashboard\_url** 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. string nullable **timezone** 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. string nullable **created\_at** RFC 3339 with the store’s offset. string nullable **hours** 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 **state** required string Allowed values: missing found **source** required 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. string nullable Allowed values: partner places gemini website manual none **approval\_mode** 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. string default: auto Allowed values: auto sample\_review **pricing** 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 **currency** required string **billing\_unit** required string Allowed values: published\_video **creatorain** required What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** required object **per\_video** number **plan\_surcharge** required The non-standard plan line, included in `merchant`. 0 / false for a standard plan. object **per\_video** number **applies** boolean **placeholder** True while the amount is provisional. boolean **merchant** required object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** required integer nullable **note** required string **locked\_at** When the price in force was locked (UTC). Null when `locked` is false. string nullable **locked** False for a store with no locked price, priced from the current defaults. boolean **source** string Allowed values: locked default **upcoming** The price from `from_month` (the store’s next month), when a re-lock is waiting. object **from\_month** string **currency** string **creatorain** What we bill the partner per published video. Not a fixed price. object **fee\_per\_video** required number **creator\_cost\_per\_video** required 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 **min** number **max** number **billed\_as** required string Allowed values: creator\_cost\_plus\_fee **surcharge** object **per\_video** number **plan\_surcharge** object **per\_video** number **applies** boolean **placeholder** boolean **merchant** object **per\_video** required number **per\_month** required Per\_video x videos per month. Null for a store with no plan. number nullable **per\_season** required Per\_month x 3. number nullable **season\_videos** integer nullable **first\_visit\_business\_days** 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. integer nullable **first\_visit\_due\_by** 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. string format: date nullable **rules** 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. Array 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 **attribute** required string Allowed values: follower\_count platform language home\_metro radius\_miles performance\_index engagement\_rate **operator** required string Allowed values: gte lte in eq **value** required One of: - [integer](#tab-panel-0-0) - [string](#tab-panel-0-1) - [Array](#tab-panel-0-2) - [object](#tab-panel-0-3) integer string Array object **count** integer **platform** string nullable Allowed values: instagram tiktok youtube facebook ##### Example ```json { "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" } ] } ``` #### 400 `validation_error`. `field` names the offending parameter. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 401 `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. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 404 `location_not_found`. No store of this key carries that `partner_location_id`. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` #### 429 `rate_limited`. Over this key’s requests-per-minute ceiling. Media typeapplication/json object **error** required object **code** required The stable value to branch on. string Allowed values: unauthorized forbidden\_ip rate\_limited validation\_error location\_already\_exists location\_not\_found location\_terminated reservation\_not\_found conflict internal\_error **message** required A human sentence. Copy, not contract; it may be reworded. string **field** The request field at fault, dotted for a nested one (`plan.term_months`). string ##### Example ```json { "error": { "code": "unauthorized" } } ``` Source: https://docs.creatorain.com/partner-api/reference/operations/terminatepartnerlocation/ (markdown: https://docs.creatorain.com/partner-api/reference/operations/terminatepartnerlocation.md)