> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blockworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Get an API key, find an asset with unlock coverage, and pull its next cliff and its supply schedule.

This page gets you a key and a first Token Unlocks response, then builds the two queries most
people want: the next cliff, and how much supply unlocks per month. The key is the same one
that authenticates every Blockworks product, so if you already have one you can skip the first
step.

<Steps>
  <Step title="Get an API key">
    Create a key at [app.blockworks.com/account/api](https://app.blockworks.com/account/api).

    Keys are shown once at creation. Store yours in a secret manager or environment
    variable, and never commit it or send it from a browser.

    ```bash theme={null}
    export BLOCKWORKS_API_KEY="your-api-key"
    ```
  </Step>

  <Step title="Find an asset with coverage">
    All Token Unlocks endpoints live under `/token-unlocks/v1` on the shared Blockworks API
    host, and every one of them requires the `X-Blockworks-API-Key` header. Start with the
    list of covered assets, narrowed to a category.

    <CodeGroup>
      ```bash curl theme={null}
      curl "https://api.blockworks.com/token-unlocks/v1/assets?category=Networks" \
        -H "X-Blockworks-API-Key: $BLOCKWORKS_API_KEY"
      ```

      ```python Python theme={null}
      import os
      import requests

      response = requests.get(
          "https://api.blockworks.com/token-unlocks/v1/assets",
          params={"category": "Networks"},
          headers={"X-Blockworks-API-Key": os.environ["BLOCKWORKS_API_KEY"]},
          timeout=30,
      )
      response.raise_for_status()

      assets = response.json()["data"] or []
      for asset in sorted(assets, key=lambda a: a["symbol"]):
          print(asset["symbol"], asset["slug"], asset["projectedEndDate"])
      ```

      ```javascript JavaScript theme={null}
      const url = new URL("https://api.blockworks.com/token-unlocks/v1/assets");
      url.searchParams.set("category", "Networks");

      const response = await fetch(url, {
        headers: { "X-Blockworks-API-Key": process.env.BLOCKWORKS_API_KEY },
      });
      if (!response.ok) throw new Error(`Request failed: ${response.status}`);

      const { data } = await response.json();
      for (const asset of (data ?? []).sort((a, b) => a.symbol.localeCompare(b.symbol))) {
        console.log(asset.symbol, asset.slug, asset.projectedEndDate);
      }
      ```
    </CodeGroup>

    Filters combine as AND across parameters and OR within one, so
    `?category=Networks&tags=Proof-of-Stake` is proof-of-stake networks, while
    `?tags=EVM,Proof-of-Stake` is either tag. Note the two things that differ from most list
    endpoints: `page` and `limit` are accepted but not applied, so you always get the full
    matching set, and the result is unordered, which is why the examples sort before printing.
  </Step>

  <Step title="Read the response">
    Token Unlocks responses use the same envelope as every Blockworks API: `error` is `null`
    on success and a string on failure, and `data` carries the payload.

    ```json theme={null}
    {
      "error": null,
      "data": [
        {
          "id": "b3d5d66c-26a2-404c-9325-91dc714a722b",
          "serialId": 6079,
          "symbol": "SOL",
          "name": "Solana",
          "genesisDate": "2020-04-07T00:00:00Z",
          "projectedEndDate": "2029-03-01T00:00:00Z",
          "slug": "solana",
          "category": "Networks",
          "sector": "Smart Contract Platform",
          "tags": [
            "Proof-of-Stake",
            "SEC Alleged Securities",
            "Stakeable"
          ],
          "otherInfo": "Tokens allocated to inflationary categories (Validator Rewards) are not accounted for in the unlock data below. "
        }
      ]
    }
    ```

    <Warning>
      An empty result is `"data": null`, not `[]`, and it arrives with a `200`. Both examples
      above fall back to an empty list for exactly this reason.
    </Warning>

    Two fields are worth reading before you trust a schedule. `otherInfo` is `null` for most
    assets, but when it is set it records an analyst caveat about incomplete coverage.
    `projectedEndDate` equal to `genesisDate` means the allocation unlocked at genesis, not
    that data is missing.
  </Step>

  <Step title="Find the next cliff">
    Unlock events are the dated points where a schedule changes. Filter to `CLIFF` and a
    forward window to get the discrete releases ahead.

    <CodeGroup>
      ```bash curl theme={null}
      curl "https://api.blockworks.com/token-unlocks/v1/assets/solana/events?unlockType=CLIFF&startTime=2026-01-01T00:00:00Z&endTime=2027-01-01T00:00:00Z" \
        -H "X-Blockworks-API-Key: $BLOCKWORKS_API_KEY"
      ```

      ```python Python theme={null}
      import os
      import requests

      response = requests.get(
          "https://api.blockworks.com/token-unlocks/v1/assets/solana/events",
          params={
              "unlockType": "CLIFF",
              "startTime": "2026-01-01T00:00:00Z",
              "endTime": "2027-01-01T00:00:00Z",
          },
          headers={"X-Blockworks-API-Key": os.environ["BLOCKWORKS_API_KEY"]},
          timeout=30,
      )
      response.raise_for_status()

      events = (response.json()["data"] or {}).get("unlockEvents", [])
      for event in events[:5]:
          cliff = event["cliff"]
          recipients = ", ".join(a["allocationRecipient"] for a in cliff["allocations"])
          print(f"{event['timestamp']} {cliff['amountNative']:,.0f} native to {recipients}")
      ```
    </CodeGroup>

    Each event carries either a `cliff` or a `dailyLinearRateChange`, and the other field is
    `null`. Both shapes report `amountNative`, `amountUSD`, `percentOfTotalAllocation`, and a
    per-recipient `allocations` breakdown. Drop `unlockType` to get both kinds in one call.
  </Step>

  <Step title="Chart supply pressure">
    The unlocks timeseries buckets released tokens by interval. `interval` is required and
    takes `DAILY`, `WEEKLY`, `MONTHLY`, `QUARTERLY`, or `YEARLY`.

    <CodeGroup>
      ```bash curl theme={null}
      curl "https://api.blockworks.com/token-unlocks/v1/assets/solana/unlocks?interval=MONTHLY&startTime=2026-01-01T00:00:00Z&endTime=2026-07-01T00:00:00Z" \
        -H "X-Blockworks-API-Key: $BLOCKWORKS_API_KEY"
      ```

      ```python Python theme={null}
      import os
      import requests

      response = requests.get(
          "https://api.blockworks.com/token-unlocks/v1/assets/solana/unlocks",
          params={
              "interval": "MONTHLY",
              "startTime": "2026-01-01T00:00:00Z",
              "endTime": "2026-07-01T00:00:00Z",
          },
          headers={"X-Blockworks-API-Key": os.environ["BLOCKWORKS_API_KEY"]},
          timeout=30,
      )
      response.raise_for_status()

      data = response.json()["data"]
      for snapshot in data["totalSnapshots"]:
          print(snapshot["timestamp"], round(snapshot["unlockedInPeriodUSD"]))

      # The same series, split by who receives the tokens.
      for allocation in data["allocations"]:
          released = sum(s["unlockedInPeriodNative"] for s in allocation["dailySnapshots"])
          print(allocation["allocationRecipient"], round(released))
      ```
    </CodeGroup>

    These snapshots are flow: each one covers its own interval and carries no running total.
    For cumulative state (how much has vested, how much remains, percent complete per day),
    use [Get Vesting Schedule](/api-reference/token-unlocks/get-v1-assets-assetId-vesting-schedule)
    instead. The per-recipient arrays are named `dailySnapshots` on both endpoints, even when
    you requested a coarser interval.
  </Step>
</Steps>

## Next steps

<CardGroup cols={2}>
  <Card title="Allocations" icon="chart-pie" href="/api-reference/token-unlocks/get-v1-allocations">
    Totals per recipient, with the analyst description, assumptions, and sources behind each
    tranche.
  </Card>

  <Card title="Vesting schedule" icon="chart-line" href="/api-reference/token-unlocks/get-v1-assets-assetId-vesting-schedule">
    Daily cumulative unlocked, remaining, and percent complete, in total and per recipient.
  </Card>

  <Card title="Concepts and caveats" icon="book-open" href="/api-reference/token-unlocks/overview">
    Flow against stock, identifier rules, and the coverage caveats worth knowing.
  </Card>

  <Card title="Errors" icon="alert-triangle" href="/getting-started/errors">
    Status codes and the shared error envelope.
  </Card>
</CardGroup>
