Calling /chat/completions from Python, Node, Go, Java and curl: A Copy-Paste Cookbook
A practical cookbook with minimal working examples for calling an OpenAI-compatible /chat/completions endpoint from Python, Node.js, Go, Java, and curl. Each example shows authentication headers, request structure, and basic error handling. Learn how to use one API key across multiple models with USDC on Base and no KYC.
Overview
Many providers expose an OpenAI-compatible /chat/completions endpoint. This means you can use the same request format and authentication headers across different models (Claude, GPT, DeepSeek, Qwen, GLM, Kimi) with a single API key. This cookbook provides copy-paste examples in five languages: Python, Node.js, Go, Java, and curl.
All examples assume you have an API key and a base URL. Replace YOURAPIKEY and BASE_URL with your actual values. The endpoint path is typically /v1/chat/completions.
Authentication and Common Headers
Most OpenAI-compatible APIs require two headers:
Authorization: Bearer YOURAPIKEYContent-Type: application/json
The request body includes at least:
model: the model identifier (e.g.,gpt-4,claude-3-opus)messages: an array of message objects withroleandcontent
Optional parameters like temperature and max_tokens may be supported. Check the provider's documentation for model names and available parameters.
Python
Using the requests library (install with pip install requests):
import requests
import json
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.example.com/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": "gpt-4",
"messages": [
{"role": "user", "content": "Hello, how are you?"}
]
}
try:
response = requests.post(
f"{BASE_URL}/chat/completions",
headers=headers,
json=payload,
timeout=30
)
response.raise_for_status()
data = response.json()
print(data["choices"][0]["message"]["content"])
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e}")
print(f"Response: {e.response.text}")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
Python's requests automatically encodes JSON and handles common exceptions. Always check the response status.
Node.js
Using the built-in fetch (Node.js 18+):
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.example.com/v1';
async function chat() {
const response = await fetch(`${BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello, how are you?' }]
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const data = await response.json();
console.log(data.choices[0].message.content);
}
chat().catch(console.error);
Node.js's fetch returns a promise. Always check response.ok before parsing JSON.
Go
Using the standard net/http package:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
apiKey := "YOUR_API_KEY"
baseURL := "https://api.example.com/v1"
payload := map[string]interface{}{
"model": "gpt-4",
"messages": []map[string]string{
{"role": "user", "content": "Hello, how are you?"},
},
}
jsonData, _ := json.Marshal(payload)
req, err := http.NewRequest("POST", baseURL+"/chat/completions", bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Request failed:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
fmt.Printf("HTTP %d: %s\n", resp.StatusCode, string(body))
return
}
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
fmt.Println("Error parsing JSON:", err)
return
}
choices := result["choices"].([]interface{})
message := choices[0].(map[string]interface{})["message"].(map[string]interface{})
fmt.Println(message["content"])
}
Go requires explicit error checking. Always close the response body.
Java
Using java.net.http.HttpClient (Java 11+):
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class ChatExample {
public static void main(String[] args) throws Exception {
String apiKey = "YOUR_API_KEY";
String baseUrl = "https://api.example.com/v1";
String jsonPayload = """
{
"model": "gpt-4",
"messages": [
{"role": "user", "content": "Hello, how are you?"}
]
}
""";
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/chat/completions"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
System.err.println("HTTP " + response.statusCode() + ": " + response.body());
return;
}
System.out.println(response.body()); // Parse JSON to extract content
}
}
Java's HttpClient is built-in. For JSON parsing, consider a library like Jackson or Gson.
curl
A simple curl command:
curl -X POST https://api.example.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello, how are you?"}]
}'
To see HTTP status and errors, add -i or -v. Use jq to parse the response:
curl -s -X POST https://api.example.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4","messages":[{"role":"user","content":"Hello"}]}' \
| jq -r '.choices[0].message.content'
Error Handling Patterns
Common HTTP errors and how to handle them:
- 401 Unauthorized: Invalid or missing API key. Check your key.
- 429 Too Many Requests: Rate limit exceeded. Implement exponential backoff.
- 5xx Server Errors: Retry with backoff.
- 4xx Client Errors: Check request body and parameters.
Always log the full error response for debugging. Most APIs return a JSON error object with details.
Using the Aggregator Service
The aggregator service provides an OpenAI-compatible endpoint, so the examples above work with minimal changes: replace BASEURL with the aggregator's base URL and YOURAPI_KEY with your key.
You top up with USDC on Base (no KYC) and get one API key for many models. Pricing is official price × 1.3 for users; key contributors are credited official price × 1.1 (premium × 1.2) in USDC.
Next Steps
- Explore available models and their identifiers.
- Adjust
temperatureandmax_tokensas needed. - Implement retry logic for production use.
- Monitor usage and costs via your dashboard.