News

OpenAI Regional Processing Per Request: Route One Call to the EU

OpenAI's API changelog entry dated August 21, 2026 changes the geography decision from project-only to request-level. An API key from a project with Global geography can now call the ordinary global domain, the US-prefixed domain, or the EU-prefixed domain. That removes the need to create a second project merely to route one eligible workload through a supported region. It does not remove the hard parts: your organization still has to qualify, the endpoint and model still need regional-processing support, and a feature that works globally can still be unavailable in one region.

August 24, 2026

Dark miniature server installation with three large glass cubes connected by cyan light beams to a smaller glowing cube at the center.
One credential can now select three processing paths; each regional path still has its own eligibility and support gates.

The Change Is One Base URL

The new path is deliberately small. Keep the key from your existing Global-geography project and select a domain when you construct the request. OpenAI's current documentation uses gpt-5.6-terra with the Responses API for all three routes:

from openai import OpenAI

client = OpenAI()  # OPENAI_API_KEY belongs to a Global project

routes = {
    "global": "https://api.openai.com/v1",
    "us": "https://us.api.openai.com/v1",
    "eu": "https://eu.api.openai.com/v1",
}

for region, base_url in routes.items():
    response = client.with_options(base_url=base_url).responses.create(
        model="gpt-5.6-terra",
        input="Reply with OK.",
        store=False,
    )
    print(region, response.id, response.output_text)

The default route carries no processing-region constraint. The US route selects the United States. Despite its hostname, the EU route is documented as Europe (EEA + Switzerland), so do not silently translate eu into a broader claim such as "all of Europe." The key requirement is just as precise: this per-request shortcut is for a key from a project whose geography is Global. A region-specific project still uses its configured regional domain in the existing way.

Keep the region as an explicit application setting, not an incidental string concatenation. Log the selected route, endpoint, model snapshot, and request ID. That gives an incident reviewer the configuration evidence needed to distinguish "the EU path was selected" from "the global default happened to be used." Do not treat the response text as proof of geography; a model replying OK only proves that the request succeeded.

Eligibility Did Not Move Into the URL

A prefixed hostname is not an entitlement. OpenAI says existing eligibility and data-retention-control requirements continue to apply. For the current US region, the support table does not require Modified Abuse Monitoring (MAM) or Zero Data Retention (ZDR). Europe does: the table requires ZDR, MAM, Eyes Off, or Safety Retention, while the surrounding guidance says non-US data residency requires approval for abuse-monitoring controls and an executed Modified Retention amendment. If your organization has neither, changing api.openai.com to eu.api.openai.com is not a rollout plan.

Preflight the account before preflighting code

Confirm four facts with the owner of the OpenAI organization: the key belongs to a Global-geography project; the organization is eligible for data residency controls; the required retention control is enabled for the project or inherited from the organization; and the non-US amendment is in place. Then test with a non-production payload. An HTTP success is useful operational evidence, but it is not a replacement for the account and contractual checks.

This is also why rotating a key or copying credentials between projects is the wrong abstraction. Put the one Global-project key in your normal secret store, keep geography in a validated routing policy, and authorize each workload class to use only the regions it needs. The same principles in the site's API contract change plan apply here: configuration, rollback, logging, and a deliberately small canary belong in the change, even when the code diff is one line.

Storage and Processing Are Separate Columns

OpenAI's table lists regional storage and regional processing independently. The United States and Europe currently show Yes in both columns, but several other regional domains show storage support and no regional-processing support. That distinction matters because a domain can keep supported persisted customer content at rest in a region without promising that every inference runs there.

Even where regional processing is supported, the scope is narrower than "all data stays here." OpenAI's data-residency terms apply to customer content, not system data such as account details, analytics, usage statistics, billing information, support requests, or structured-output schemas. They also exclude transfers caused by your own infrastructure or end-user location and data sent to third-party services. Remote MCP servers are a concrete example: the regional table supports the tool for US and European processing, but the server is a third party and its own residency policy governs what you send to it.

For an organizational treatment of this distinction — procurement, contracts, and follow-up rather than API implementation — see the separate Swedish perspective on storage location versus processing location for AI calls. The engineering control here is smaller: never collapse the two support columns into one regional=true flag.

Validate the Combination, Not the Region

Regional support is a four-part tuple: region, endpoint, model or tool, and request options. As checked on August 24, the Responses API and gpt-5.6-terra are listed for regional processing in both the US and Europe. That does not mean every Responses configuration is portable. OpenAI lists these current endpoint limitations:

That fourth item is the sharpest illustration of the two-column distinction above: a documented feature can move customer content out of a storage-only region to deliver the service. It does not apply to the US and Europe, which both support regional processing — but it is the reason an allowlist should record the region, endpoint, model, and options together rather than a single regional flag.

Model lists are equally specific and can change. A robust deployment policy should therefore be an allowlist of the combinations your application has actually approved, not a copy of every item in today's vendor table. Pin a model snapshot where the application permits it, store the documentation check date beside the policy, and expand the allowlist only after a source review and a smoke test. The verification ladder is the useful pattern: cheap local rejection first, then a controlled live request, then a production canary.

APPROVED = {
    ("global", "/v1/responses", "gpt-5.6-terra"),
    ("us", "/v1/responses", "gpt-5.6-terra"),
    ("eu", "/v1/responses", "gpt-5.6-terra"),
}

def regional_request_allowed(region, endpoint, model, *, background=False):
    if (region, endpoint, model) not in APPROVED:
        return False
    if region == "eu" and endpoint == "/v1/responses" and background:
        return False
    return True

This intentionally tiny allowlist is not a claim that other models are unsupported. It says only which combinations this application has reviewed. That difference prevents a future documentation expansion from silently turning into a production expansion.

Make Unsupported Cases Fail Before the Network

Positive tests prove that the intended path works. Negative tests prove that a later feature flag, model substitution, or endpoint migration cannot bypass your geography policy. The three tests below cover one region-specific option, one endpoint with storage but not processing, and one model that belongs to another endpoint:

def test_eu_responses_rejects_background_mode():
    assert not regional_request_allowed(
        "eu", "/v1/responses", "gpt-5.6-terra", background=True
    )

def test_vector_store_is_not_an_approved_processing_endpoint():
    assert not regional_request_allowed(
        "eu", "/v1/vector_stores", "service-level"
    )

def test_realtime_model_cannot_be_substituted_into_responses():
    assert not regional_request_allowed(
        "eu", "/v1/responses", "gpt-realtime-translate"
    )

Run the three-route live probe only after these policy tests pass. Use a synthetic prompt with no customer content, and expect the EU request to fail until the account prerequisites are complete. Record the status and error body without weakening the assertion to "any response is fine." When all routes work, canary one real workload class through EU, watch latency and error rate, then widen it. Keep global as an explicit rollback target rather than falling back automatically: an automatic geography fallback can turn a regional-processing requirement into a silent policy violation.

The fallback distinction is important. A model fallback handles service availability; a geography fallback changes where the work is processed. The site's model fallback drill is useful for the mechanics, but the authorization rule here should be stricter: if EU processing is mandatory and the EU route fails, fail closed or queue the job. Route globally only when the workload policy explicitly permits it.

The rollout decision

Use the same Global-project key and select api.openai.com, us.api.openai.com, or eu.api.openai.com per request. Before enabling EU, verify the account's retention controls and amendment. Then allowlist the exact endpoint, model, and options you reviewed, add negative tests for unsupported combinations, and log the chosen route. The August 21 change removes project and credential sprawl; it does not remove regional policy.

Sources checked August 24, 2026