DEV Community

Cover image for One API for GPT and Claude, Without Pretending They're Interchangeable
Olivia Hayes
Olivia Hayes

Posted on Originally published at cometapi.com

One API for GPT and Claude, Without Pretending They're Interchangeable

I want model routing to be boring: one place for credentials, explicit model IDs, and request builders I can test. I don't want a shared API to conceal differences that matter in production.

For common chat workloads, CometAPI provides that shared layer: one key and an OpenAI-compatible base URL, https://api.cometapi.com/v1, for supported OpenAI and Anthropic models. The same account also exposes OpenAI Responses, Anthropic Messages, and Gemini-native content generation.

That gives me a choice of contracts, not a guarantee of identical behavior. My application still owns parameter compatibility, token accounting, quality checks, and fallback decisions.

Start with the request contract

I choose the endpoint before choosing how much routing logic to share.

Contract When I'd use it
/v1/chat/completions Common chat requests that need portability across supported models
/v1/responses OpenAI workflows whose selected model or advanced features fit Responses
/v1/messages Claude workflows that depend on native request fields or response content blocks

For a minimal compatible chat request, switching models can mean changing only model. Once tools, images, reasoning controls, caching, or provider-specific fields enter the picture, that assumption needs testing.

I keep model IDs in configuration and separate request builders wherever endpoint contracts diverge. A router should select a compatible request path, not silently discard unsupported features.

Two clients, one credential

Before adding application logic, I verify current IDs and endpoints through GET https://api.cometapi.com/api/models or the public model directory. Then I pin explicit IDs in environment variables rather than embedding aliases throughout the codebase.

The examples below expect COMETAPI_KEY plus the relevant model variables to be set. Credentials stay out of source control.

Shared Chat Completions path

For supported models, a single OpenAI client can issue the same common chat request to either family:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["COMETAPI_KEY"],
    base_url="https://api.cometapi.com/v1",
)

for model in [os.environ["PRIMARY_MODEL"], os.environ["SECONDARY_MODEL"]]:
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "user", "content": "Summarize this request in one sentence."}
        ],
    )
    print(model, response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

The shared setup is the useful part. It doesn't establish that both models support every field accepted by the SDK.

For each candidate, I record the model ID, endpoint, status, usage, latency, and any error body from a minimal request before adding tools or multimodal inputs.

Native Claude Messages path

If the application already relies on Anthropic content blocks, prompt caching, effort controls, or other Messages-specific behavior, I'd retain the native contract:

import os
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ["COMETAPI_KEY"],
    base_url="https://api.cometapi.com",
)

message = client.messages.create(
    model=os.environ["CLAUDE_MODEL"],
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Summarize this request in one sentence."}
    ],
)
print(message.content[0].text)
Enter fullscreen mode Exit fullscreen mode

Notice the different base URLs: the OpenAI client uses /v1; the Anthropic client uses the host root and calls /v1/messages.

After these minimal paths work, I add streaming, tools, caching, and multimodal input individually. Debugging one compatibility boundary at a time is preferable to diagnosing an entire agent stack at once.

The compatibility checks I'd put before routing

A common SDK interface is not a common feature set.

OpenAI models

Check the model's listed endpoints rather than assuming Chat Completions and Responses are interchangeable. Some reasoning and coding families have fuller support on Responses.

Newer models may require max_completion_tokens. Send reasoning_effort, logprobs, and other advanced fields only when the selected model supports them.

Anthropic models

The gateway compatibility table described in the source lists these constraints for the OpenAI-compatible Claude route:

  • temperature: 0 to 1.
  • n: 1.
  • logprobs: unsupported.
  • reasoning_effort: unsupported.

That last point does not mean Claude-native effort controls are the same thing as OpenAI's reasoning_effort. If I need native behavior, I use Messages and verify the supported fields there.

Both families

Before deploying, I check current IDs, capabilities, endpoint support, context limits, and prices. I also check output structure and token accounting rather than assuming a successful request proves semantic compatibility.

Compare specific models, not provider reputations

I wouldn't pick a production route from “OpenAI versus Anthropic” as an abstract debate. The useful comparison is between explicit models on a defined task.

The following figures are the source article's catalog snapshot, reported as checked on August 31, 2026. They are not fresh verification or benchmark results. Prices are per 1 million input/output tokens; verify the live records before using them for deployment or budgeting.

Model Context and inputs Listed endpoints Input / output price Workloads to evaluate
GPT-5.6 Sol, gpt-5.6-sol 1.05M context; text and image /v1/responses, /v1/chat/completions Short context: $3.20 / $16; above 272K input: $6.40 / $24 Complex reasoning, long-horizon agents, demanding coding, research, high-impact technical work
GPT-5.6 Luna, gpt-5.6-luna 1.05M context; text and image /v1/responses, /v1/chat/completions Short context: $0.16 / $0.96; above 272K input: $0.32 / $1.44 Classification, summaries, routine support, monitoring, high-volume tasks with clear acceptance criteria
Claude Fable 5, claude-fable-5 1M context; up to 128K output; text and image /v1/messages, /v1/chat/completions $8 / $40 Repository-scale coding, professional analysis, large-document reasoning, long-running agents
Claude Haiku 4.5, claude-haiku-4-5-20251001 200K context; text, image, and PDF /v1/messages, /v1/chat/completions $0.80 / $4 Fast chat, extraction, lightweight coding, sub-agents, scaled automation

A few constraints matter more than the headline prices:

  • The generic gpt-5.6 alias routes to Sol.
  • Above 272K input tokens, the higher GPT-5.6 rate applies to the whole request.
  • Fable 5 has the highest unit cost in this set. Its safety classifiers can redirect certain high-risk cyber, biology, chemistry, or model-distillation requests.
  • Haiku 4.5 has less context and lower frontier capability than the flagship options; production routing still needs quality validation.
  • Luna's lower token price does not establish lower workflow cost. Retries, review effort, and accepted-output rate count.

I treat this table as a shortlist, not a leaderboard.

Build an evaluation that matches the application

No controlled benchmark was run for the source article, so there are no measured latency or quality scores to inherit.

My comparison would run both families through the same application path, holding these constant:

  • Prompt set and system instructions.
  • Output cap.
  • Region and measurement window.
  • Parameters supported by both routes.

Where support differs, I record the difference instead of forcing a misleading match.

After a short warm-up, I'd collect at least 20 measured requests per model, including:

Metric Why I want it
Time to first token Streaming responsiveness
Total latency End-to-end completion time
Success rate Whether the route reliably completes requests
Input and output tokens Observed usage
Estimated cost Cost at current rates
Task-specific quality score Whether the output is usable

Report p50 and p95 latency, not just an average. Repeat the evaluation when versions or traffic patterns change.

The rubric should follow the workload:

Tool-heavy or structured output: test schema adherence, tool-call accuracy, and recovery from invalid tool results. Requirements such as OpenAI-specific reasoning controls or log probabilities can eliminate candidates before quality testing.

Analysis, writing, and code review: include Claude in the shortlist, but compare against an OpenAI model using the same source material and review rubric. A compelling demo prompt isn't an evaluation.

High-volume tasks: test efficiency-oriented models from both families. I want the cheapest route that clears the reliability and quality thresholds, not the cheapest input-token line item.

Budget for accepted outputs

For rates quoted per million tokens, the basic estimate is:

estimated_cost =
    (input_tokens / 1_000_000) * input_rate
  + (output_tokens / 1_000_000) * output_rate
  + model_specific_usage_charges
Enter fullscreen mode Exit fullscreen mode

I use live rates and observed usage, including any additional usage units listed in the catalog. Cached input and reasoning-token behavior also need evaluation when the selected model reports them.

The practical controls are straightforward: trim repeated context, cap output, log usage, and route routine tasks to the smallest model that meets the quality threshold.

Hard-coded prices and evergreen discount assumptions are a maintenance liability. More importantly, token savings disappear quickly if the cheaper model needs retries or manual correction.

Make fallback narrower than “try Claude next”

A cross-family fallback can reduce dependence on one model route, but only if the backup supports the actual workload:

  • Required input types and context size.
  • Tools and output structure.
  • Request parameters.
  • Latency budget.

If the primary request contains OpenAI-specific fields that the Claude route rejects, translate or remove them explicitly. I wouldn't leave that decision hidden inside a generic retry wrapper.

My route order would be:

  1. Primary gateway model.
  2. A second capability-compatible gateway model.
  3. An optional direct-provider route, only when its account is configured and intentionally enabled.

Fallback is appropriate for connection errors, timeouts, 408, 429, and temporary 5xx failures. It is not a fix for invalid requests, invalid API keys, or unsupported parameters.

Each route needs a timeout derived from the application's total latency budget: sequential fallbacks add delay. Every backup also needs testing with the same request shape and required capabilities as the primary.

The boundary I want is simple: shared credentials and transport where useful, explicit model contracts everywhere they affect correctness.

Top comments (0)