<!-- Markdown copy of https://docs.creatorain.com/guides/video-production/ -->
# Video production

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](/guides/webhooks/).
