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

# Add an API key for legacy gateways

> Migrate a self-hosted squid from keyless v2 gateway access to a v2 gateway API key.

Since **May 19th 2026, 12:00 UTC**, accessing legacy centralized gateways (a.k.a. v2 archives — URLs
starting with `https://v2.archive.subsquid.io`) **when self-hosting** requires an API key. This
guide takes a squid that reaches such a gateway without a key and adds one.

<Note>
  This affects **self-hosted** squids only. [SQD Cloud](/en/cloud/overview) deployments relying on
  legacy gateways are unaffected — the platform supplies gateway access.
</Note>

## Does this apply to my squid?

Look at your processor / data source configuration:

* **`.setGateway(...)`** → you need a key. This is the case for Substrate (`SubstrateBatchProcessor`),
  Tron (`TronBatchProcessor`), and any EVM/Solana squid still on a legacy gateway.
* **`.setPortal(...)`** (Portal-based) or **neither `.setGateway()` nor `.setPortal()`** (RPC-only) →
  nothing to do; those paths don't use a v2 gateway.

<Tip>
  On EVM and Solana you can avoid keys entirely by moving historical ingestion to a public Portal —
  see [Migrate a squid to Portal](/en/sdk/migration/gateway-to-portal). Portal is public and needs no
  key. Substrate and Tron have no Portal dataset, so a gateway key is the way forward for them.
</Tip>

<Steps>
  <Step title="Get an API key">
    Register and create a gateway API key at [portal.sqd.dev/app](https://portal.sqd.dev/app):

    <Card title="The API keys app" icon="key" href="https://portal.sqd.dev/app">
      Register and create your gateway API key
    </Card>

    (The same app will also issue Portal API keys in the near future.)
  </Step>

  <Step title="Update @subsquid packages">
    <Tabs>
      <Tab title="NPM">
        ```bash theme={"system"}
        npx --yes npm-check-updates --filter '@subsquid/*' --target semver --upgrade && npm i
        ```
      </Tab>

      <Tab title="PNPM">
        ```bash theme={"system"}
        npx --yes npm-check-updates --filter '@subsquid/*' --target semver --upgrade && pnpm i
        ```
      </Tab>

      <Tab title="Yarn">
        ```bash theme={"system"}
        npx --yes npm-check-updates --filter '@subsquid/*' --target semver --upgrade && yarn
        ```
      </Tab>

      <Tab title="Bun">
        ```bash theme={"system"}
        npx --yes npm-check-updates --filter '@subsquid/*' --target semver --upgrade && bun i
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Supply the key">
    The processor reads the key from the `SQD_API_KEY` environment variable by default, so the
    simplest option needs **no code change** — set it in your `.env`:

    ```bash title=".env" theme={"system"}
    SQD_API_KEY=your_api_key
    ```

    Under the hood the gateway client resolves the key as `options.apiKey ?? process.env.SQD_API_KEY`
    (in `@subsquid/util-internal-archive-client`), so the env variable is picked up automatically
    whether you pass a bare URL or a settings object to `.setGateway(...)`.

    If you prefer to pass it explicitly (e.g. to read it from a different variable), give
    `.setGateway(...)` a settings object instead of a URL string:

    ```diff theme={"system"}
    -  .setGateway('https://v2.archive.subsquid.io/network/ethereum-mainnet')
    +  .setGateway({
    +    url: 'https://v2.archive.subsquid.io/network/ethereum-mainnet',
    +    apiKey: process.env.SQD_API_KEY,
    +  })
    ```

    <Warning>
      Keep the key out of source control — read it from the environment (`.env` locally, a
      [secret](/en/cloud/resources/env-variables#secrets) in Cloud), never hard-code it.
    </Warning>
  </Step>
</Steps>

Done. Your self-hosted squid will keep reaching the legacy gateway once keyless access is switched
off. If the key is missing, the processor logs a one-time warning and gateway requests will start
failing with an authentication error.
