# Bring your own key (BYOK)

> Connect your own AI provider key, what the connection test checks, daily health checks, fallback, cost estimates and the residency attestation.

Source: https://shopassist.coec.dk/docs/ai/byok · Updated 2026-10-01

With your own key, the assistant runs on your account at your AI provider. Your provider bills you for usage, and it is **your** processor, not ShopAssist's sub-processor.

## Providers [#providers]

- [OpenAI](/docs/ai/openai)

- [Anthropic](/docs/ai/anthropic)

- [Google Gemini](/docs/ai/google-gemini)

- [Azure OpenAI](/docs/ai/azure-openai)

- [Mistral](/docs/ai/mistral)

- [OpenAI-compatible](/docs/ai/openai-compatible) — OpenRouter, Groq, Together, Ollama, vLLM, LM Studio

## Connect a key [#connect]

1. In **AI → Model**, choose **Use your own AI key**, the provider and the model.
2. Read the data-location note for the provider and tick the attestation (below).
3. Paste the key and save. The key is encrypted at rest and never shown again; only its last four characters are displayed.
4. **Test connection** runs automatically. Until it passes, the assistant is unavailable on your storefront and the widget offers your contact options instead.

## What the connection test checks [#probe]

| Check | Required | What it tests | On failure |
| --- | --- | --- | --- |
| `auth` | Yes | The key is accepted (lists models or sends a tiny request) | `auth_failed`, `insufficient_quota`, `gemini_free_tier`, `endpoint_blocked`, `provider_unavailable`, `model_not_found` |
| `tools` | Yes | The model calls a tool with valid arguments and continues after the result | `tools_unsupported`: the model can't run the shopping tools |
| `ttft` | No (degraded) | The first answer event arrives within 8 seconds | `ttft_slow`: works, but shoppers wait |
| `parallel_tools` | No | Two tools are called in one step | `parallel_tools_unsupported`: slightly slower answers |
| `vision` | No | The model names the colour of a test image | `vision_unsupported`: visual search is off |
| `context` | Self-hosted only | A fact at the start of an 8,000-token prompt is recalled | `context_too_small`: the endpoint truncates prompts |

The test takes up to 30 seconds and can be run 10 times per hour. Probe requests are tiny and never counted as conversations.

## Daily health checks [#health]

Every day ShopAssist checks that the key is still accepted, and once a week it runs the full test. If the key stops working or slows down, owners and admins get an email (at most once a day) and the dashboard shows the reason. After fixing it, run **Test connection** again.

## Fallback [#fallback]

Add a second key in **AI → Fallback** to switch automatically when the primary provider fails. Without a fallback, provider outages are not covered by the SLA.

## Cost [#cost]

Your provider charges per token. Typical costs per 1,000 conversations:

Estimate based on list prices on 2026-09-28; your provider bills you directly.

| Provider | Model | USD per 1,000 conversations | ≈ EUR per 1,000 conversations |
| --- | --- | --- | --- |
| Azure OpenAI | GPT-6 Luna | $3.61 | €3.10 |
| Mistral | Mistral Small 4 | $4.71 | €4.05 |
| OpenAI | GPT-5.6 Luna | $7.62 | €6.55 |
| Google Gemini | Gemini 3.1 Flash-Lite | $8.85 | €7.61 |
| OpenAI | GPT-5 mini | $9.85 | €8.47 |
| Google Gemini | Gemini 3.5 Flash-Lite | $12.02 | €10.34 |
| Mistral | Mistral Large 3 | $14.70 | €12.64 |
| OpenAI | GPT-5.4 mini | $26.55 | €22.83 |
| Anthropic | Claude Haiku 4.5 | $36.10 | €31.05 |
| Anthropic | Claude Sonnet 5 | $72.20 | €62.09 |

## Attestation [#attestation]

Before you save a key, you confirm:

> "I confirm that my business has its own agreement with \{provider}, including a data processing agreement and, where needed, a valid transfer mechanism for any processing outside the EEA. I instruct ShopAssist to send shopper conversations and the store data needed to answer them to this provider. I understand that \{provider} is my processor, not ShopAssist's sub-processor."

The confirmation is recorded with the store, the provider and the attestation version. Saving without it fails with `residency_ack_required`.

## Errors [#errors]

| Code                                          | Meaning                                              | Fix                                                 |
| --------------------------------------------- | ---------------------------------------------------- | --------------------------------------------------- |
| `auth_failed`                                 | The provider rejected the key                        | Create a new key; check the project or organization |
| `insufficient_quota`                          | No credit left on the provider account               | Top up or raise the spending limit                  |
| `rate_limited`                                | The provider is rate-limiting                        | Raise your tier at the provider, or add a fallback  |
| `model_not_found`                             | The model or deployment doesn't exist or was retired | Choose a current model                              |
| `tools_unsupported`                           | The model can't call tools                           | Choose a model with tool calling                    |
| `context_too_small`                           | The endpoint truncates prompts                       | Raise the context window (self-hosted)              |
| `endpoint_blocked`                            | The URL isn't public HTTPS                           | Expose it over HTTPS with authentication            |
| `invalid_key_format`, `key_provider_mismatch` | The key doesn't look like a key for this provider    | Check you pasted the right key                      |

More: [AI provider errors](/docs/troubleshooting/ai-provider-errors).
