chat-completions-cookbook-languages · EN · 2026-10-06

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 YOURAPIKEY
  • Content-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 with role and content

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 temperature and max_tokens as needed.
  • Implement retry logic for production use.
  • Monitor usage and costs via your dashboard.