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

# Authentication

> Configure the YoukaClient with your API key

The SDK authenticates every request with a bearer API key. You construct a `YoukaClient` once and reuse it for the lifetime of your process.

## `new YoukaClient(options)`

```ts theme={null}
import { YoukaClient } from "@youka/sdk";

const client = new YoukaClient({
  apiKey: process.env.YOUKA_API_KEY!,
});
```

### Options

<ParamField path="apiKey" type="string" required>
  Your Youka API key. Create one at
  [online.youka.io/account](https://online.youka.io/account) under **API keys**.
</ParamField>

<ParamField path="fetch" type="typeof fetch">
  Custom `fetch` implementation. Defaults to the global `fetch`. Use this to
  inject logging, proxies, or custom retry middleware.
</ParamField>

## Storing the API key

<Warning>
  API keys grant access to your billing. Never commit them to source control.
</Warning>

Recommended patterns:

<Tabs>
  <Tab title="Environment variable">
    ```ts theme={null}
    const client = new YoukaClient({
      apiKey: process.env.YOUKA_API_KEY!,
    });
    ```
  </Tab>

  <Tab title="Secret manager">
    ```ts theme={null}
    import { getSecret } from "./my-secret-manager";

    const client = new YoukaClient({
      apiKey: await getSecret("youka-api-key"),
    });
    ```
  </Tab>
</Tabs>

## Injecting a custom fetch

Every SDK method uses the `fetch` you pass to the constructor. This makes it easy to add logging or middleware:

```ts theme={null}
import { YoukaClient } from "@youka/sdk";

const instrumentedFetch: typeof fetch = async (input, init) => {
  const start = Date.now();
  const response = await fetch(input, init);
  console.log(
    `${init?.method ?? "GET"} ${input} ${response.status} in ${Date.now() - start}ms`,
  );
  return response;
};

const client = new YoukaClient({
  apiKey: process.env.YOUKA_API_KEY!,
  fetch: instrumentedFetch,
});
```

## Per-request options

Every method accepts an optional second or third argument with request-level options:

```ts theme={null}
await client.projects.create(body, {
  idempotencyKey: "import-2026-04-08-song-001",
  signal: abortController.signal,
});
```

<ParamField path="idempotencyKey" type="string">
  Passed as the `Idempotency-Key` header. Reusing the same key with the same
  payload returns the original result instead of creating a duplicate. See [API
  idempotency](/en/api/idempotency).
</ParamField>

<ParamField path="signal" type="AbortSignal">
  Standard abort signal. Cancels in-flight requests and long-running
  `client.tasks.wait(...)`, `client.projects.wait(...)`, and
  `client.exports.wait(...)` polls.
</ParamField>

## What's next

* [Projects](/en/sdk/projects) — create your first project
* [Errors](/en/sdk/errors) — handle authentication failures
* [API authentication](/en/api/authentication) — raw HTTP header details
