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

# configure()

> The API key never enters your application's memory — in development or in production.

`configure()` is the only function you need for HTTP API keys. It returns a config object ready to spread into any provider SDK constructor. The key is **never in your process** — in development, it stays in the local proxy; in production, it is injected by the Elding cloud proxy server-side.

```js theme={null}
import OpenAI from "openai";
import { configure } from "@elding/sdk";

const openai = new OpenAI(
  await configure("OPENAI_API_KEY", "https://api.openai.com")
);
```

The same line works in development and in production. No `if (process.env.NODE_ENV)`. No change between environments.

***

## How it works

`configure()` returns `{ apiKey, baseURL, defaultHeaders }`. What those fields contain depends on the environment.

<CardGroup cols={3}>
  <Card title="Development" icon="laptop">
    Requires `elding proxy` running. `apiKey` is a placeholder (`{{OPENAI_API_KEY}}`). Requests go through the local proxy at `127.0.0.1`, which injects the real key. The key never touches your process.
  </Card>

  <Card title="Production" icon="cloud">
    Requires `ELDING_REFRESH_TOKEN` and `ELDING_SET_ID`. `apiKey` is a deploy token. Requests go through `elding.app/api/proxy`, which injects the real key server-side. The key never touches your process.
  </Card>

  <Card title="Fallback" icon="server">
    No proxy active, no deploy token. The SDK fetches the raw key from the vault and returns it as `apiKey`. The key enters memory. Not recommended for production.
  </Card>
</CardGroup>

In both the development and production modes, the API key is **injected at the proxy level** — your application code, your logs, and your AI agent never see it.

***

## Parameters

| Parameter    | Type            | Required | Description                                                       |
| ------------ | --------------- | -------- | ----------------------------------------------------------------- |
| `secretName` | `string`        | Yes      | Name of the key in the vault (`A-Z`, `0-9`, `_`).                 |
| `target`     | `string`        | Yes      | HTTPS base URL of the provider (e.g. `"https://api.openai.com"`). |
| `options`    | `ClientOptions` | No       | Override `refreshToken`, `setId`, or `cacheTtlMs`.                |

***

## Return value

`configure()` always returns `Promise<{ apiKey, baseURL, defaultHeaders }>`.

| Field            | In development                   | In production                                    |
| ---------------- | -------------------------------- | ------------------------------------------------ |
| `apiKey`         | `{{OPENAI_API_KEY}}` placeholder | deploy token                                     |
| `baseURL`        | `http://127.0.0.1:{port}/`       | `https://elding.app/api/proxy/api.openai.com`    |
| `defaultHeaders` | proxy routing headers            | `x-elding-token`, `x-elding-key`, `x-elding-set` |

Spread directly into the provider constructor — it picks up exactly what it needs.

***

## Provider examples

### OpenAI

```js theme={null}
import OpenAI from "openai";
import { configure } from "@elding/sdk";

const openai = new OpenAI(
  await configure("OPENAI_API_KEY", "https://api.openai.com")
);

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: "Hello" }],
});
```

### Anthropic

```js theme={null}
import Anthropic from "@anthropic-ai/sdk";
import { configure } from "@elding/sdk";

const anthropic = new Anthropic(
  await configure("ANTHROPIC_API_KEY", "https://api.anthropic.com")
);
```

### Mistral / Together AI / any OpenAI-compatible API

```js theme={null}
import OpenAI from "openai";
import { configure } from "@elding/sdk";

const mistral = new OpenAI(
  await configure("MISTRAL_API_KEY", "https://api.mistral.ai")
);
```

### Custom `fetch`

Destructure the result and pass all three fields:

```js theme={null}
import { configure } from "@elding/sdk";

const { apiKey, baseURL, defaultHeaders } = await configure(
  "RESEND_API_KEY",
  "https://api.resend.com"
);

const res = await fetch(`${baseURL}/emails`, {
  method: "POST",
  headers: {
    ...defaultHeaders,
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ from: "...", to: "...", subject: "...", html: "..." }),
});
```

<Warning>
  Always spread `defaultHeaders` before your own headers. They carry the proxy routing tokens — without them, the request won't reach the right provider in development.
</Warning>

***

## Production setup

Add two environment variables to your deployment platform (Vercel, Railway, Fly.io, etc.):

```bash theme={null}
ELDING_REFRESH_TOKEN=eld_rt_...   # dashboard → API Tokens → New deploy token
ELDING_SET_ID=...                 # dashboard → your set → copy ID
```

No code change required. `configure()` reads these automatically.

<Note>
  The deploy token is scoped to a single set and locked to the provider host. If it leaks, an attacker can only call that one API endpoint — they never see the actual key. You can revoke it instantly from the dashboard.
</Note>

***

## Security model

| What                    | Where it lives                                                       |
| ----------------------- | -------------------------------------------------------------------- |
| API key (e.g. `sk-...`) | Elding vault only, AES-256-GCM encrypted                             |
| Dev access              | Local proxy at `127.0.0.1` — never exposed on the network            |
| Prod access             | Cloud proxy — key injected server-side, never returned to the caller |
| Deploy token            | Scoped to one set, locked to one host, instantly revocable           |

`configure()` is the only function you need. The key is never a string in your code.
