> For the complete documentation index, see [llms.txt](https://docs.soda.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.soda.io/soda-ai/bring-your-own-key-byok.md).

# Bring your own key (BYOK)

{% hint style="info" %}
Bring your own key is **only available in organizations fully on Soda v4**.

[Migrate to Soda v4](/reference/migrate-from-v3-to-v4.md) to have access to the newest Soda capabilities.
{% endhint %}

Bring-your-own-key (BYOK) lets you point Soda's AI-backed features at an OpenAI account that you own and control, instead of the OpenAI project Soda operates on your behalf. Once a feature is bound to a provider that uses your key:

* **Your data stays in your OpenAI workspace.** Every AI request the feature makes (Ask AI prompts, Contract Copilot generations, Autopilot runs) is sent directly to your OpenAI project. None of it passes through Soda's OpenAI project, and the privacy, retention, and regional-routing terms that apply are the ones you have configured on your own OpenAI account (for example workspace-level data-retention settings or a zero-retention agreement).
* **You stay in control of the key.** Soda never stores the raw key; it stores a reference to where the key lives (an environment variable on your infrastructure, or a Soda Cloud secret you manage). Rotation and revocation happen in the system you already use, with no need to involve Soda support.

You can mix and match. Some capabilities can stay on the Soda built-in provider (and continue to be covered by your Soda subscription) while others run against your own key.

## AI configuration

Soda's AI-backed features run on a configurable provider layer. **By default, every organization uses the Soda built-in provider**, which is managed end-to-end by Soda. If you want those features to run against your own OpenAI account instead, you can add a custom provider and bind it to the features you choose.

### Organization settings - AI tab visibility

The **AI** tab (LLM) in **Organization settings** is shown only when at least one AI-backed feature is enabled for your organization. **If every AI-backed feature is currently disabled, the tab is hidden**, because there is nothing to configure.

<figure><img src="/files/ieAI7JfizCELaSgBhYpA" alt=""><figcaption></figcaption></figure>

### Providers

The **Providers** section of the AI tab lists every provider available to your organization.

#### **Soda's built-in provider**

The **Soda (OpenAI)** card is always present and is always shown first. It represents the AI endpoint that Soda manages on your behalf, and it:

* is included with your Soda subscription,
* cannot be edited or removed, and
* has no settings of its own: there is no API key to rotate, and the model is chosen and maintained by Soda.

If you only use the built-in provider, no further setup is required: every AI-backed feature is bound to it by default.

#### **Add a custom OpenAI provider**

Click **Add provider** at the end of the providers list to open the **Add provider** dialog.

<figure><img src="/files/DfpDj53mMyHElQhCgjTm" alt=""><figcaption></figcaption></figure>

Fill in:

* **Type** — currently only **OpenAI** is available.
* **Name** — a name that identifies this provider in the providers list and in the feature-configuration dropdowns. Choose a label that makes it easy to recognize which key it represents, for example `Acme prod OpenAI`.
* **API key** — a reference to where the key is stored. **Soda never stores the raw key itself**; instead, the value you enter here points to the location Soda should read at run time. The field accepts two reference formats, described in the next section.

When you click **Save** the new provider appears in the providers list and becomes selectable in every feature-configuration box.

#### **API key reference formats**

The **API key** field accepts one of two reference formats: **environment variable**, or **Soda Cloud secret**. Soda resolves the reference at run time and uses the real value only in memory; the raw key is never written to Soda Cloud's storage.

**1. Environment variable — `${env.NAME}`**

Use the `${env.NAME}` format when the key is set as an environment variable on the self-hosted agent.

```bash
${env.OPENAI_API_KEY}
```

At run time, Soda reads the named environment variable from the host's environment. The value never enters Soda Cloud and is never visible in the secrets UI. It lives entirely in your own infrastructure.

This option is recommended when:

* you already **manage credentials through your platform's environment** (for example Kubernetes secrets mounted as environment variables, AWS Parameter Store injected at boot, or a `.env` file on a self-hosted machine), or
* you prefer the key to **remain entirely outside Soda Cloud**.

{% hint style="info" %}
Storing the key as an environment variable will not work with the Soda AI feature because it is a Soda-managed service, and you do not have control over the environment variables.
{% endhint %}

**2. Soda Cloud secret — `${secret.NAME}`**

Use the `${secret.NAME}` format to reuse Soda Cloud's built-in secrets manager. The referenced secret must already exist under **Organization settings → Secrets**. The reference looks like:

```
${secret.openai-api-key}
```

At run time, Soda looks up the secret in your organization's encrypted secret store and uses its value in memory. This option is recommended when:

* you **don't run a self-hosted agent** and have nowhere to set environment variables, or
* you prefer to **manage every credential in one place**, using the same rotation and access controls you already use for warehouse passwords and other secrets.

{% hint style="info" %}
**A `${secret.…}` reference creates a live link between the provider and the secret.** While any AI provider's API key still points at a given secret, Soda Cloud prevents that secret from being deleted; the deletion dialog lists the affected providers and asks you to update them first.
{% endhint %}

#### Manage existing providers

Each custom provider has a three-dot menu with a **Remove** action. A provider can only be removed when no feature is currently bound to it. If a feature still uses the provider, the removal is blocked and Soda tells you which capabilities to reassign first.

{% hint style="info" %}
The Soda built-in provider has no menu and cannot be removed.
{% endhint %}

### Attach a provider to a feature

Below the providers list, the **Feature configuration** section allows you to bind each AI-backed capability to a provider:

<figure><img src="/files/2UKY2fw1JltjLM3JtBeH" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Capabilities that are disabled for your organization are not shown.
{% endhint %}

#### What each capability covers

* **Soda AI** powers **Ask AI** and **Contract Copilot**. You can point this capability at any provider, including your own OpenAI account, but the model used for Soda AI is fixed by Soda. There is no **Model** field, because the model is chosen by Soda to match the prompts that ship with these features.
* **Runner** powers **Autopilot**. The Runner box also includes a **Model** field where you can specify the model your provider should use (for example `gpt-4o` or `gpt-4o-mini`). If you leave the field empty, the provider's default model is used.

#### Bind a feature

{% stepper %}
{% step %}
In the capability's box, open the **Provider** dropdown.
{% endstep %}

{% step %}
Choose **Soda (OpenAI)** to keep the feature on the built-in provider, or choose any custom provider you have added.
{% endstep %}

{% step %}
For Runner, optionally enter the model name in the **Model** field.
{% endstep %}

{% step %}
Click **Save** at the bottom of the section.
{% endstep %}
{% endstepper %}

The new binding takes effect on the next run of that feature.

#### Switch back to the built-in provider

If a custom provider is bound to a capability and you want to revert:

{% stepper %}
{% step %}
Open the capability's box.
{% endstep %}

{% step %}
Set the **Provider** dropdown back to **Soda (OpenAI)**.
{% endstep %}

{% step %}
Click **Save.**
{% endstep %}
{% endstepper %}

Once no capability is bound to a custom provider, you can remove that provider from the providers list.

#### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

| The **AI** tab is missing from Organization settings.         | At least one AI-backed feature must be enabled for your organization: Ask AI, Contract Copilot, or Autopilot. If all three are disabled, the tab is intentionally hidden.                               |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The **Add provider** dialog rejects the API key.              | The key must be a `${env.NAME}` or `${secret.NAME}` reference. Plain strings, empty values, and other `${…}` formats are not accepted.                                                                  |
| Removing a provider fails with a message naming a capability. | The provider is still bound to that capability. Open **Feature configuration**, change the named capability to a different provider, save, then remove the provider again.                              |
| A `${secret.NAME}` reference does not resolve at run time.    | Make sure the secret still exists under **Organization settings → Secrets** and that its name matches the reference exactly. Secret names are case-sensitive.                                           |
| A `${env.NAME}` reference does not resolve at run time.       | Make sure the environment variable is set in the process that runs Soda (for example, the self-hosted agent) and that the variable name matches exactly. Environment variable names are case-sensitive. |

***

{% if visitor.claims.plan === 'datasetStandard' %}
{% hint style="success" %}
You are **logged in to Soda** and seeing the **Dataset Standard license** documentation. Learn more about [Documentation access & licensing](/reference/documentation-access-and-licensing.md).
{% endhint %}
{% endif %}

{% if visitor.claims.plan === 'enterprise' %}
{% hint style="success" %}
You are **logged in to Soda** and seeing the **Team license** documentation. Learn more about [Documentation access & licensing](/reference/documentation-access-and-licensing.md).
{% endhint %}
{% endif %}

{% if visitor.claims.plan === 'enterpriseUserBased' %}
{% hint style="success" %}
You are **logged in to Soda** and seeing the **Enterprise license** documentation. Learn more about [Documentation access & licensing](/reference/documentation-access-and-licensing.md).
{% endhint %}
{% endif %}

{% if !(visitor.claims.plan === 'enterprise' || visitor.claims.plan === 'enterpriseUserBased' || visitor.claims.plan === 'datasetStandard') %}
{% hint style="info" %}
You are **not logged in to Soda** and are viewing the default public documentation. Learn more about [Documentation access & licensing](/reference/documentation-access-and-licensing.md).

If you do have a Soda license, make sure to **log in to Soda Cloud in this same browser**.
{% endhint %}
{% endif %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.soda.io/soda-ai/bring-your-own-key-byok.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
