# Stream a Bite store

> Land a Bite store's customers, orders, promotions and loyalty in your warehouse every few minutes, connected through Bite's own sign-in, with nothing to approve.

A Bite stream lands a Bite store's customers, orders, promotions and loyalty in your warehouse, as often as every few minutes. Each run reads only the customers that changed and the orders placed since the last run.

Bite is a **published source**, like [Postgres](https://docs.sanda-os.com.au/streams/postgres): sanda wrote the code that reads it and runs it as its own, so there is no connector for cherry to write or for anyone to approve. A store's admin connects the store through Bite's own sign-in, you choose what to read, and you set a schedule.

:::note
Bite is in the catalogue once connecting Bite is switched on for your console. If **Choose a source** doesn't list it, ask sanda support.
:::

## Before you start

- **A store admin connects the store.** Bite asks whoever connects to sign in to Bite and approve what sanda may read, and only a store's admins can approve it. In sanda, only owners and admins connect a store and make a stream on it, because sanda reads the store on the whole workspace's behalf.
- **One store at a time.** Bite calls each brand a store, and each connection reads one store. A brand with three stores connects three times and makes a stream for each, because a stream keeps each store's records by Bite's own ids.
- **Contact details are your choice.** Customers' email, phone, date of birth and addresses are a permission of their own. Tick **Include customers' contact details** when you connect to ask for them. Without it those columns arrive empty, and everything else arrives as usual.

## Connect a store

:::steps
1. **Open Pull.** Go to **Data · Streams**, open the **Pull** tab and press the **Bite** card under **Choose a source**. The new pull's editor opens on **Connect a Bite store** when none is connected yet. Once a store is connected, **Connect a store** beside Bite under **Connected** adds another.
2. **Choose whether to include contact details**, then press **Continue to Bite**.
3. **Sign in to Bite and choose the store.** Bite lists what sanda asks to read. Approve it. If you don't, nothing is connected.
4. **Back in sanda**, a line at the top of the page says the store is connected, and whether its customers' contact details came with it. The store is listed under Bite in **Connected**. If you started from a new stream, you are back in its editor with the store chosen.
:::

sanda keeps the connection encrypted, and it is never shown, in the console or to cherry. **Connect again** connects the store again: choose the same store when Bite asks, and every stream on it carries on. **Disconnect** forgets the connection and asks Bite to end it. A store admin can also remove sanda's access in Bite at any time, and the store's streams then wait until it is connected again.

## Make a stream

:::steps
1. **Start it.** Press the **Bite** card under **Choose a source**, or **New pull** and then **Bite**.
2. **Name it.** Its tables are named after it: a stream called `bondi` lands orders in `raw.bondi__orders`.
3. **Choose the store**, and, if your workspace has more than one warehouse, the warehouse it lands in. Both are chosen once.
4. **Choose what it reads.** Everything the store allowed is ticked. Untick what you don't need.
5. **Read history from** is optional: the date the first run starts from. Leave it empty to read the last 365 days.
6. **Choose when it runs**, and press **Save pull**. Saving reads nothing yet: press **Run now**, or wait for its schedule.
:::

## What it reads

| Tick | Lands in | Each run reads |
|---|---|---|
| **Customers** | `raw.<stream>__customers` | The customers that changed since the last run |
| **Orders** | `raw.<stream>__orders` | The orders placed since the last run |
| **Promotions** | `raw.<stream>__promotions` | The promotions running now |
| **Sites** | `raw.<stream>__sites` | The whole list |
| **Loyalty tiers** | `raw.<stream>__tiers` | The whole list |
| **Products** | `raw.<stream>__products` | The whole list |
| **Product categories** | `raw.<stream>__categories` | The whole list |
| **Loyalty rewards** | `raw.<stream>__rewards` | The whole list |

Something the store didn't allow (promotions, say) is marked **not allowed by this store** in the editor, and sanda won't save a stream that reads it. Connect the store again and allow it, or leave it off.

### Customers

Each run reads the customers whose record changed since the last run, oldest change first. A customer's record changes whenever anything about them does: their profile, points, credit, tier or marketing consent. Each run starts 10 minutes before the newest change the last one saw, so a change made while the last run was reading isn't missed. A customer read twice is still one row, and one that hasn't changed costs nothing.

A customer deactivated in Bite keeps their row, with `active` false.

### Orders

Each run reads the orders placed since the last run, starting 10 minutes before the newest one it saw. Bite lists orders a few weeks at a time, so a first run walks from the history date to today in windows of 30 days, and a long history takes several runs, each carrying on from the last.

An order's items and the promotions applied to it land with the order, as lists in its `items` and `promotions` columns. Orders are read by when they were placed, so a later change to an order already read is read again only when you press **Load everything again**.

### Promotions and the lists

Promotions, sites, tiers, products, categories and rewards are read whole each run. A promotion that ends drops out of what Bite lists as running, so its row is marked `_deleted_at` and kept.

## What lands in your warehouse

Every field becomes a column, typed by its values, and the whole record is kept in `_record`, as for every [pull](https://docs.sanda-os.com.au/streams/in#where-the-records-land). A few things are worth knowing when you model them:

- **Money is in cents**, with its currency beside it: Bite sends A$456.00 as `45600` and `AUD`. Divide by 100 in a view.
- **Times are UTC**, as Bite sends them. Convert them to your own time zone in a view.
- **Ids are text**, as Bite sends them. An order's `site_id` names a row of sites, and an item's `product_key` and `category_id` name rows of products and categories.
- **Nested details are JSON**: a customer's `loyalty` (points, credit and tier), `activity` and `marketing` (consent and tags) each land as a JSON column of their own.
- **How an order was placed and how it was fulfilled are separate**: `channel` is app, website, pos or catering, and `order_type` is pickup, delivery or dine_in.
- **Contact details are empty** when the store didn't allow them.

## Change a stream

**Edit**, on the stream's page, changes everything but the store and the warehouse. Something you take off keeps its table, with what it landed. A new **Read history from** date takes effect the next time everything is read from the start: press **Load everything again** on the stream's page.

## When something goes wrong

| What you see | What to do |
|---|---|
| Bite no longer accepts sanda's connection to the store | A store admin removed sanda's access, or the connection lapsed. The stream waits, rather than failing again and again. Press **Connect it again** on the stream's page, or **Connect again** beside the store under **Connected**, and choose the same store |
| The store didn't allow sanda to read something | Take it off the stream with **Edit**, or connect the store again and allow it |
| Bite asked sanda to slow down | Nothing to do: the run waits as Bite asks, then carries on |
| Bite didn't answer, or answered with an error of its own | Nothing to do: the run tries again, and the next run carries on from the last page that landed |

A failed run counts toward the stream pausing itself, as any stream's does. See [runs](https://docs.sanda-os.com.au/streams/runs).

## Limits

- A run makes at most 2 requests a second, because a store's allowance with Bite is shared with every other app it has connected. Each request asks for up to 250 records.
- **Read history from** goes back to 1 January 2015 at the earliest.
- One run lands at most 5,000,000 records, so a long history is several runs.

A Bite stream is billed like any pull: a charge for each run that does its work, and the rows it lands past what your edition includes. See [what streams cost](https://docs.sanda-os.com.au/streams#what-streams-cost).

:::links
- [Pull](https://docs.sanda-os.com.au/streams/in): Every way records come into your warehouse on a stream.
- [Stream graphs](https://docs.sanda-os.com.au/streams/graphs): Model what a stream lands, then send the result out, every time it lands.
- [Runs](https://docs.sanda-os.com.au/streams/runs): What each run did, and what to do when one fails.
:::
