Migrating from OpenAI
Change the URL, key, and model; verify compatibility and keep a rollback path.
Keep the OpenAI SDK and migrate one Chat Completions request by changing the base URL, key, and model ID. This changes the model producing the answer; it does not make DeepSeek behave like GPT-4o.
client = OpenAI(
- base_url="https://api.openai.com/v1",
- api_key=os.environ["OPENAI_API_KEY"],
+ base_url="https://api.deepraxis.com/openai/v1",
+ api_key=os.environ["PRAXIS_API_KEY"],
)
-model = "gpt-4o"
+model = "deepseek-flash"1. Prepare
You need Python 3.10+, uv, and a Praxis key. Create one in Console → API Keys and securely inject it into the current terminal as PRAXIS_API_KEY. Never put the key in code or logs. Keep your original service configuration and key for rollback. Run the commands below in Bash on macOS or Linux.
test -n "${PRAXIS_API_KEY:-}"Expected: exit code 0. Exit code 1 means the variable is missing; set it before continuing.
2. Choose a model ID
These are migration choices, not aliases or promises of equivalent quality. Availability was checked on October 12, 2026; confirm it in the model catalog before switching traffic.
| Existing ID | Praxis choice | What changes |
|---|---|---|
gpt-4o, gpt-4o-mini | deepseek-flash | These original IDs do not exist; reassess prompts, tools, and output quality |
gpt-4.1, o3-mini, gpt-5 | deepseek-flash | No automatic mapping; the original IDs return 404 |
| An OpenAI-family model is required | gpt-5.6-sol | Chat Completions is available; Responses is not |
| Existing Responses code | deepseek-flash or glm-5.3-flash | These are the currently available Responses choices |
For Responses, check that your selected ID appears in GET /openai/v1/models?api=responses (Python: client.models.list(extra_query={"api": "responses"})). Alternatively, inspect supported_apis in GET /model/v1/models or GET /model/v1/models/{id} and confirm it includes openai.responses. Other OpenAI filters are chat, embeddings, images, audio, and videos; comma-separated values match any selected API.
Behavior differences
- A protocol-compatible request keeps its protocol when forwarded. This does not guarantee every official model, endpoint, or field is available.
- A listed model can still reject a particular operation with
404 model_protocol_not_offered. Keep Chat and Responses capability checks separate. - Recheck streaming, tool execution, structured output, and reasoning on your own prompts before shifting traffic. Field differences live in Chat Completions and Responses.
- Files, conversations, and response IDs from the original service do not move with a URL change. Retain source data and rebuild the resources your application needs.
- Chat's
usage.costis the amount charged; Responses and Messages currently omit it. WhenX-Praxis-Generation-Idis present, useGET /model/v1/generation?id=GENERATION_IDas described in the generation record API. Records may take a few seconds to appear. If the header is absent, check Console → Usage and costs. Neither the response body'sidnorX-Request-Idis a substitute for a generation ID. Missing cost does not mean zero cost.
Unsupported endpoints and alternatives
Paths below are relative to /openai/v1 and return 404. Alternatives are not equivalent replacements. If your application depends on these operations, split the calls and keep the original service.
| Original endpoint | Migration option |
|---|---|
moderations | No direct replacement; keep your moderation service |
batches | Send individual requests with application-controlled concurrency |
fine_tuning | Choose an existing model; retain your fine-tuning workflow |
assistants | Rebuild with Responses / Conversations and an application tool loop |
completions | Use chat/completions with messages |
audio/translations | Transcribe first, then translate through chat |
uploads | Use files; check size and purpose limits |
images/variations | Submit the image and editing instructions to images/edits; evaluate the result |
Available endpoints include chat/completions, responses, embeddings, images/generations, images/edits, audio/speech, audio/transcriptions, videos, files, and models. Endpoint availability does not mean every model supports that capability. See the OpenAI API reference for individual operations and limits.
3. Verify one request
Run this complete example after setting PRAXIS_API_KEY:
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY http_proxy https_proxy all_proxy
uv run -q --no-project --with openai --with anthropic python - <<'PY'
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.deepraxis.com/openai/v1",
api_key=os.environ["PRAXIS_API_KEY"],
timeout=90.0,
max_retries=0,
)
models = client.models.list(extra_query={"api": "chat"})
assert "deepseek-flash" in {m.id for m in models.data}
raw = client.chat.completions.with_raw_response.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "Reply OK."}],
max_tokens=1024,
)
reply = raw.parse()
text = reply.choices[0].message.content
print("HTTP", raw.status_code)
print("X-Request-Id:", raw.headers.get("x-request-id"))
print("X-Praxis-Generation-Id:", raw.headers.get("x-praxis-generation-id"))
print(text)
assert raw.status_code == 200 and text and text.strip()
assert raw.headers.get("x-request-id")
PYExpected: exit code 0, HTTP 200, nonempty text (usually OK.), and an X-Request-Id. Assertions check both model availability and a real reply, not just connectivity. Keep the request ID for troubleshooting, never the key. The example incurs a small usage charge.
Failures
| Observed error | Action |
|---|---|
404 with Model "gpt-4o" does not exist. | Change the model as well as the URL and key; use the exact catalog ID |
404 model_protocol_not_offered | Use a model that offers the requested operation; for Responses choose deepseek-flash or glm-5.3-flash |
404 Not Found on an endpoint above | Use its alternative or leave that request on the original service |
4. Roll back
Restore all three original values: https://api.openai.com/v1, the key from OPENAI_API_KEY, and your original model ID. Remove Praxis-only request fields and restore original resource IDs. Restart the application so its client uses the restored configuration, then run your original smoke test. Keep its request ID.
Expected: the original endpoint returns a successful response with usable text. Rolling back configuration does not refund calls already made or copy conversation state between services.