Is It the SDK, the Shim, or the Aggregator? Isolating the Fault Layer with a Raw curl Baseline
When an API call fails, the fault could lie in your SDK, a compatibility shim, or the aggregator. This guide shows how to isolate the responsible layer by constructing a raw HTTP request with curl, comparing it to your client's behavior, and using that evidence to pinpoint the issue before reporting it.
When an API call fails, the error might originate from your application code, the SDK you're using, a compatibility shim (like an OpenAI-to-Anthropic adapter), the network, or the aggregator itself. Before you file an issue or start debugging blindly, strip the call down to a raw HTTP request. This lets you see exactly what's sent and received, and compare it to what your client stack produces.
Why a Raw curl Baseline Matters
SDKs and shims add layers of abstraction. They modify headers, transform request bodies, retry, and parse responses. When something breaks, these layers can mask the true cause. A raw curl request bypasses all of that, giving you a ground truth: what does the aggregator actually receive and return when you send a minimal, well-formed request?
If the raw request succeeds, the fault is likely in your client stack (SDK, shim, or your own code). If it fails, the issue may be with the aggregator or the network. Either way, you have a clear signal.
Step 1: Capture What Your Client Sends
Before you craft a curl command, capture the exact request your client makes. Most SDKs provide a debug mode or allow logging of HTTP requests. For example, in Python's requests library you can enable logging, or in Node.js you can use a tool like NODE_DEBUG=http. Alternatively, use a proxy like mitmproxy to inspect the traffic.
Focus on:
- The full URL and HTTP method.
- All headers (including
Authorization,Content-Type, and any custom headers). - The raw request body (if any).
You don't need to replicate every detail in curl, but you need to know what your client is doing differently.
Step 2: Construct a Minimal curl Request
Start with the simplest possible request to the same endpoint. Use the official API base URL for the aggregator. For example, to list models (a common health-check endpoint):
curl -X GET https://api.example-aggregator.com/v1/models \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"
Replace YOURAPIKEY with your actual key. If you're testing a chat completion, use a minimal JSON body:
curl -X POST https://api.example-aggregator.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-3-5-sonnet-20241022",
"messages": [{"role": "user", "content": "Hello"}],
"max_tokens": 10
}'
Adjust the model name to one you know is available. Keep the body as simple as possible: no streaming, no tools, no extra parameters. This isolates the core functionality.
Step 3: Analyze the Response
Run the curl command and inspect both the HTTP status code and the response body. Use -i to include headers in the output, or -v for verbose mode.
- If you get a 2xx status and a valid response: The aggregator is working with a minimal request. The problem likely lies in your client stack—perhaps the SDK is adding malformed headers, the shim is rewriting the body incorrectly, or your code is sending invalid parameters.
- If you get a 4xx status: Check the error message. It might indicate an issue with your API key, a malformed request, or an unsupported model. Compare the request body and headers to what your client sends.
- If you get a 5xx status: The aggregator may be experiencing issues. Retry once, then check the aggregator's status page or support channels.
- If the request times out or fails to connect: There may be a network problem or the aggregator endpoint might be down.
Step 4: Compare and Isolate
Now that you have a baseline, incrementally add complexity to match your client's request.
- Add headers one by one: Start with
AuthorizationandContent-Type. Then add any custom headers your client uses. If a header causes failure, you've found a suspect. - Modify the body: Begin with a minimal body, then add parameters like
stream,temperature, ortools. If the request fails only when a specific parameter is present, the issue may be with that parameter's handling by the aggregator or a shim. - Test with and without the shim: If you're using a shim (e.g., to translate between API formats), try sending a request in the native format of the aggregator. If that works but the shimmed request fails, the shim is likely at fault.
Step 5: Use the Evidence
Once you've isolated the layer, you can act:
- SDK issue: Check the SDK's documentation or issue tracker. Try a different version or a different SDK. You can also report the issue with your curl baseline as evidence.
- Shim issue: Review the shim's configuration and transformation logic. If it's a third-party shim, consider filing an issue with the maintainers.
- Aggregator issue: If the raw request fails consistently and you've ruled out client-side problems, contact the aggregator's support with the exact curl command (redact your API key) and the response you received. This gives them a reproducible case.
Best Practices
- Keep your API key secure: Never share it in issues or logs. Use environment variables in curl commands (e.g.,
$API_KEY) and redact it when sharing. - Document your baseline: Save the curl command and its output. This becomes a reference point for future debugging.
- Test incrementally: Change one variable at a time to avoid confusion.
- Check the aggregator's documentation: Ensure you're using the correct base URL and endpoints. The aggregator may have specific requirements for headers or request formats.
By following these steps, you can quickly determine whether the fault lies in your SDK, a shim, or the aggregator itself, and provide precise information when seeking help.