{
  "components": {
    "schemas": {
      "APIKey": {
        "type": "object"
      },
      "ChatCompletion": {
        "type": "object"
      },
      "Model": {
        "description": "An upstream model.",
        "properties": {
          "aliases": {
            "description": "Aliases callers can use in the request `model` field that resolve to this model via the default mapping.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "configured": {
            "description": "Whether an upstream credential is currently mounted for this provider. Unconfigured models cannot be routed to.",
            "type": "boolean"
          },
          "context_window": {
            "description": "Maximum total tokens (prompt + completion) the upstream accepts.",
            "type": "integer"
          },
          "id": {
            "description": "Concrete upstream model id, e.g. `gpt-4o-mini`.",
            "type": "string"
          },
          "pricing": {
            "description": "USD per million tokens for `prompt` and `completion`.",
            "type": "object"
          },
          "provider": {
            "description": "Upstream vendor — `openai`, `gemini`, `deepseek`.",
            "type": "string"
          }
        },
        "type": "object",
        "x-sample": "{\n  \"id\":             \"gpt-4o-mini\",\n  \"provider\":       \"openai\",\n  \"aliases\":        [\"auto\", \"cheap\"],\n  \"context_window\": 128000,\n  \"pricing\": {\n    \"prompt\":     0.15,\n    \"completion\": 0.60\n  },\n  \"configured\":     true\n}\n",
        "x-sample-label": "The Model object"
      },
      "Route": {
        "description": "A routing rule.",
        "properties": {
          "action": {
            "description": "Resolution. For `pin`: `provider` + `model`.",
            "type": "object"
          },
          "action_kind": {
            "description": "`pin` sends to a fixed provider/model pair. `auto` defers to routeur.ai's picker.",
            "x-type": "pin | auto"
          },
          "created_at": {
            "description": "ISO-8601 UTC timestamp.",
            "x-type": "timestamp"
          },
          "enabled": {
            "description": "Disabled rules are skipped at runtime.",
            "type": "boolean"
          },
          "id": {
            "description": "Unique identifier, prefixed `route_`.",
            "type": "string"
          },
          "match": {
            "description": "Match condition. Currently supports `requested_model` (exact string match).",
            "type": "object"
          },
          "name": {
            "description": "Human-readable rule identifier surfaced in trace metadata as `rule:\u003cname\u003e`.",
            "type": "string"
          },
          "priority": {
            "description": "Higher numbers evaluate first.",
            "type": "integer"
          },
          "updated_at": {
            "description": "ISO-8601 UTC timestamp.",
            "x-type": "timestamp"
          }
        },
        "type": "object",
        "x-sample": "{\n  \"id\":          \"route_01J...\",\n  \"name\":        \"premium_demo\",\n  \"priority\":    100,\n  \"enabled\":     true,\n  \"action_kind\": \"pin\",\n  \"match\": {\n    \"requested_model\": \"demo-premium\"\n  },\n  \"action\": {\n    \"provider\": \"openai\",\n    \"model\":    \"gpt-4o\"\n  },\n  \"created_at\": \"2026-05-29T10:00:00Z\",\n  \"updated_at\": \"2026-05-29T10:00:00Z\"\n}\n",
        "x-sample-label": "The Route object"
      },
      "Trace": {
        "description": "A compact record persisted for every request through the gateway.",
        "properties": {
          "api_key_id": {
            "description": "Resolved caller key id.",
            "type": "string"
          },
          "cost_usd": {
            "description": "Estimate from the configured pricing table.",
            "type": "number"
          },
          "disclosed_bytes": {
            "description": "Bytes of model output that had already reached the caller when a chunked-moderation block aborted the stream (ADR-011 disclosure trade-off).",
            "type": "integer"
          },
          "latency_ms": {
            "description": "End-to-end latency measured by routeur.ai.",
            "type": "integer"
          },
          "model": {
            "description": "Final upstream model selected for the call.",
            "type": "string"
          },
          "organization_id": {
            "description": "Owning organisation for the request.",
            "type": "string"
          },
          "payload_url": {
            "description": "Short-lived signed URL to the full payload archive when payload storage is enabled.",
            "type": "string"
          },
          "prompt_tokens / completion_tokens / total_tokens": {
            "description": "Usage metrics returned by the upstream provider.",
            "type": "integer"
          },
          "provider": {
            "description": "Final upstream provider selected for the call.",
            "type": "string"
          },
          "redactions": {
            "description": "Number of input substitutions DLP made before the upstream call.",
            "type": "integer"
          },
          "request_id": {
            "description": "Stable id used across response metadata, trace records, and payload archives.",
            "type": "string"
          },
          "requested_model": {
            "description": "Model alias or string the caller originally sent.",
            "type": "string"
          },
          "route_reason": {
            "description": "`default` or `rule:\u003cname\u003e`.",
            "type": "string"
          },
          "status_code": {
            "description": "Caller-visible HTTP status code.",
            "type": "integer"
          },
          "stream_aborted": {
            "description": "True when a stream was cut after delivery began — a mid-stream upstream failure, a client disconnect, or a chunked output-moderation block.",
            "type": "boolean"
          },
          "streamed": {
            "description": "True when the response was delivered as a server-sent event stream.",
            "type": "boolean"
          },
          "ttfb_ms": {
            "description": "Time to first byte — ms from request start until the first response byte left the gateway. Streamed requests only.",
            "type": "number"
          }
        },
        "type": "object",
        "x-sample": "{\n  \"request_id\":        \"01K...\",\n  \"organization_id\":   \"org_42\",\n  \"api_key_id\":        \"key_01J...\",\n  \"provider\":          \"openai\",\n  \"model\":             \"gpt-4o-mini\",\n  \"requested_model\":   \"auto\",\n  \"route_reason\":      \"default\",\n  \"latency_ms\":        2939,\n  \"prompt_tokens\":     13,\n  \"completion_tokens\": 7,\n  \"total_tokens\":      20,\n  \"cost_usd\":          0.00000615,\n  \"status_code\":       200,\n  \"redactions\":        1,\n  \"streamed\":          true,\n  \"ttfb_ms\":           184,\n  \"payload_url\":       \"https://payloads.routeur.ai/...?sig=...\"\n}\n",
        "x-sample-label": "The Trace object"
      }
    },
    "securitySchemes": {
      "bearer_auth": {
        "description": "All requests authenticate with a bearer token.\nSee [Authentication](/guides/authentication).\n",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {
      "name": "routeur.ai",
      "url": "https://routeur.ai"
    },
    "description": "Intelligent LLM gateway.",
    "title": "routeur.ai API",
    "version": "1"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/api-keys": {
      "get": {
        "description": "List the API keys available to the authenticated organisation.",
        "operationId": "listApiKeys",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"data\": [\n    {\n      \"id\":           \"key_01J...\",\n      \"name\":         \"Production\",\n      \"prefix\":       \"rtr_live_qF8…\",\n      \"created_at\":   \"2026-04-12T09:11:30Z\",\n      \"last_used_at\": \"2026-05-29T10:55:00Z\"\n    }\n  ]\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "List API keys",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/api-keys \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\"https://api.routeur.ai/v1/api-keys\", {\n  headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` }\n});\nconst { data } = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.get(\n    \"https://api.routeur.ai/v1/api-keys\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\nkeys = r.json()[\"data\"]\n"
          }
        ],
        "x-stability": "Preview"
      },
      "post": {
        "description": "Create a new API key for authenticating requests to routeur.ai.",
        "operationId": "createApiKey",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "name": {
                    "description": "Human label that appears in the dashboard and trace records, e.g. `Production`.",
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\":         \"key_01J...\",\n  \"name\":       \"Production\",\n  \"prefix\":     \"rtr_live_qF8…\",\n  \"key\":        \"rtr_live_qF8…W2k\",\n  \"created_at\": \"2026-05-29T11:05:00Z\"\n}\n",
                "x-label": "Response"
              }
            },
            "description": "Created"
          }
        },
        "summary": "Create an API key",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl -X POST https://api.routeur.ai/v1/api-keys \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"name\": \"Production\" }'\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\"https://api.routeur.ai/v1/api-keys\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROUTEUR_KEY}`,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({ name: \"Production\" })\n});\nconst created = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.post(\n    \"https://api.routeur.ai/v1/api-keys\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n    json={\"name\": \"Production\"},\n)\ncreated = r.json()\n"
          }
        ],
        "x-stability": "Preview"
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "description": "Revoke an API key so it can no longer be used for authentication.",
        "operationId": "revokeApiKey",
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "summary": "Revoke an API key",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl -X DELETE https://api.routeur.ai/v1/api-keys/key_01J... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "await fetch(`https://api.routeur.ai/v1/api-keys/${id}`, {\n  method: \"DELETE\",\n  headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` }\n});\n"
          },
          {
            "lang": "python",
            "source": "requests.delete(\n    f\"https://api.routeur.ai/v1/api-keys/{key_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\n"
          }
        ],
        "x-stability": "Preview"
      },
      "parameters": [
        {
          "description": "API key id (the `id` field, not the prefix or the secret itself).",
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ]
    },
    "/v1/chat/completions": {
      "post": {
        "description": "Submit an OpenAI-compatible chat completion request through routeur.ai routing.",
        "operationId": "createChatCompletion",
        "parameters": [
          {
            "description": "Append a `routeur` metadata block to the response.",
            "in": "header",
            "name": "Routeur-Trace",
            "required": false,
            "schema": {
              "x-type": "true | false"
            }
          },
          {
            "description": "Return the route resolution without calling the upstream provider.",
            "in": "header",
            "name": "Routeur-Dry-Run",
            "required": false,
            "schema": {
              "x-type": "true | false"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "messages": {
                    "description": "Conversation history. Each item has a `role` and `content`.",
                    "items": {
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "model": {
                    "description": "The model to use. Pass `auto` (or any other alias defined in\nyour routing rules) to let routeur.ai pick the upstream model.\nPass an explicit upstream model id (e.g. `gpt-4o-mini`,\n`claude-3-5-sonnet`) to bypass routing and send the request\ndirectly to that model.\n",
                    "type": "string"
                  },
                  "stream": {
                    "default": false,
                    "description": "When true, the response is streamed as server-sent events (`text/event-stream`): a sequence of `chat.completion.chunk` objects terminated by `data: [DONE]`. For organizations with output-moderation rules the stream is delivered only after moderation completes (see the Streaming section of the guide).\n",
                    "type": "boolean"
                  },
                  "temperature": {
                    "default": 1,
                    "description": "Sampling temperature passed through to the upstream provider.",
                    "type": "number"
                  }
                },
                "required": [
                  "model",
                  "messages"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\": \"chatcmpl_01J...\",\n  \"object\": \"chat.completion\",\n  \"model\": \"gpt-4o-mini\",\n  \"choices\": [{\n    \"index\": 0,\n    \"message\": {\n      \"role\": \"assistant\",\n      \"content\": \"Hello there!\"\n    },\n    \"finish_reason\": \"stop\"\n  }],\n  \"routeur\": {\n    \"provider\": \"openai\",\n    \"model\": \"gpt-4o-mini\",\n    \"route_reason\": \"default\",\n    \"redactions\": 1\n  }\n}\n",
                "x-label": "Response"
              },
              "text/event-stream": {
                "example": "data: {\"id\":\"chatcmpl_01J...\",\"object\":\"chat.completion.chunk\",\"model\":\"gpt-4o-mini\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\"}}]}\n\ndata: {\"object\":\"chat.completion.chunk\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"}}]}\n\ndata: {\"object\":\"chat.completion.chunk\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":9,\"completion_tokens\":2,\"total_tokens\":11}}\n\ndata: [DONE]\n",
                "x-label": "Streamed response (stream=true)"
              }
            },
            "description": "OK. A single chat completion object when `stream` is false, or an SSE `text/event-stream` of `chat.completion.chunk` objects when `stream` is true.\n"
          }
        },
        "summary": "Create a chat completion",
        "tags": [
          "chat-completions"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/chat/completions \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"auto\",\n    \"messages\": [\n      {\"role\": \"user\", \"content\": \"Hello\"}\n    ]\n  }'\n"
          },
          {
            "lang": "node",
            "source": "import OpenAI from \"openai\";\n\nconst client = new OpenAI({\n  apiKey: process.env.ROUTEUR_KEY,\n  baseURL: \"https://api.routeur.ai/v1\"\n});\n\nconst r = await client.chat.completions.create({\n  model: \"auto\",\n  messages: [{ role: \"user\", content: \"Hello\" }]\n});\n"
          },
          {
            "lang": "python",
            "source": "from openai import OpenAI\n\nclient = OpenAI(\n    api_key=os.environ[\"ROUTEUR_KEY\"],\n    base_url=\"https://api.routeur.ai/v1\",\n)\n\nr = client.chat.completions.create(\n    model=\"auto\",\n    messages=[{\"role\": \"user\", \"content\": \"Hello\"}],\n)\n"
          }
        ],
        "x-stability": "Stable"
      }
    },
    "/v1/models": {
      "get": {
        "description": "List the upstream models currently available through routeur.ai.",
        "operationId": "listModels",
        "parameters": [
          {
            "description": "Restrict the result to one provider, e.g. `openai`.",
            "in": "query",
            "name": "provider",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Restrict to models whose provider credentials are currently mounted.",
            "in": "query",
            "name": "configured",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"data\": [\n    {\n      \"id\":       \"gpt-4o-mini\",\n      \"provider\": \"openai\",\n      \"context_window\": 128000,\n      \"configured\": true\n    },\n    {\n      \"id\":       \"gemini-1.5-pro-latest\",\n      \"provider\": \"gemini\",\n      \"context_window\": 2000000,\n      \"configured\": true\n    }\n  ]\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "List models",
        "tags": [
          "models"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/models \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\"https://api.routeur.ai/v1/models\", {\n  headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` }\n});\nconst { data } = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.get(\n    \"https://api.routeur.ai/v1/models\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\nmodels = r.json()[\"data\"]\n"
          }
        ],
        "x-stability": "Stable"
      }
    },
    "/v1/models/{id}": {
      "get": {
        "description": "Retrieve metadata for a single model by its identifier.",
        "operationId": "retrieveModel",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\":             \"gpt-4o-mini\",\n  \"provider\":       \"openai\",\n  \"context_window\": 128000,\n  \"pricing\": { \"prompt\": 0.15, \"completion\": 0.60 },\n  \"configured\":     true\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "Retrieve a model",
        "tags": [
          "models"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/models/gpt-4o-mini \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\n  `https://api.routeur.ai/v1/models/${id}`,\n  { headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` } }\n);\nconst model = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.get(\n    f\"https://api.routeur.ai/v1/models/{model_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\nmodel = r.json()\n"
          }
        ],
        "x-stability": "Stable"
      },
      "parameters": [
        {
          "description": "Model id, e.g. `gpt-4o-mini`. Aliases (`auto`) resolve to their underlying model.",
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ]
    },
    "/v1/routes": {
      "get": {
        "description": "List the routing rules configured for the authenticated organisation.",
        "operationId": "listRoutes",
        "parameters": [
          {
            "description": "Restrict the result to only enabled (or only disabled) rules.",
            "in": "query",
            "name": "enabled",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Maximum number of rules to return.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"data\": [\n    {\n      \"id\":       \"route_01J...\",\n      \"name\":     \"premium_demo\",\n      \"priority\": 100,\n      \"enabled\":  true,\n      \"action_kind\": \"pin\",\n      \"match\":  { \"requested_model\": \"demo-premium\" },\n      \"action\": { \"provider\": \"openai\", \"model\": \"gpt-4o\" }\n    }\n  ],\n  \"has_more\": false\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "List routes",
        "tags": [
          "routes"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/routes \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\"https://api.routeur.ai/v1/routes\", {\n  headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` }\n});\nconst { data } = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "import os, requests\n\nr = requests.get(\n    \"https://api.routeur.ai/v1/routes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\ndata = r.json()[\"data\"]\n"
          }
        ],
        "x-stability": "Preview"
      },
      "post": {
        "description": "Create a new routing rule for model selection and request handling.",
        "operationId": "createRoute",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "action": {
                    "description": "For `pin`, supply `provider` and `model`.",
                    "type": "object"
                  },
                  "action_kind": {
                    "description": "Resolution strategy.",
                    "x-type": "pin | auto"
                  },
                  "enabled": {
                    "default": true,
                    "description": "Create disabled if you want to stage a rule without it taking effect.",
                    "type": "boolean"
                  },
                  "match": {
                    "description": "Match condition. Currently supports `requested_model`.",
                    "type": "object"
                  },
                  "name": {
                    "description": "Unique within the organisation. Surfaced in trace metadata.",
                    "type": "string"
                  },
                  "priority": {
                    "default": 0,
                    "description": "Higher numbers evaluate first.",
                    "type": "integer"
                  }
                },
                "required": [
                  "name",
                  "action_kind",
                  "match",
                  "action"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\":          \"route_01J...\",\n  \"name\":        \"premium_demo\",\n  \"priority\":    100,\n  \"enabled\":     true,\n  \"action_kind\": \"pin\",\n  \"match\":  { \"requested_model\": \"demo-premium\" },\n  \"action\": { \"provider\": \"openai\", \"model\": \"gpt-4o\" },\n  \"created_at\": \"2026-05-29T10:00:00Z\"\n}\n",
                "x-label": "Response"
              }
            },
            "description": "Created"
          }
        },
        "summary": "Create a route",
        "tags": [
          "routes"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/routes \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"premium_demo\",\n    \"priority\": 100,\n    \"action_kind\": \"pin\",\n    \"match\":  { \"requested_model\": \"demo-premium\" },\n    \"action\": { \"provider\": \"openai\", \"model\": \"gpt-4o\" }\n  }'\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\"https://api.routeur.ai/v1/routes\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROUTEUR_KEY}`,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({\n    name: \"premium_demo\",\n    priority: 100,\n    action_kind: \"pin\",\n    match:  { requested_model: \"demo-premium\" },\n    action: { provider: \"openai\", model: \"gpt-4o\" }\n  })\n});\n"
          },
          {
            "lang": "python",
            "source": "r = requests.post(\n    \"https://api.routeur.ai/v1/routes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n    json={\n        \"name\": \"premium_demo\",\n        \"priority\": 100,\n        \"action_kind\": \"pin\",\n        \"match\":  {\"requested_model\": \"demo-premium\"},\n        \"action\": {\"provider\": \"openai\", \"model\": \"gpt-4o\"},\n    },\n)\n"
          }
        ],
        "x-stability": "Preview"
      }
    },
    "/v1/routes/{id}": {
      "delete": {
        "description": "Delete a routing rule by its identifier.",
        "operationId": "deleteRoute",
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "summary": "Delete a route",
        "tags": [
          "routes"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl -X DELETE https://api.routeur.ai/v1/routes/route_01J... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "await fetch(`https://api.routeur.ai/v1/routes/${id}`, {\n  method: \"DELETE\",\n  headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` }\n});\n"
          },
          {
            "lang": "python",
            "source": "requests.delete(\n    f\"https://api.routeur.ai/v1/routes/{route_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\n"
          }
        ],
        "x-stability": "Preview"
      },
      "get": {
        "description": "Retrieve a single routing rule by its identifier.",
        "operationId": "retrieveRoute",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\":          \"route_01J...\",\n  \"name\":        \"premium_demo\",\n  \"priority\":    100,\n  \"enabled\":     true,\n  \"action_kind\": \"pin\",\n  \"match\":  { \"requested_model\": \"demo-premium\" },\n  \"action\": { \"provider\": \"openai\", \"model\": \"gpt-4o\" }\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "Retrieve a route",
        "tags": [
          "routes"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/routes/route_01J... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\n  `https://api.routeur.ai/v1/routes/${id}`,\n  { headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` } }\n);\nconst route = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.get(\n    f\"https://api.routeur.ai/v1/routes/{route_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\nroute = r.json()\n"
          }
        ],
        "x-stability": "Preview"
      },
      "parameters": [
        {
          "description": "Route id, e.g. `route_01J...`.",
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "patch": {
        "description": "Update selected fields on an existing routing rule.",
        "operationId": "updateRoute",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\":         \"route_01J...\",\n  \"enabled\":    false,\n  \"updated_at\": \"2026-05-29T11:00:00Z\"\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "Update a route",
        "tags": [
          "routes"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl -X PATCH https://api.routeur.ai/v1/routes/route_01J... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"enabled\": false }'\n"
          },
          {
            "lang": "node",
            "source": "await fetch(`https://api.routeur.ai/v1/routes/${id}`, {\n  method: \"PATCH\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROUTEUR_KEY}`,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({ enabled: false })\n});\n"
          },
          {
            "lang": "python",
            "source": "requests.patch(\n    f\"https://api.routeur.ai/v1/routes/{route_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n    json={\"enabled\": False},\n)\n"
          }
        ],
        "x-stability": "Preview"
      },
      "put": {
        "description": "Replace an existing routing rule with a full new definition.",
        "operationId": "replaceRoute",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"id\":          \"route_01J...\",\n  \"name\":        \"premium_demo\",\n  \"priority\":    200,\n  \"updated_at\":  \"2026-05-29T11:00:00Z\"\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "Replace a route",
        "tags": [
          "routes"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl -X PUT https://api.routeur.ai/v1/routes/route_01J... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"premium_demo\",\n    \"priority\": 200,\n    \"enabled\": true,\n    \"action_kind\": \"pin\",\n    \"match\":  { \"requested_model\": \"demo-premium\" },\n    \"action\": { \"provider\": \"openai\", \"model\": \"gpt-4o\" }\n  }'\n"
          },
          {
            "lang": "node",
            "source": "await fetch(`https://api.routeur.ai/v1/routes/${id}`, {\n  method: \"PUT\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROUTEUR_KEY}`,\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify(fullRoute)\n});\n"
          },
          {
            "lang": "python",
            "source": "requests.put(\n    f\"https://api.routeur.ai/v1/routes/{route_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n    json=full_route,\n)\n"
          }
        ],
        "x-stability": "Preview"
      }
    },
    "/v1/traces": {
      "get": {
        "description": "List recent request traces for the authenticated organisation.",
        "operationId": "listTraces",
        "parameters": [
          {
            "description": "Maximum number of records to return.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "type": "integer"
            }
          },
          {
            "description": "Cursor — `request_id` from the previous page.",
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Restrict to a single HTTP status code, e.g. `200` or `403`.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Restrict to a single upstream provider.",
            "in": "query",
            "name": "provider",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"data\": [\n    {\n      \"request_id\":  \"01K...\",\n      \"provider\":    \"openai\",\n      \"model\":       \"gpt-4o-mini\",\n      \"latency_ms\":  2939,\n      \"status_code\": 200,\n      \"cost_usd\":    0.00000615\n    }\n  ],\n  \"has_more\": true\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "List traces",
        "tags": [
          "traces"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl \"https://api.routeur.ai/v1/traces?limit=20\u0026status=200\" \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\n  \"https://api.routeur.ai/v1/traces?limit=20\",\n  { headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` } }\n);\nconst { data, has_more } = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.get(\n    \"https://api.routeur.ai/v1/traces\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n    params={\"limit\": 20, \"status\": 200},\n)\ntraces = r.json()[\"data\"]\n"
          }
        ],
        "x-stability": "Preview"
      }
    },
    "/v1/traces/{request_id}": {
      "get": {
        "description": "Retrieve the full stored trace record for a single request.",
        "operationId": "retrieveTrace",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": "{\n  \"request_id\":  \"01K...\",\n  \"provider\":    \"openai\",\n  \"model\":       \"gpt-4o-mini\",\n  \"latency_ms\":  2939,\n  \"status_code\": 200,\n  \"cost_usd\":    0.00000615,\n  \"redactions\":  1,\n  \"payload_url\": \"https://payloads.routeur.ai/...?sig=...\"\n}\n",
                "x-label": "Response"
              }
            },
            "description": "OK"
          }
        },
        "summary": "Retrieve a trace",
        "tags": [
          "traces"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl https://api.routeur.ai/v1/traces/01K... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\n  `https://api.routeur.ai/v1/traces/${requestId}`,\n  { headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` } }\n);\nconst trace = await res.json();\n"
          },
          {
            "lang": "python",
            "source": "r = requests.get(\n    f\"https://api.routeur.ai/v1/traces/{request_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\ntrace = r.json()\n"
          }
        ],
        "x-stability": "Preview"
      },
      "head": {
        "description": "Inspect high-level trace metadata through response headers only.",
        "operationId": "inspectTrace",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Routeur-Trace-Payload": {
                "description": "Signed URL for the payload archive if one exists. Absent when payload storage is disabled.",
                "schema": {
                  "x-type": "url"
                }
              },
              "X-Routeur-Trace-Provider": {
                "description": "Final upstream provider used.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Routeur-Trace-Status": {
                "description": "Caller-visible HTTP status the original request received.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "x-body": "X-Routeur-Trace-Status:   200\nX-Routeur-Trace-Provider: openai\nX-Routeur-Trace-Payload:  https://payloads.routeur.ai/...?sig=...\n",
            "x-content-type": "no body",
            "x-label": "Response headers",
            "x-lang": "text"
          }
        },
        "summary": "Inspect a trace",
        "tags": [
          "traces"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "source": "curl -I https://api.routeur.ai/v1/traces/01K... \\\n  -H \"Authorization: Bearer $ROUTEUR_KEY\"\n"
          },
          {
            "lang": "node",
            "source": "const res = await fetch(\n  `https://api.routeur.ai/v1/traces/${requestId}`,\n  { method: \"HEAD\", headers: { Authorization: `Bearer ${process.env.ROUTEUR_KEY}` } }\n);\nconst payloadUrl = res.headers.get(\"X-Routeur-Trace-Payload\");\n"
          },
          {
            "lang": "python",
            "source": "r = requests.head(\n    f\"https://api.routeur.ai/v1/traces/{request_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROUTEUR_KEY']}\"},\n)\npayload_url = r.headers.get(\"X-Routeur-Trace-Payload\")\n"
          }
        ],
        "x-stability": "Preview"
      },
      "parameters": [
        {
          "description": "Trace request id, e.g. `01K...`. Returned from the `routeur` block of any chat response.",
          "in": "path",
          "name": "request_id",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ]
    }
  },
  "security": [
    {
      "bearer_auth": []
    }
  ],
  "servers": [
    {
      "description": "Production",
      "url": "https://api.routeur.ai"
    }
  ],
  "tags": [
    {
      "description": "OpenAI-compatible chat completion requests routed through routeur.ai.",
      "name": "chat-completions"
    },
    {
      "description": "Routing rule management for model resolution and traffic shaping.",
      "name": "routes"
    },
    {
      "description": "Available upstream model inventory and metadata.",
      "name": "models"
    },
    {
      "description": "Request trace records and trace inspection endpoints.",
      "name": "traces"
    },
    {
      "description": "API key lifecycle operations for authenticating to routeur.ai.",
      "name": "api-keys"
    }
  ]
}