---
title: Quickstart
description: Create a key, make your first call, and read the response.
icon: rocket
sidebar:
  order: 1
---

Everything lives under `https://app.bloomcount.com/api/v1`, speaks JSON, and
authenticates with a bearer token.

1. **Create an API key**

    In the app, open **Settings → API** and create a key. Tick only the scopes the
    integration needs: a key without `products:write` cannot create products, and a
    key with no scope for a resource cannot read it either.

    The key is shown **once**, at creation. It looks like `bloomcount_` followed by
    48 hex characters. Store it where your server can read it and nobody else can.

2. **Make a call**

    List a few products, asking for two fields so the response is easy to read:

    <CodeGroup>

    ```bash curl
    curl "https://app.bloomcount.com/api/v1/products?limit=3&fields=name,category" \
      -H "Authorization: Bearer bloomcount_..."
    ```

    ```js JavaScript
    const res = await fetch(
      "https://app.bloomcount.com/api/v1/products?limit=3&fields=name,category",
      { headers: { Authorization: `Bearer ${process.env.BLOOMCOUNT_API_KEY}` } },
    );
    const { items } = await res.json();
    ```

    ```python Python
    import os, requests

    res = requests.get(
        "https://app.bloomcount.com/api/v1/products",
        params={"limit": 3, "fields": "name,category"},
        headers={"Authorization": f"Bearer {os.environ['BLOOMCOUNT_API_KEY']}"},
    )
    items = res.json()["items"]
    ```

    </CodeGroup>

3. **Read the response**

    Every list endpoint returns the same envelope: the rows in `items`, plus
    `isDone` and `cursor` for paging.

    ```json
    {
      "items": [
        {
          "productId": "prod_h71eaa8d4mr3vk2qz9pn5wf",
          "name": "Rose",
          "category": "Roses"
        }
      ],
      "isDone": false,
      "cursor": "..."
    }
    ```

    The id came back even though it was not asked for, because it always does. Pass
    `cursor` back as a query parameter for the next page, and stop when `isDone` is
    `true`.

## What to read next

**[Authentication](/authentication)**

Scopes, rate limits, and idempotent retries.

**[Conventions](/conventions)**

Bulk writes, prefixed ids, and asking for fewer fields.

**[Guides](/guides/catalogue-sync)**

Tasks that span several calls: catalogue, events, hire.

**[Errors](/errors)**

Every code the API returns and what to do about it.

:::tip[Trying it from these pages]
Every endpoint page has a **Try it** panel. Paste a key into it and the request
runs against your own tenant, so the response you see is your data.
:::
