For the complete documentation index, see llms.txt. This page is also available as Markdown.

Authentication

How to authenticate with the relayer using a backend proxy or a direct API key.

The Zama-hosted mainnet relayer requires an API key on every request. The Sepolia testnet relayer is open — it needs no key, so on testnet you can leave auth unset and skip this guide. This page covers the two strategies for the mainnet relayer (or any keyed endpoint): proxying through your backend (recommended for browser apps) and passing the key directly (suitable for server-side apps).

Building on Sepolia testnet? You don't need an API key — the sepolia preset works out of the box. API keys apply only to the Zama-hosted mainnet relayer; see Relayer API keys to apply for one (or self-host instead).

Steps

1. Understand the two options

Strategy
Use when
API key location

Backend proxy

Browser apps, dApps

Server-side only — never sent to the client

Direct API key

Node.js scripts, backend services, prototyping

Passed in the auth field of the transport config

Browser apps should always use a proxy. Embedding the API key in client-side code exposes it to anyone inspecting network traffic or your bundle.

Server-side apps (Node.js scripts, backend services) can safely use a direct API key since the code runs in a trusted environment where secrets are not exposed to end users.

2. Set up a backend proxy

Create an endpoint that forwards relayer requests and injects the API key. Store your credentials in environment variables:

RELAYER_API_KEY=your-api-key

Here is a minimal Express proxy:

import express from "express";
import { mainnet, sepolia } from "@zama-fhe/sdk/chains";

const app = express();
app.use(express.json());

// Map chain IDs to their network config
const Configs: Record<number, typeof mainnet> = { [mainnet.id]: mainnet, [sepolia.id]: sepolia };

app.use("/api/relayer/:chainId", async (req, res) => {
  const config = Configs[Number(req.params.chainId)];
  if (!config) {
    res.status(400).send("Unsupported chain");
    return;
  }

  const url = new URL(req.url, config.relayerUrl);
  const body = ["GET", "HEAD"].includes(req.method) ? undefined : JSON.stringify(req.body);

  const response = await fetch(url, {
    method: req.method,
    headers: { "content-type": "application/json", "x-api-key": process.env.RELAYER_API_KEY! },
    body,
    // @ts-expect-error: required by the relayer
    duplex: "half",
  });

  res.status(response.status).send(await response.text());
});

app.listen(3001);

The proxy adds the x-api-key header to every forwarded request. Your frontend never sees the key.

You can adapt this pattern to any server framework (Fastify, Hono, Next.js API routes, etc.). The key requirements are:

  • Forward the HTTP method, path, and body to the upstream relayer URL

  • Inject the x-api-key header before forwarding

  • Return the upstream response status and body to the client

3. Configure the SDK to use your proxy

Point the relayerUrl at your backend endpoint instead of the relayer directly:

No auth field is needed on the client side — the proxy handles authentication transparently. The SDK sends requests to your proxy URL, and your proxy appends the API key before forwarding to the relayer.

4. (Alternative) Use a direct API key for server-side apps

When the SDK runs in a trusted environment (Node.js script, backend service), you can pass the API key directly on the chain definition:

Then pass mySepolia to createConfig — the auth field is picked up automatically by the relayer. See the Node.js backend guide for a complete example.

The auth field supports multiple methods depending on how your relayer is configured.

5. Auth methods reference

The auth field accepts three formats. Which one to use depends on where your relayer lives — the transport has to match what your relayer (or the auth layer in front of it) expects.

Method
How it's sent
Use it when

ApiKeyHeader

x-api-key: key header

Zama-hosted relayer — required; it only accepts the key in the x-api-key header. Also the default for most setups.

ApiKeyCookie

x-api-key=key cookie

Behind your own proxy — authenticate the SDK→proxy hop with a cookie; your proxy then injects x-api-key upstream.

BearerToken

Authorization: Bearer <token>

Self-hosted relayer — only if your own auth layer expects a bearer token.

When using RelayerWeb with a proxy, you can also add CSRF protection via the security.getCsrfToken callback. See the RelayerWeb reference for details.

Next steps

Last updated