cd /news/developer-tools/the-3-step-smoke-test-i-use-for-any-… · home topics developer-tools article
[ARTICLE · art-55978] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

The 3-step smoke test I use for any OpenAI-compatible API

A developer at DaoXE published a three-step smoke test for verifying OpenAI-compatible API endpoints. The test isolates authentication, model availability, and a minimal chat completion call using the OpenAI SDK. The approach is designed to quickly confirm that a specific account, endpoint, model, and runtime can complete a single request.

read4 min views1 publishedJul 12, 2026

Disclosure and availability:DaoXE is a service we operate. It is not available in mainland China. This article is for developers in regions allowed by the service terms.

Changing baseURL

in an OpenAI SDK takes one line. Proving that the new endpoint is configured correctly is the harder part.

When an integration fails, it is tempting to change the API key, model, prompt, timeout, and response parser at the same time. That usually creates more uncertainty. I prefer a three-step smoke test that isolates one layer at a time:

The result is not a benchmark or a reliability guarantee. It is a repeatable way to answer a narrower question: can this exact account, endpoint, model, and runtime complete one request right now?

This walkthrough uses DaoXE as the example endpoint, but the same sequence works with other OpenAI-compatible services.

Start with the API key and base URL. Do not put a real key in source code, screenshots, issue reports, or shell snippets that will be committed.

export DAOXE_API_KEY="your_api_key"
export DAOXE_BASE_URL="https://daoxe.com/v1"

Do not set the model yet. Model access can vary by account and can change over time. Copying a model name from an old tutorial adds an unnecessary variable before authentication has even been checked.

If you use a .env

file locally, make sure it is ignored by Git. In production, use the secret manager provided by your deployment platform.

Call the Models endpoint first:

curl --fail-with-body --show-error --silent \
  "${DAOXE_BASE_URL}/models" \
  -H "Authorization: Bearer ${DAOXE_API_KEY}"

This request checks two things without running a generation:

If jq

is installed, reduce the response to model IDs:

curl --fail-with-body --show-error --silent \
  "${DAOXE_BASE_URL}/models" \
  -H "Authorization: Bearer ${DAOXE_API_KEY}" \
  | jq -r '.data[].id'

Choose one ID from that response and copy it exactly:

export DAOXE_MODEL="copy_an_exact_id_from_the_current_response"

Avoid permanently hard-coding a model name from documentation. A successful request in somebody else's account does not prove that the same ID is available to your account today.

Create an empty Node.js project and install the OpenAI SDK:

npm init -y
npm install openai

Create smoke-test.mjs

:

import OpenAI from "openai";

const required = ["DAOXE_API_KEY", "DAOXE_BASE_URL", "DAOXE_MODEL"];
const missing = required.filter((name) => !process.env[name]);

if (missing.length > 0) {
  console.error(`Missing environment variables: ${missing.join(", ")}`);
  process.exit(1);
}

const client = new OpenAI({
  apiKey: process.env.DAOXE_API_KEY,
  baseURL: process.env.DAOXE_BASE_URL,
  timeout: 30_000,
  maxRetries: 0,
});

const startedAt = performance.now();

try {
  const response = await client.chat.completions.create({
    model: process.env.DAOXE_MODEL,
    messages: [{ role: "user", content: "Reply with only OK." }],
    max_tokens: 8,
  });

  const elapsedMs = Math.round(performance.now() - startedAt);
  console.log({
    ok: true,
    elapsedMs,
    model: response.model,
    content: response.choices?.[0]?.message?.content,
    usage: response.usage,
  });
} catch (error) {
  const elapsedMs = Math.round(performance.now() - startedAt);
  console.error({
    ok: false,
    elapsedMs,
    status: error.status,
    type: error.name,
  });
  process.exit(1);
}

Run it:

node smoke-test.mjs

This request can incur a charge. Check the live model catalog, account status, and pricing before running it.

The max_tokens: 8

limit keeps the connectivity check small; it is not a recommendation for normal application traffic. I also set maxRetries: 0

on purpose. During first-pass debugging, an automatic retry can hide the original failure or turn one uncertain request into several billable requests.

A successful run proves that, at that moment, the following combination completed one request:

It does not prove long-term availability, output quality, latency distribution, or total application cost.

For a useful test record, keep the timestamp, environment, HTTP result, elapsed time, returned model field, and token usage. Do not log the API key or the complete Authorization

header.

Symptom Check first Next action
401
Empty, expired, or whitespace-padded key Re-inject the key securely, then repeat the Models request
403
Account permissions or regional eligibility Review the account state and service terms; do not try to bypass the restriction in code
404
Versioned baseURL and combined resource path
Print only non-sensitive URL configuration and inspect the final path
Model not found Whether the ID came from the current Models response Discover the models again and copy the ID exactly
429
Current rate, quota, and account state Read the response details before choosing a backoff policy
Timeout or network error DNS, TLS, proxy, and runtime egress Run the Models request from the same environment to separate network and generation failures
5xx
Temporary service or upstream failure Save the timestamp and request identifier, then retry a limited number of times later

The important rule is to change one layer at a time. If authentication is failing, changing the prompt cannot help. If model discovery works but generation fails, the problem is already narrower.

Retries are not automatically safe. A request may have executed on the server even when the client did not receive the response. Blindly retrying can duplicate work and cost.

Before enabling retries, decide:

I split CI into two layers:

That catches code regressions without sending a billable request on every commit. Secret masking is helpful, but the safer default is still never to print the secret.

For any OpenAI-compatible endpoint, the shortest useful validation sequence is:

If your region is supported by the service terms, you can inspect DaoXE. The public examples include cURL, Node.js, Python, and Postman, plus Simplified Chinese and Traditional Chinese guides.

── more in #developer-tools 4 stories · sorted by recency
── more on @daoxe 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/the-3-step-smoke-tes…] indexed:0 read:4min 2026-07-12 ·