OpenAI-Compatible Endpoints: An Engineer’s Walkthrough
An OpenAI-compatible endpoint promises a familiar integration surface, not identical behavior from every model behind it. The useful engineering question is therefore not whether your SDK connects, but whether your application’s complete workflow survives the switch. Use this walkthrough to separate connection setup from production readiness.
1. Define the compatibility contract
Start by listing the API operations your application actually uses. OpenAI documents separate endpoints, request schemas, response schemas, and streaming events; matching one operation does not establish support for the others. ([developers.openai.com](https://developers.openai.com/api/reference/overview?utm_source=openai)) Treat compatibility as a checklist rather than a binary label.
- Transport: Authentication, request paths, HTTP responses, and streaming.
- Schema: Message roles, content blocks, tool definitions, and output fields.
- Behavior: Instruction following, refusal handling, and tool selection.
Record which features are required, optional, or deliberately unsupported. This turns an ambiguous migration into a testable contract.
2. Configure the destination explicitly
The official OpenAI Python SDK exposes configuration for api_key and base_url, allowing the destination and credentials to be configured separately. ([github.com](https://github.com/openai/openai-python/blob/main/src/openai/_client.py?utm_source=openai)) For CodeRelay Hub, use the supplied API base on the host api.coderelayhub.com over HTTPS and a workspace API key. Keep credentials in a server-side secret store or environment configuration, never in browser bundles.
Check the provider’s configuration instructions before adding a version prefix. Do not guess whether the base requires /v1, and do not append /chat/completions to a base that the SDK will extend itself. Inspect the final request path during development, with authorization headers redacted.
3. Prove one minimal request
For a supported Chat Completions route, start with model and messages, disable streaming, and ask for a short response. The documented response shape includes choices containing an assistant message, along with completion metadata. ([developers.openai.com](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create)) Assert the fields your application consumes rather than merely checking for HTTP success.
Copy the exact API model identifier from the provider’s catalog; a display name such as Gemini 2.5 Flash is not necessarily the request identifier. Leave optional sampling settings out initially. Add each required parameter separately so a rejected field has an obvious cause.
4. Test streaming as a separate integration
OpenAI’s Chat Completions streams deliver incremental delta objects, while Responses streams use typed semantic events. These are different parsing contracts, not interchangeable formats. ([developers.openai.com](https://developers.openai.com/api/docs/guides/streaming-responses?utm_source=openai)) Match your consumer to the specific API surface supported by the endpoint.
Test cancellation, an interrupted connection, and an empty text delta. Verify that your interface distinguishes partial output from successful completion. If you request streamed usage, account for missing final accounting: OpenAI documents that an interrupted stream may never deliver its final usage chunk. ([developers.openai.com](https://developers.openai.com/api/reference/resources/chat/subresources/completions/streaming-events?utm_source=openai)) Do not silently treat missing usage as zero.
5. Exercise the complete tool loop
Function calling involves more than receiving a function name. The application must process the call, execute the permitted operation, return its result, and continue the conversation. OpenAI’s documentation describes this as a multistep exchange. ([developers.openai.com](https://developers.openai.com/api/docs/guides/function-calling)) Build a harmless test tool before enabling operations with side effects.
Validate arguments against your own schema and authorization rules before execution. Test malformed arguments, multiple calls, and tool failures. For structured output, validate the returned object with your application’s schema validator. Make successful parsing and valid business data separate acceptance checks.
6. Budget retries and observe failures
The official Python SDK automatically retries selected connection failures and HTTP errors, and exposes timeout and max_retries controls. ([github.com](https://github.com/openai/openai-python/blob/main/README.md?plain=1&utm_source=openai)) Configure these explicitly instead of layering application retries over unknown SDK defaults.
Set an overall request deadline and a bounded retry budget. Treat an interrupted generation as an uncertain outcome, especially after a tool might have executed. Log the selected model, endpoint operation, elapsed time, attempt count, and available request identifiers. Redact secrets and sensitive prompt content.
7. Promote workflows, not connection tests
Before rollout, run representative conversations through every client you intend to use, including Claude Code, Codex, or Gemini CLI where configured. Verify each client’s protocol and required features rather than assuming one successful SDK request proves compatibility. With a pay-as-you-go hub such as CodeRelay Hub, keep model selection configurable and monitor usage alongside application quality. Introduce fallback routes only after testing their behavior against the same acceptance suite.
Open a free workspace to test your integration.