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

# Keep AI inference in the EU (EU data residency)

> Enforce EU-only inference and storage for every AI model call with one organization-wide Model access rule, or choose an EU route per call on any plan. Opper itself is hosted in Stockholm.

Opper is hosted in the EU, in Stockholm. Where a model call runs depends on the
route it uses, and you can keep inference in the EU in two ways:

* **Per call, on any plan.** Call an EU route, such as `azure/gpt-5.5`
  (Sweden) or `mistral/mistral-large-2512` (France). That call runs in the EU.
* **For your whole organization, on the Control Plane plan.** A
  [Model access](/control-plane/rules/model-access) rule with **Inference
  location** and **Storage location** set to EU. It is an account-level lock,
  not a filter in a model picker: Opper refuses every call to a route outside
  the EU with `403` before the request leaves Opper, whichever API key, SDK, or
  app sends it.

## Where your data is processed

| Layer | Where | What it covers |
| - | - | - |
| **Opper platform** | Stockholm, Sweden: AWS `eu-north-1`, with a second production environment at Evroc | The gateway, traces, usage records, and stored files |
| **The model call** | Where the route runs, for example Sweden for `azure/gpt-5.5` or the United States for `anthropic/claude-sonnet-4-6` | The prompt and response, while the provider processes them |

Every route in the catalog records two locations:

* **Inference location**: where the model runs.
* **Storage location**: where the provider keeps any content it retains, such
  as logs or content held for moderation. A route that retains nothing passes
  any storage requirement. A route that retains content without a recorded
  storage location counts as `GLOBAL` and fails an EU storage requirement.

## Enforce EU-only for your organization

In the [Opper platform](https://platform.opper.ai), open **Rules → Model access**:

<Steps>
  <Step title="Start an organization allowlist">
    Select **Set an org allowlist**, or edit the existing one.
  </Step>

  <Step title="Set the locations">
    Set **Inference location** to **EU** and **Storage location** to **EU**.
    Use **EEA** instead to also allow Norway, Iceland, and Liechtenstein, or
    pick individual countries.
  </Step>

  <Step title="Review and save">
    Select the match counter to review the models that remain, then select
    **Save changes**. The rule applies from the next request.
  </Step>
</Steps>

The same rule through the [Management API](/control-plane/management-api#manage-rules-from-code):

```bash theme={null}
curl -X POST https://api.opper.ai/management/v1/controls/rules \
  -H "Authorization: Bearer $OPPER_MANAGEMENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "'$(uuidgen | tr A-Z a-z)'",
    "kind": "comply",
    "enabled": true,
    "scope": {"type": "org"},
    "config": {"type": "allowlist", "allowlist": {"provider": {"locations": {"inference": {"include": ["EU"]}, "storage": {"include": ["EU"]}}}}}
  }'
```

### What the rule covers

* **Every model call**: text generation, embeddings, image generation,
  speech, transcription, video, OCR, realtime voice, and rerank.
* **Every API key and project** in the organization. A project override can
  narrow the rule further, but cannot allow a location the organization rule
  excludes.
* **Routes without a recorded location.** A route with no recorded inference
  location, or one that retains content with no recorded storage location,
  counts as `GLOBAL` and is refused.

Inference location says where a model runs, not who operates it. Several EU
routes are run by companies headquartered outside the EU, such as Azure and AWS
in Sweden. To restrict by the operator's or the model maker's home country as
well, add **Provider country** or **Maker country** to the same rule.

## What a blocked call returns

A call to a route outside the EU is refused with `403` before anything reaches
the provider. On chat completions:

```json theme={null}
{
  "error": {
    "code": "permission_error",
    "message": "model \"anthropic/claude-sonnet-4-6\" is blocked by the active model allowlist: inference location US is outside EU"
  }
}
```

Other endpoints return the same message in their own error shape. See
[What a blocked call returns](/control-plane/rules/model-access#what-a-blocked-call-returns).

## Bare model names mix regions

A bare model name is served by a pool of routes, and a pool can span regions.
In September 2026, `claude-sonnet-4-6` was served from these five routes:

| Route | Inference location | Under an EU inference and storage rule |
| - | - | - |
| `anthropic/claude-sonnet-4-6` | United States | Skipped |
| `vertexai/claude-sonnet-4-6` | Global | Skipped |
| `vertexai/claude-sonnet-4-6-eu` | EU | Used |
| `aws/claude-sonnet-4-6-eu` | Sweden | Used |
| `azure/claude-sonnet-4-6` | Sweden | Skipped: retains content with no recorded storage location |

Under that rule, a call to `claude-sonnet-4-6` runs only on the routes that
pass and skips the rest. Without a rule, it can run on any of them. To keep a single
call in the EU without a rule, pin an EU route such as
`aws/claude-sonnet-4-6-eu`.

## Find EU routes

* **Browse:** [opper.ai/models/eu](https://opper.ai/models/eu), or the
  machine-readable [opper.ai/models/eu.json](https://opper.ai/models/eu.json).
* **Query the catalog** without an API key:

  ```bash theme={null}
  curl "https://api.opper.ai/v3/models?type=llm&inference_location=EU&storage_location=EU&limit=0"
  ```

  `inference_location` and `storage_location` match the same way as the Rules
  page, so the result is what a rule with the same settings allows. `limit=0`
  returns every match and `total` gives the count. Add
  `&training=no&logging=none` for routes that are both EU and
  [zero data retention](/control-plane/zero-data-retention).

## EU and zero data retention together

EU residency and zero data retention are separate requirements, and one rule can
hold both: set the locations above and set **Provider data policy** to **Zero
data retention**. See [Enforce zero data retention](/control-plane/zero-data-retention)
for what that policy covers.

## Related

<CardGroup cols={2}>
  <Card title="Enforce zero data retention" icon="eye-slash" href="/control-plane/zero-data-retention">
    Store no content at Opper and allow only providers that neither train on nor log it.
  </Card>

  <Card title="Model access" icon="scale-balanced" href="/control-plane/rules/model-access">
    Every allowlist field, error body, and override.
  </Card>

  <Card title="Security" icon="shield" href="/overview/security">
    Certifications, hosting, DPA, and sub-processors.
  </Card>

  <Card title="Dynamic routes" icon="route" href="/capabilities/routes/overview">
    Route across EU models by price, latency, or throughput.
  </Card>
</CardGroup>
