aiml docs
Migrate

From OpenAI

Keep the SDK and the code; change the base URL, the key and the model id.

The three changes

  1. Base URL https://api.openai.com/v1 becomes https://api.ai.ml/v1.
  2. Key sk-… becomes aiml-live-… (create one in the console, inference scope).
  3. Model gpt-5-mini becomes openai/gpt-5-mini. Every model is vendor/model; a bare OpenAI model name is also accepted and resolves to openai/<name>.
cookbook/ts/streaming.ts#L5-L8
const client = new OpenAI({
  baseURL: (process.env.AIML_BASE_URL ?? "https://api.ai.ml") + "/v1",
  apiKey: process.env.AIML_API_KEY,
});

What stays the same

  • Chat Completions request and response bodies, including tools, tool_choice, response_format (json_object and json_schema), stream, stream_options, n, seed, logprobs, stop, penalties and user.
  • Streaming frames (chat.completion.chunk, data: [DONE]).
  • The error envelope {"error":{"message","type","param","code"}}. code carries the aiml code, which is more specific than OpenAI's; see Errors.

What is different

TopicOpenAIaiml
Request idx-request-id headerx-aiml-request-id header and the response id
Costnot returnedaiml.cost.total_micro_usd in the body, x-aiml-cost-micro header
Usage on streamsstream_options.include_usagesame; the last chunk also carries aiml
Rate limitsper organisationper key (rpm, tpm, concurrency), see Rate limits
Billingpostpaidprepaid credits; 402 insufficient_credits when the balance cannot cover the reserve
Routingone providerseveral endpoints per model; aiml.route steers it

Steering the route

The optional aiml object on the request carries what the OpenAI format cannot express:

{
  "model": "openai/gpt-5-mini",
  "messages": [{ "role": "user", "content": "hi" }],
  "aiml": {
    "route": {
      "providers": { "order": ["openai", "azure"] },
      "require": { "regions": ["eu"], "zdr": true, "max_price": { "output": 2.5 } },
      "sort": "latency",
      "fallbacks": true,
      "ttft_budget_ms": 1500
    },
    "metadata": { "app": "support-bot", "tags": { "tier": "free" } }
  }
}

route.providers (only, ignore, order) and route.require (regions, zdr, data_policy, max_price in USD per million tokens, reasoning) narrow the candidate endpoints; sort, fallbacks, affinity, stream_retry, schema_retry, ttft_budget_ms and max_duration_ms shape how they are tried. metadata (app, user_id, tags) lands in analytics and on the generation record.

The Responses API

/v1/responses takes the same body the OpenAI SDK sends (client.responses.create): input as a string or items, instructions, tools (function and hosted: web_search_preview, file_search, code_interpreter, image_generation), tool_choice, text.format, reasoning, include, max_output_tokens, temperature, top_p, stream, user, metadata. Streaming returns the named events (response.createdresponse.completed) with sequence_number; the final response.completed object carries usage and aiml.

cookbook/curl/responses.sh#L9-L13
curl -sS "$BASE/v1/responses" \
  -H "Authorization: Bearer $AIML_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"model\":\"${AIML_MODEL:-openai/gpt-5}\",\"input\":\"Say hello in one short sentence.\",\"max_output_tokens\":64,\"store\":false}" \
  | python3 -c '

The gateway is stateless, which changes three things:

TopicOpenAIaiml
storeresponses are stored for 30 daysnever stored; store: true is ignored with a param_dropped warning and store: false is what reaches the provider
previous_response_id, conversation, item_referencecontinue a stored response422 unsupported_feature.previous_response_id (or .conversation, .item_reference); send the full history as input items
Reasoning across turnsthe stored response carries itask for include: ["reasoning.encrypted_content"] (the gateway adds it whenever reasoning is set) and replay the returned reasoning item as is; its encrypted_content is what lets the model continue

Every model behind the gateway is reachable through /v1/responses, including providers that speak another wire format: items translate to the IR and back, so input_image, input_file, function_call / function_call_output and text.format: json_schema work against Anthropic and Gemini endpoints too, with aiml.warnings listing anything the endpoint could not honour.

On this page