メインコンテンツへスキップ

OpenAI の base_url 変更:優先順位とパスの書き方

送信先は引数、OPENAI_BASE_URL、既定値の順で決まります。base は /v1 や /openai/v1 までで、/chat/completions は書きません。

LaoZhang AI Team公開22 分で読めます
目次
1つの OpenAI SDK から base_url の違いで OpenAI の /v1、Azure OpenAI の /openai/v1、Gemini API の /v1beta/openai、ゲートウェイの /v1 へ振り分けられる様子

OpenAI の公式 SDK で送信先を変えるには、クライアントを作るときの base_url(Node では baseURL)か、環境変数 OPENAI_BASE_URL を使います。両方あれば引数が勝ち、どちらもなければ https://api.openai.com/v1 に送られます。SDK はこの base の後ろに /chat/completions や /responses をつなげるだけなので、base には接続先が求めるパスの前半(/v1、/openai/v1、/v1beta/openai など)まで書き、エンドポイント名そのものは書きません。

以下の SDK の挙動は、2026年9月26日時点の最新版である openai-python 3.19.2 と openai(npm)7.23.0 のソースコード、およびローカルのエコーサーバーで実際のリクエストパスを記録した結果に基づきます。base_url が正しくても、接続先が呼び出し中の API を実装していなければ 404 になるため、Chat Completions と Responses のどちらを呼んでいるかも合わせて確認します。

優先順位:引数、環境変数、data residency

Python と Node で共通の基本は「引数 → OPENAI_BASE_URL → 既定値」です。ただし空文字の扱いなど、細部で両者は違います。

設定の状態Python(openai 3.19.2)Node(openai 7.23.0)
引数だけ指定引数の URL引数の URL
OPENAI_BASE_URL だけ指定環境変数の URL環境変数の URL
引数と環境変数の両方引数が優先引数が優先
どちらもなしhttps://api.openai.com/v1https://api.openai.com/v1
OPENAI_BASE_URL=""(空文字)base が空のまま残り、送信時に APIConnectionError未設定と同じ扱いで https://api.openai.com/v1 に送る
旧名の OPENAI_API_BASE だけ指定無視され、https://api.openai.com/v1無視され、https://api.openai.com/v1
data_residency="eu" と環境変数https://eu.api.openai.com/v1(環境変数より優先)dataResidency: 'eu' で同じ結果
baseURL: null と環境変数該当なし環境変数を読まず既定値

いちばん気づきにくいのは、Node で OPENAI_BASE_URL が空文字になっているケースです。エラーにならずに api.openai.com へ送られるため、ゲートウェイや他社のキーがそのまま OpenAI に届きます。OpenAI はそのキーを受け付けないので、キーの不備に見える 401 になりがちです。401 を見てキーを疑う前に、送信先を確かめる価値があります。

OPENAI_API_BASE と openai.api_base は v1 より前の openai-python で使われていた名前で、現行の SDK は読みません。古いサンプルからコピーした設定で送信先が変わらないときは、ここを最初に疑います。フレームワークやツールが自前で環境変数を読んでいる場合は、SDK と同じ名前・同じ優先順位とは限らないので、そのツールのドキュメントを確認してください。Codex CLI は独自の設定(openai_base_url と model_providers)を使うので、Codex カスタムプロバイダー設定:APIキーとBase URLの選び方を参照してください。

OpenAI のリージョン別エンドポイントは、URL を直接書くより data_residency(Node は dataResidency)で指定します。SDK に登録されている値は us、eu、ae で、それぞれ https://us.api.openai.com/v1 のような URL に展開されます。base_url と同時に渡すとクライアントの生成時点でエラーになります。自分のアカウントでそのリージョンを使えるかどうかは、SDK の一覧からは分かりません。

呼び出しごとに送信先を変えたい場合は、client.with_options(base_url=...)(Node は client.withOptions({ baseURL }))が使えます。変わるのはその呼び出しだけで、クライアント本体の base はそのまま残ります。

引数で指定する最小の例として、Gemini API の OpenAI 互換エンドポイントに向けるコードを示します。

python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
    api_key=os.environ["GEMINI_API_KEY"],
)
print(client.base_url)  # 実際に使われる base を表示
js
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
  apiKey: process.env.GEMINI_API_KEY,
});
console.log(client.baseURL);

base_url にはどこまで書くか

SDK は base の後ろに chat/completions や responses といった相対パスをつなげて、1本の URL にします(Python は base の末尾にスラッシュを補います)。したがって、接続先のドキュメントに載っている完全な URL から、末尾のエンドポイント名(/chat/completions、/responses、/embeddings など)を取り除いた残りが、そのまま base_url になります。

ローカルのエコーサーバーに chat.completions.create() を送ったとき、サーバーが受け取ったパスは Python と Node で同じでした。

base_url に書いた値サーバーが受け取ったパス判定
http://[::1]:8765/chat/completions/v1 配下で待ち受けるサーバーでは 404
http://[::1]:8765/v1/v1/chat/completions正しい
http://[::1]:8765/v1//v1/chat/completions正しい。スラッシュは二重にならない
http://[::1]:8765/v1/chat/completions/v1/chat/completions/chat/completionsエンドポイント名が二重になり 404

末尾のスラッシュの有無は結果に影響しません。影響するのは、途中のパスを書き漏らすか、エンドポイント名まで書いてしまうかの2点です。

base_url に書いた値へ SDK が chat/completions をつなげた結果の比較。/v1 までなら正しいパス、/v1 が抜けると /chat/completions、エンドポイント名まで書くと二重になって 404

接続先ごとの書き方は次のとおりです。キーと model に渡す値も接続先に合わせて変わるので、base_url だけを差し替えて終わりにはなりません。

接続先base_urlAPI キーmodel に渡す値注意点
OpenAI(既定)https://api.openai.com/v1OpenAI の API キーOpenAI のモデル ID何も指定しなければこれ
OpenAI のリージョン別data_residency で us・eu・ae を指定OpenAI の API キーOpenAI のモデル IDbase_url と併用不可
Azure OpenAI(v1 API)https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/Azure OpenAI の API キー、または Entra ID のトークンプロバイダーデプロイ名OpenAI() を使い、api-version は不要
Gemini API の OpenAI 互換https://generativelanguage.googleapis.com/v1beta/openai/Gemini API キーGemini のモデル IDライブラリ対応はベータ版。Responses API の記載なし
OpenAI 互換ゲートウェイ(例:LaoZhang API)https://api.laozhang.ai/v1ゲートウェイの API キーゲートウェイのモデル一覧にある IDResponses は GPT-6 系のみ明記
ローカル・自前のサーバー互換エンドポイントの URL から末尾のエンドポイント名を除いたものサーバーの設定によるサーバーが読み込んでいるモデル名Cursor からは直接届かない(後述)

Azure OpenAI は、Microsoft Learn の v1 API の説明(2026年5月13日更新)で、エンドポイントに /openai/v1 を付けて base_url に渡すよう案内されています。*.services.ai.azure.com/openai/v1/ の形も使え、OPENAI_BASE_URL と OPENAI_API_KEY を設定すれば引数なしの OpenAI() でも動きます。SDK には従来の AzureOpenAI(azure_endpoint=..., api_version=...) も残っていますが、こちらは別の方式なので、v1 の base_url と混ぜないようにします。v1 の GA 版が対応するのは機能の一部だと同じページに書かれています。Azure で 429 が出る場合は Azure OpenAI の TPM 制限を切り分ける:使用量が少なくても出る 429 の対処法が参考になります。

Gemini API の互換ドキュメント(2026年9月2日更新)は、コードを3行更新すれば OpenAI のライブラリから使えると説明しています。その3行は API キー、base_url、モデル名のことで、動く範囲はドキュメントに載っている機能(Chat Completions、ストリーミング、関数呼び出し、構造化出力、埋め込み、画像、バッチなど)に限られます。

LaoZhang API のドキュメントでは、OpenAI SDK 用の base_url は https://api.laozhang.ai/v1 で、Google Gen AI SDK と Anthropic SDK はホスト直下の https://api.laozhang.ai を使うとされています。同じゲートウェイでも SDK によって base の書き方が変わる、という点でも分かりやすい例です。2026年9月のお知らせで Chat Completions と Responses の両方から呼べると明記されているのは GPT-6 Astra、Sol、Luna の3モデルで、それ以外のモデルで Responses を使えるかは各モデルの説明を確認してください。

Chat Completions と Responses:互換の範囲を確かめる

client.responses.create() は POST {base}/responses に送られます。base_url が正しくても、接続先がこのパスを実装していなければ 404 です。「OpenAI 互換」と書かれていても、どの API までが互換なのかはサービスごとに違います。

2025年11月には、OpenAI のコミュニティフォーラムで、Gemini の互換 base_url に対して responses.create() を呼んだら 404 になったという報告がありました。そこに付いた利用者の回答は「他社は一般に Chat Completions の互換だけを提供している」というものです。Gemini のドキュメントにも Responses API の記載はありません。記載がないことは「絶対に動かない」という意味ではありませんが、前提にはできません。

一方、Azure OpenAI の v1 API のサンプルは responses.create() を使っています。判断の手順は単純で、接続先のドキュメントに /responses が載っていれば Responses を、載っていなければ chat.completions.create() を使います。Responses を前提にしたエージェントのコードを互換サービスに移すなら、先にその対応を確かめてください。Assistants API のコードを移している途中なら、Assistants APIからResponses APIへ移行する実装手順【停止日・状態・ロールバック】も合わせて確認できます。

プロキシと base_url は別の設定

base_url は「どのサービスの API を呼ぶか」という API の起点です。HTTP プロキシは「そのリクエストがどの経路を通るか」という通信の経路です。日本語ではどちらも「プロキシ」と呼ばれがちなので、手元の設定がどちらなのかを先に決めます。

  • 相手から専用の URL と API キーを渡され、その URL に API として送る場合は、ゲートウェイです。base_url に書きます。
  • http://proxy.example.com:8080 のようなアドレスを経由して api.openai.com などに届く場合は、HTTP プロキシです。HTTP クライアントの設定に書きます。

HTTP プロキシのアドレスを base_url に入れると、SDK はそこへ /chat/completions を API リクエストとして直接送るため、意図した経路にはなりません。

base_url は SDK からゲートウェイや API サービスへ直接向かう API の起点、HTTP プロキシは SDK から接続先の API へ向かう途中の経路であることを示す図

Python(3.19.2)では、README にあるとおり http_client にプロキシを渡します。古いバージョンではクラス名が DefaultHttpxClient なので、インストール済みのバージョンの README を確認してください。

python
from openai import OpenAI, DefaultHttpx2Client

client = OpenAI(
    base_url="https://api.openai.com/v1",  # API の起点
    http_client=DefaultHttpx2Client(proxy="http://proxy.example.com:8080"),  # 経路
)

Node では undici の fetch と ProxyAgent を fetchOptions の dispatcher に渡します。

js
import OpenAI from 'openai';
import { fetch, ProxyAgent } from 'undici';

const client = new OpenAI({
  fetch,
  fetchOptions: { dispatcher: new ProxyAgent('http://proxy.example.com:8080') },
});

応答がまったく返らずに APIConnectionError になる場合は、リクエストが接続先に届いていないので、OpenAI API 接続エラー: APIConnectionError はまず経路から切り分けるの手順が使えます。

実際の送信先を確かめる

設定を変えたら、リクエストが本当にどこへ向かっているかを確認します。軽い順に次の4つです。

  1. クライアントを作った直後に print(client.base_url)(Node は console.log(client.baseURL))で、最終的な base を表示する。
  2. 環境変数 OPENAI_LOG=debug で SDK のログを出す。Node ではクライアントの logLevel: 'debug' でも指定でき、環境変数より優先されます。ログの形式はバージョンによって変わります。
  3. ローカルのエコーサーバーに向けて、SDK が組み立てたパスをそのまま見る。
  4. 接続先のダッシュボードやログに、そのリクエストが記録されているかを見る。記録がなければ、リクエストはそこに届いていません。

3 は、本物の接続先を呼ばずにパスの組み立てだけを確かめる方法です。Python の標準ライブラリだけで動きます。

python
# echo_server.py
import json
import socket
from http.server import BaseHTTPRequestHandler, HTTPServer

class Echo(BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        model = json.loads(body or b"{}").get("model")
        print(f"{self.command} {self.path} model={model}", flush=True)
        reply = {
            "id": "chatcmpl-echo", "object": "chat.completion", "created": 0,
            "model": model or "echo",
            "choices": [{"index": 0, "finish_reason": "stop",
                         "message": {"role": "assistant", "content": self.path}}],
        }
        data = json.dumps(reply).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

    def log_message(self, *args):
        pass

class V6Server(HTTPServer):
    address_family = socket.AF_INET6

V6Server(("::1", 8765), Echo).serve_forever()
python
# check.py
from openai import OpenAI

client = OpenAI(api_key="sk-dummy", max_retries=0)
print("base_url:", client.base_url)
r = client.chat.completions.create(
    model="test-model",
    messages=[{"role": "user", "content": "ping"}],
)
print("server saw:", r.choices[0].message.content)

別のターミナルで python echo_server.py を起動し(IPv6 のループバックアドレス ::1 で待ち受けます)、OPENAI_BASE_URL=http://[::1]:8765/v1 python check.py を実行すると、server saw: /v1/chat/completions と表示されます。OPENAI_BASE_URL に /chat/completions まで含めると /v1/chat/completions/chat/completions が表示されます。本番のコードと同じ方法で base_url を渡してから試すと、フレームワーク経由の設定が効いているかも分かります。

キーはダミーで構いません。base_url の向け先には、Authorization ヘッダーで API キーがそのまま届きます。見知らぬサーバーやテスト用のサーバーに本物のキーを送らないようにしてください。

症状から直す場所を決める

エラーの種類と、実際に送られたパスを組み合わせると、直すべき層が決まります。

症状送信先・パスの状態直す場所
404、パスが /v1/chat/completions/chat/completionsbase にエンドポイント名まで入っているbase_url から /chat/completions を削る
404、パスが /chat/completions(/v1 などがない)base に途中のパスが足りない/v1、/openai/v1、/v1beta/openai などを足す
/responses だけが 404接続先が Responses API を実装していないchat.completions.create() に切り替えるか、対応している接続先を使う
他社のキーなのに OpenAI の Incorrect API key providedリクエストが api.openai.com に届いている旧名の環境変数、Node の空文字、環境変数が実行プロセスに渡っていない、などを確認
model not found、存在しないモデル接続先には届いているmodel を接続先の ID に直す。Azure はデプロイ名
APIConnectionError、応答なし接続先に届いていないPython の空文字の OPENAI_BASE_URL、ホストとポート、プロキシ、ファイアウォール
429接続先には届いているbase_url ではなく、接続先のレート制限とクォータ

401 が返っていて送信先が正しい場合は、キー自体の問題です。OpenAI に直接つなぐ場合にどのキーや ID が必要なのかは、OpenAI API Key と Organization ID: 2026年に本当に必要なものにまとまっています。

Cursor の "Override OpenAI Base URL"

Cursor では Settings > Models の API キー欄に "Override OpenAI Base URL" という項目があり、OpenAI 互換の別サービスにチャットを向けられます。Cursor の公式ヘルプページは自分の API キーの登録方法を説明していますが、この項目の挙動は載っていません。以下は2026年8〜9月の Cursor スタッフによるフォーラム回答に基づくもので、一部は修正時期が未定の既知の問題です。

設定は次の順で行います(2026年8月25日・9月10日のスタッフ回答)。

  1. OpenAI API Key の欄に接続先のキーを貼り、"Use OpenAI API key" のトグルをオンにする。キーを貼ることとトグルを入れることは別の操作で、トグルがオフのあいだは base URL も使われません。
  2. Override OpenAI Base URL をオンにする。オンにした直後は https://api.openai.com/v1 が入っているので、接続先の base(例:Fireworks なら https://api.fireworks.ai/inference/v1)に書き換える。
  3. Enter を押すか欄の外をクリックして保存し、Settings を閉じて開き直し、値が残っていることを確かめる。トグルをオフにしてからオンに戻すと、既定値にリセットされます。
  4. "+ Add Custom Model" で接続先の実際のモデル ID を追加し、新しいチャットで送る。

うまくいかないときは、症状から次のように切り分けます。

症状スタッフ回答での原因対処
他社のキーが OpenAI に Incorrect API key provided で拒否されるbase URL が既定値の https://api.openai.com/v1 のまま(2026年9月10日)手順2〜3をやり直す
Unauthorized User API key が出るが、接続先のログに記録がないモデル ID が Cursor の管理するモデル名(例:kimi-k3、kimi-k2.6)と重なり、base URL を使わずに Cursor 側で処理された(2026年8月19日・9月10日)名前が重ならない、接続先の実際のモデル ID を使う
BAD_MODEL_NAME、AI Model Not Found"Use OpenAI API key" がオフで、キーが付かずに送られた(2026年8月25日)トグルをオンにして新しいチャットを開く
Composer や Grok で "This model does not support custom API keys"この設定は Claude と Gemini 以外のすべてのモデルに効き、Cursor 上で動くモデルは自分のキーを受け付けない(2026年9月23日)Cursor のモデルを使うあいだは OpenAI のキーをオフにする
手元の PC のローカルアドレスや社内ネットワークのアドレスに届かないリクエストは Cursor のサーバーでプロンプトを組み立ててから送られるため、公開された HTTPS が必要(2026年2月22日・4月2日・5月22日)ngrok や Cloudflare Tunnel で公開 URL を作る

オンにしているあいだは、内蔵のモデル一覧から選んだ OpenAI 系のモデルも含めて、Claude と Gemini 以外のリクエストがこの URL に向かいます。自前のモデルと Cursor のモデルを同時に使い分ける機能は検討中で、時期は示されていません(2026年8月21日・9月15日)。今のところは、使うモデルに合わせてトグルを切り替えるしかありません。

トンネルでローカルのモデルサーバーを公開すると、その URL を知っていれば誰でも届きます。公開する前に、サーバー側で認証を有効にしておくのが安全です。

公式ヘルプページには、ほかにも判断に関わる条件があります。自分のキーが使われるのはチャットモデルだけで、Tab 補完は Cursor のモデルのままです。自分のキーを使う場合、Cursor のゼロデータ保持ポリシーは適用されません。Team と Enterprise では、自分のキーで送ったリクエストにも Cursor Token 料金(入力・出力・キャッシュを含め100万トークンあたり$0.25)がかかります。また、自分のキーでは接続先のレート制限とコンテキスト上限がそのまま効くため、長い会話では制限を超えやすくなります。

なお、Cursor 3.15.6 では OpenAI API Key と Override OpenAI Base URL の入力欄がクリックで選べない不具合がありました。スタッフはトグルを入れてから Tab キーで欄に移動する回避策を案内し、修正は後続の 3.15 系の更新で配布されると告知しています。

さらに読む: API ガイド
GPT-5.4の無料APIガイド:2026年の5つのアクセス方法と料金比較
API ガイド

GPT-5.4 無料API:2026年のすべてのアクセス方法と料金詳細

OpenAIは2026年3月5日にGPT-5.4をリリースしたが、公式の無料APIは存在しない。しかし開発者には5つの合法的なアクセス経路がある。この記事では各方法の正確な制限、動作するコード、プロンプトキャッシュで90%コストを削減する方法を解説する。

22 分