Verifying Your First /chat/completions Call With curl Before Writing Any App Code
Use a short, copy-paste curl sequence to validate authentication, model alias resolution, and streaming against the aggregator's OpenAI-compatible endpoint before you install any SDK. This isolates integration problems from application bugs.
Why test with curl first
Every SDK adds its own layer: environment variables, retries, serialization, streaming wrappers. When a first request fails, you cannot tell whether the problem is your key, the model name, the transport, or your app. A few raw HTTP calls remove that ambiguity. If curl works, any later failure is almost certainly in your application code.
The aggregator exposes an OpenAI-compatible /chat/completions endpoint, so the same payload shape you test here carries over to most SDKs.
Prerequisites
- A topped-up account. Top-ups are made with USDC on Base without KYC; your balance is consumed as you make calls at official price × 1.3.
- An API key from the dashboard.
curlinstalled. A JSON pretty-printer such asjqis helpful but optional.
Keep the key in an environment variable rather than pasting it into shell history:
export AGG_KEY="your_api_key_here"
export AGG_BASE="https://your-aggregator-host/v1"
Adjust AGG_BASE to the base URL shown in the docs.
Step 1: Confirm auth with a minimal non-streaming call
Start with the smallest possible request. This checks the key, the base URL, and basic connectivity in one shot.
curl -sS "$AGG_BASE/chat/completions" \
-H "Authorization: Bearer $AGG_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-20250514",
"messages": [{"role": "user", "content": "Reply with the single word: ok"}]
}' | jq .
Replace the model with any identifier accepted by the aggregator. What to look for:
- HTTP 200 and a JSON body containing
choices[0].message.content. - 401/403 means the key is wrong, missing, or not yet active.
- 402 or a balance-related error means the account needs a top-up.
- 404 usually means the base URL or path is wrong.
If you get a valid completion, authentication and routing are working.
Step 2: Verify model alias resolution
The aggregator maps friendly model names to upstream endpoints. A typo or an unsupported alias is a common first failure, so test it explicitly.
- Send the model you actually plan to use in production, not a placeholder.
- Check the response's
modelfield. Providers often echo back the resolved or canonical model name, which tells you what actually served the request. - If the alias is rejected, the error body typically lists the problem. Fix the name here rather than debugging it inside an SDK.
curl -sS "$AGG_BASE/chat/completions" \
-H "Authorization: Bearer $AGG_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "your-production-model-alias",
"messages": [{"role": "user", "content": "Say hello in five words."}],
"max_tokens": 64
}' | jq '{model, usage, content: .choices[0].message.content}'
Printing model and usage together confirms two things: the alias resolved, and the call was billed. Usage figures show how consumption maps to your USDC balance.
Step 3: Exercise streaming
Streaming is where integrations break most often, because it changes the response from one JSON object to a series of server-sent events. Test it with raw curl before trusting any SDK's stream handling.
curl -sS -N "$AGG_BASE/chat/completions" \
-H "Authorization: Bearer $AGG_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "your-production-model-alias",
"messages": [{"role": "user", "content": "Count from one to five."}],
"stream": true
}'
Expect lines beginning with data:, each carrying a small delta, terminated by data: [DONE]. Things to check:
- Deltas arrive incrementally rather than as one blob;
-Ndisables curl buffering so you can see this. - The final chunk includes a finish reason and, where provided, usage.
- No
errorobject appears mid-stream.
If streaming fails here, the issue is between you and the aggregator, not in your app's stream parser.
Step 4: Test the error paths deliberately
Good integrations handle failures. Reproduce them cheaply with curl:
- Send an invalid model alias and observe the error shape.
- Send a request with the
Authorizationheader omitted to confirm the 401 body. - Send a malformed JSON body to see how validation errors are returned.
Knowing these shapes now means your app can log and surface them correctly later.
Step 5: Record a baseline before moving to an SDK
Once all three calls succeed, you have a known-good reference. Save the working commands in a scratch file. When an SDK call fails, replay the curl request with the same model and payload. If curl still works, the bug is in your code; if it fails, something changed on the account or endpoint.
What this sequence does and does not cover
It verifies authentication, alias resolution, streaming, error shapes, and that billing is recorded. It does not test concurrency, long prompts, tool calls, or multi-turn state, which depend on the models you choose and how your app manages context. Treat the curl pass as a gate before integration, not a substitute for application testing.
When you are confident the endpoint behaves as expected, install your SDK, point it at the same base URL and key, and reuse the same model aliases.