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

# Authentication

> How to pass your API key to the SDK and override the base URL.

The Spine API uses API keys sent as the `X-API-KEY` request header. The
SDK adds the header for you on every request — you just need to give it
a key.

## Passing the key

<CodeGroup>
  ```ts Environment variable (preferred) theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
  // Shell:
  // export SPINE_API_KEY=sk_spine_...

  import { Spine } from 'spine-sdk';

  const client = new Spine({ apiKey: process.env.SPINE_API_KEY! });
  ```

  ```ts Explicit argument theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
  import { Spine } from 'spine-sdk';

  const client = new Spine({ apiKey: 'sk_spine_...' });
  ```
</CodeGroup>

<Warning>
  Never commit keys to source control. Use your deployment platform's
  secret manager (AWS Secrets Manager, 1Password, Doppler, etc.) and
  inject them at runtime. Never ship keys to the browser — proxy requests
  through your own backend instead.
</Warning>

If `apiKey` is falsy, the `Spine` constructor throws immediately — before
any network call.

## Key rotation

Keys revoked in the dashboard stop working on the next request; you'll
see `SpineAuthError` thrown from the SDK. Roll new keys through your
secret store before revoking the old one so running processes don't
break mid-run. The server caches keys for up to 5 minutes, so leave that
grace window.

## Overriding the base URL

Point the SDK at a staging or enterprise deployment via `baseURL`:

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const client = new Spine({
  apiKey: process.env.SPINE_API_KEY!,
  baseURL: 'https://staging.getspine.ai',
});
```

The SDK appends `/v1` paths automatically, so pass the host without the
API prefix.

## Tuning timeouts and retries

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const client = new Spine({
  apiKey: process.env.SPINE_API_KEY!,
  timeoutMs: 60_000,   // per-request timeout (default: 60_000)
  maxRetries: 2,       // transient 5xx / network retries (default: 2)
});
```

See [Errors and retries](/sdks/typescript/errors) for the retry policy.

## Injecting your own fetch

For advanced cases (custom proxies, test doubles, alternative runtimes),
pass a pre-configured `fetch` implementation. The SDK still applies
`X-API-KEY` and `User-Agent` headers — your implementation does not need
to set them.

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
import undici from 'undici';

const client = new Spine({
  apiKey: process.env.SPINE_API_KEY!,
  fetch: undici.fetch as typeof fetch,
});
```

## Observing requests

Use `onRequest` and `onResponse` for tracing every call:

```ts theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
const client = new Spine({
  apiKey: process.env.SPINE_API_KEY!,
  onRequest: ({ method, url }) => console.debug('[spine]', method, url),
  onResponse: ({ status, durationMs }) =>
    console.debug('[spine]', status, `${durationMs}ms`),
});
```
