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

# Authentication

> Authenticate Cludo API requests using HTTP Basic credentials or a SiteKey, including when to use each method and how to send the Authorization header.

export const ApiTokenBuilder = () => {
  const [authType, setAuthType] = useState("basic");
  const [customerId, setCustomerId] = useState("");
  const [engineId, setEngineId] = useState("");
  const [apiKey, setApiKey] = useState("");
  const [copiedHeader, setCopiedHeader] = useState(false);
  const [copiedCurl, setCopiedCurl] = useState(false);
  const siteKeyBase64 = typeof btoa !== "undefined" && customerId && engineId ? btoa(`${customerId}:${engineId}:SearchKey`) : "";
  const basicBase64 = typeof btoa !== "undefined" && customerId && apiKey ? btoa(`${customerId}:${apiKey}`) : "";
  const headerValue = authType === "sitekey" ? siteKeyBase64 ? "SiteKey " + siteKeyBase64 : "" : basicBase64 ? "Basic " + basicBase64 : "";
  const baseUrl = Number(customerId) >= 10000000 ? "https://api-us1.cludo.com" : "https://api.cludo.com";
  const pathCustomerId = customerId.trim() || "<customer-id>";
  const pathEngineId = engineId.trim() || "<engine-id>";
  const authForCurl = authType === "sitekey" ? siteKeyBase64 ? "SiteKey " + siteKeyBase64 : "SiteKey <your-sitekey-token>" : basicBase64 ? "Basic " + basicBase64 : "Basic <your-basic-token>";
  const curlCmd = 'curl -X POST "' + baseUrl + "/api/v4/" + pathCustomerId + "/" + pathEngineId + '/search" \\\n' + '  -H "Authorization: ' + authForCurl + '" \\\n' + '  -H "Content-Type: application/json" \\\n' + "  -d '{\"query\": \"*\", \"page\": 1, \"perPage\": 10}'";
  const copyToClipboard = (text, setter) => {
    if (typeof navigator !== "undefined" && navigator.clipboard) {
      navigator.clipboard.writeText(text).then(() => {
        setter(true);
        setTimeout(() => setter(false), 2000);
      });
    }
  };
  const btnBase = "px-3 py-1.5 rounded-lg text-sm font-medium transition-colors";
  const btnActive = btnBase + " bg-primary text-white";
  const btnInactive = btnBase + " bg-zinc-950/10 dark:bg-white/10 text-zinc-950/80 dark:text-white/80 hover:bg-zinc-950/20 dark:hover:bg-white/20";
  return <div className="p-4 border border-zinc-950/20 dark:border-white/20 rounded-2xl not-prose space-y-4">
      <div className="flex flex-wrap gap-2">
        <button type="button" onClick={() => setAuthType("basic")} className={authType === "basic" ? btnActive : btnInactive}>
          Basic (API Key)
        </button>
        <button type="button" onClick={() => setAuthType("sitekey")} className={authType === "sitekey" ? btnActive : btnInactive}>
          SiteKey (Search)
        </button>
      </div>

      {authType === "sitekey" ? <>
          <div className="grid gap-3 sm:grid-cols-2">
            <label className="block text-sm text-zinc-950/70 dark:text-white/70">
              Customer ID
              <input type="text" value={customerId} onChange={e => setCustomerId(e.target.value)} placeholder="e.g. 10" className="mt-1 w-full rounded-lg border border-zinc-950/20 dark:border-white/20 bg-white dark:bg-zinc-950/50 px-3 py-2 text-sm" />
            </label>
            <label className="block text-sm text-zinc-950/70 dark:text-white/70">
              Engine ID
              <input type="text" value={engineId} onChange={e => setEngineId(e.target.value)} placeholder="e.g. 6" className="mt-1 w-full rounded-lg border border-zinc-950/20 dark:border-white/20 bg-white dark:bg-zinc-950/50 px-3 py-2 text-sm" />
            </label>
          </div>
          <p className="text-xs text-zinc-950/50 dark:text-white/50">
            The token always includes the literal string <code className="font-mono">SearchKey</code> as the third component.
          </p>
        </> : <div className="grid gap-3 sm:grid-cols-2">
          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Customer ID
            <input type="text" value={customerId} onChange={e => setCustomerId(e.target.value)} placeholder="e.g. 3" className="mt-1 w-full rounded-lg border border-zinc-950/20 dark:border-white/20 bg-white dark:bg-zinc-950/50 px-3 py-2 text-sm" />
          </label>
          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            API Key
            <input type="text" value={apiKey} onChange={e => setApiKey(e.target.value)} placeholder="your-api-key" className="mt-1 w-full rounded-lg border border-zinc-950/20 dark:border-white/20 bg-white dark:bg-zinc-950/50 px-3 py-2 text-sm font-mono" />
          </label>
        </div>}

      <div className="space-y-1">
        <p className="text-sm text-zinc-950/70 dark:text-white/70">
          Authorization header value:
        </p>
        <div className="flex items-center gap-2">
          <code className="flex-1 rounded-lg bg-zinc-950/10 dark:bg-white/10 px-3 py-2 text-sm font-mono break-all">
            {headerValue || "—"}
          </code>
          <button type="button" onClick={() => copyToClipboard(headerValue, setCopiedHeader)} disabled={!headerValue} className="shrink-0 rounded-lg border border-zinc-950/20 dark:border-white/20 px-3 py-2 text-sm hover:bg-zinc-950/10 dark:hover:bg-white/10 disabled:opacity-40 disabled:pointer-events-none">
            {copiedHeader ? "Copied!" : "Copy"}
          </button>
        </div>
      </div>

      <div className="space-y-1">
        <p className="text-sm text-zinc-950/70 dark:text-white/70">
          Ready-to-run cURL:
        </p>
        <pre className="rounded-lg bg-zinc-950/10 dark:bg-white/10 p-3 text-xs font-mono overflow-x-auto whitespace-pre-wrap">
          {curlCmd}
        </pre>
        <button type="button" onClick={() => copyToClipboard(curlCmd, setCopiedCurl)} className="rounded-lg border border-zinc-950/20 dark:border-white/20 px-3 py-1.5 text-sm hover:bg-zinc-950/10 dark:hover:bg-white/10">
          {copiedCurl ? "Copied!" : "Copy cURL"}
        </button>
      </div>
    </div>;
};

The Cludo API supports two authentication schemes. Which one to use depends on where the request is made and which endpoint you call.

| Scheme              | Use case                                                                                                   |
| ------------------- | ---------------------------------------------------------------------------------------------------------- |
| **Basic (API Key)** | Default for API requests, server-side integrations, index management, crawler URL queues, and search tools |
| **SiteKey**         | Public client-side search where an API key must not be exposed                                             |

<Info>
  Unless an endpoint says otherwise, use Basic authentication. SiteKey is only intended for browser-facing search integrations.
</Info>

***

## Basic (API Key) aauthentication

Used for API requests from a trusted backend, scripts, and integrations. Use Basic authentication for index management, crawler URL queues, search tools, and any endpoint where you can keep the API key private.

### Building the token

```bash theme={null}
# Format: base64(customerId:apiKey)
echo -n "3:c8fk2L9mK4pQ" | base64
# MzpjOGZrMkw5bUs0cFE=
```

<CodeGroup>
  ```bash cURL theme={null}
  # Use https://api-us1.cludo.com for the US region
  curl -X POST "https://api.cludo.com/api/v4/3/6/search" \
    -H "Authorization: Basic MzpjOGZrMkw5bUs0cFE=" \
    -H "Content-Type: application/json" \
    -d '{"query": "test"}'
  ```

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

  # Use https://api-us1.cludo.com for the US region
  url = "https://api.cludo.com/api/v4/3/6/search"
  headers = {
      "Authorization": "Basic MzpjOGZrMkw5bUs0cFE=",
      "Content-Type": "application/json",
  }

  response = requests.post(url, json={"query": "test"}, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  // Use https://api-us1.cludo.com for the US region
  const response = await fetch("https://api.cludo.com/api/v4/3/6/search", {
    method: "POST",
    headers: {
      "Authorization": "Basic MzpjOGZrMkw5bUs0cFE=",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query: "test" }),
  });

  const data = await response.json();
  console.log(data);
  ```

  ```typescript TypeScript theme={null}
  // Use https://api-us1.cludo.com for the US region
  const response = await fetch("https://api.cludo.com/api/v4/3/6/search", {
    method: "POST",
    headers: {
      "Authorization": "Basic MzpjOGZrMkw5bUs0cFE=",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query: "test" }),
  });

  const data: unknown = await response.json();
  console.log(data);
  ```
</CodeGroup>

### Where to find your credentials

Log in to [MyCludo](https://my.cludo.com) and navigate to **Account Settings** to find your Customer ID and API key.

***

## SiteKey aauthentication

Used for public website search widgets and other client-side search integrations. SiteKey authentication exists so browser code can call search-related endpoints without exposing your API key.

### Building the token

```bash theme={null}
# Format: base64(customerId:engineId:SearchKey)
# "SearchKey" is a fixed, literal string. Do not replace it with a value.
echo -n "3:6:SearchKey" | base64
# Mzo2OlNlYXJjaEtleQ==
```

<Warning>
  A SiteKey is tied to one specific engine. You cannot use a SiteKey from one engine to authenticate requests to another engine.
</Warning>

<CodeGroup>
  ```bash cURL theme={null}
  # Use https://api-us1.cludo.com for the US region
  curl -X POST "https://api.cludo.com/api/v4/3/6/search" \
    -H "Authorization: SiteKey Mzo2OlNlYXJjaEtleQ==" \
    -H "Content-Type: application/json" \
    -d '{"query": "test"}'
  ```

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

  # Use https://api-us1.cludo.com for the US region
  url = "https://api.cludo.com/api/v4/3/6/search"
  headers = {
      "Authorization": "SiteKey Mzo2OlNlYXJjaEtleQ==",
      "Content-Type": "application/json",
  }

  response = requests.post(url, json={"query": "test"}, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  // Use https://api-us1.cludo.com for the US region
  const response = await fetch("https://api.cludo.com/api/v4/3/6/search", {
    method: "POST",
    headers: {
      "Authorization": "SiteKey Mzo2OlNlYXJjaEtleQ==",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query: "test" }),
  });

  const data = await response.json();
  console.log(data);
  ```

  ```typescript TypeScript theme={null}
  // Use https://api-us1.cludo.com for the US region
  const response = await fetch("https://api.cludo.com/api/v4/3/6/search", {
    method: "POST",
    headers: {
      "Authorization": "SiteKey Mzo2OlNlYXJjaEtleQ==",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query: "test" }),
  });

  const data: unknown = await response.json();
  console.log(data);
  ```
</CodeGroup>

***

## Try it: build your token

Use the tool below to generate your SiteKey or Basic authorization header and a ready-to-run cURL command. Switch between **SiteKey** and **Basic** to see the correct prefix for each scheme.

<ApiTokenBuilder />
