このエントリは2025/10/29現在の情報に基づいています。将来の機能追加や変更に伴い、記載事項からの乖離が発生する可能性があります。
問い合わせ
Azure OpenAI Service (AOAI) のGPT-5モデルを使おうとしているいつもの主から、以下のような問い合わせが届いた。
AOAIのGPT-5モデルはこれまでのモデルとは異なり、V1 API (Responses APIs) でアクセスしなければいけないようなので、ドキュメントに従って構成しているが、API Keyを渡すところで詰まっている。ふつうにSDKからAOAIに直接アクセスする場合、特に問題なく動作するのだが、Azure API Management (APIM) を挟んだ場合、APIMでSubscription Keyを渡そうとするとうまくいかない。APIMを挟んでも動作するようにするにはどうすればよいか?
GPT-5ではV1を使う必要がある、という記述は以下にある。
API と機能のサポート / API & feature support
https://learn.microsoft.com/azure/ai-foundry/openai/how-to/reasoning?tabs=gpt-5#api–feature-support
この主によると、OpenAIのGitHubリポジトリにはAzureOpenAIパッケージを使うようなサンプルが出ているが、
The official Python library for the OpenAI API
https://github.com/openai/openai-python?tab=readme-ov-file#microsoft-azure-openai
Azure OpenAIのドキュメントを見たところOpenAIパッケージを使うように、というガイドが出ていたので、Python library for the OpenAI API (以下、OpenAI API) を利用することにした、とのこと。
v1 API
https://learn.microsoft.com/en-us/azure/ai-foundry/openai/api-version-lifecycle?tabs=python#v1-api
ちょっと動作確認
確かに、簡単なアプリケーションを作ってみたところ、直接アクセスする分には動作した。
from openai import OpenAI
endpoint = "https://...."
model_name = "gpt-5-chat"
deployment_name = "gpt-5-chat"
api_key = "...."
def main():
print("Hello from gpt5-chat!")
client = OpenAI(
base_url=f"{endpoint}",
api_key=api_key,
)
completion = client.chat.completions.create(
model=deployment_name,
messages=[
{"role": "user", "content": "Hello! Can you tell me a fun fact about space?"}
],
)
print("Response from gpt5-chat:")
print(completion.choices[0].message.content) # type: ignore
if __name__ == "__main__":
main()
で、APIMを挟むと、以下のような例外が出て動作しない。
openai.AuthenticationError: Error code: 401 -
{
'statusCode': 401,
'message': 'Access denied due to missing subscription key. Make sure to include subscription key when making requests to an API.'
}
これは有名な話なので、すぐにピンと来た方もいらっしゃるかもしれない。
OpenAI APIでのAPI Keyの取り扱い
ドキュメントにも記載があるが、OpenAI APIでは、
authorization: Bearer {API Key}
の形でAPI Keyを渡す。実際のコードでは以下に記載されている。
https://github.com/openai/openai-python/blob/main/src/openai/_client.py#L328
https://github.com/openai/openai-python/blob/main/src/openai/_client.py#L679
ドキュメントでは以下のあたり。
Authentication
https://platform.openai.com/docs/api-reference/authentication
API keys should be provided via HTTP Bearer authentication.
authorization: Bearer OPENAI_API_KEY
ただ、APIMを挟む場合は状況が異なる。クライアントからはAOAIのAPI Keyを渡すことはほぼなく、通常はAPIMのSubscription Key、もしくはJWTと組み合わせてAPIMに渡す。JWTだけの場合は、JWTを検証するポリシーに委ねるため、特に問題はない。APIクライアントからSubscription Keyを送信してくる場合、OpenAI APIはお構いなしで
authorization: Bearer APIM_SUBSCRIPTION_KEY
で渡してくる。もし、旧APIと同じく、api-keyでSubscription Keyを渡してくると期待している場合、つまり
api-key: APIM_SUBSCRIPTION_KEY
でAPIMを構成してしまうと、当然ながら401が返ってしまう。
現時点での回避策
現時点では以下の回避策が考えられる。
| 方針 | 設定 | 備考 |
|---|---|---|
| ①旧APIの方針に合わせる (クライアントアプリでカスタムヘッダーを追加) | クライアントアプリは、Subscription Keyをapi-keyにも指定するよう、カスタムヘッダーを追加するapi-key: APIM_SUBSCRIPTION_KEY | – APIMでは、authorizationの内容を無視– クライアントアプリが多い場合、修正が大変 |
| ②Responses APIに合わせる (APIMでSubscription Key Headerを変更) | Subscription Key Headerを authorizationに変更https://learn.microsoft.com/azure/api-management/api-management-subscriptions#use-a-subscription-key 作成したSubscription Keyの前に Bearer を付ける | – クライアントアプリが本来の認証認可目的でトークンを渡してくる場合、クライアントは別のHTTP Headerを使う必要がある(authorizationは使えない) |
| ③ホストしている旧APIの前にProxyを置く | 様々な方法があるが、例えばAPIMを2段構成にする。 1段目で authorization: Bearer APIM_SUBSCRIPTION_KEYを api-key: APIM_SUBSCRIPTION_KEYに書き換え、バックエンドサービス(旧API)にルーティング | – V1完全移行後も残存 – CORS関連で例外が出る可能性がある |
①はクライアント側に一手間必要であるが、APIMとしては特に何もする必要がない。

②は、Subscription Key作成時に以下のあたりを考慮する必要がある。

- クライアントに渡すKeyには
Bearerを含めない - APIM側では
Bearerを含めて保持しておく
これは以下の理由による。
- APIMでは
Bearerを含めた値でSubscription Keyをチェックするため、Bearerが抜け落ちていると401を返す
これは、クライアントアプリはSubscription Keyを
authorization: Bearer APIM_SUBSCRIPTION_KEY
で送信してくるにもかかわらず、APIM内でBearer を付けずにSubscription Keyを保持していると、APIMは
authorization: APIM_SUBSCRIPTION_KEY
を期待してしまうため、結果整合せずに401を返してしまう。そしてもう一つ、
- APIMのInboundセクションでは、Subscription Keyの判断はできない(ポリシースコープ外)。そのため、
Bearerを除去する仕組みをInboundセクション内に設定しても意味がない
は文字通りで、Subscription KeyのチェックはInboundセクションでは取り扱いできないので、Bearer の有無はポリシーで判断できない。
なので、Subscription Keyのセルフサービス発行をさせたい場合にはハードルが上がってしまう。なおカスタムのSubscription Keyを作成する方法は、以下のエントリを参照。
③は過去に以下のエントリで記載している構成と同じ。

コストも掛かるし、手間も掛かり、かつエレガントではないので、3方法の中では一番おすすめしないやり方。
どれを選択すべきか
現時点では、V1 APIへの移行過渡期のため、
- 旧APIの利用が考えられる、かつクライアントアプリの個数が少ないのであれば、①
- V1にすべて移行するのであれば、②
- どうしても、というなら、③