{
  "openapi": "3.1.0",
  "info": {
    "title": "Frontier API",
    "version": "1",
    "description": "Frontier exposes a small OpenAI-style Chat Completions interface with buffered JSON and SSE streaming responses, plus read-only model and account-usage discovery. It is not the full OpenAI API. Create and manage API keys at https://openfrontier.dev/account.",
    "termsOfService": "https://renvoi.co/legal/terms"
  },
  "externalDocs": {
    "description": "Frontier developer docs",
    "url": "https://openfrontier.dev/docs"
  },
  "servers": [
    {
      "url": "https://openfrontier.dev",
      "description": "Production"
    }
  ],
  "paths": {
    "/v1/models": {
      "get": {
        "operationId": "listModels",
        "summary": "List the current Frontier model aliases",
        "security": [],
        "responses": {
          "200": {
            "description": "Current model aliases",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "frontier-auto",
                      "object": "model",
                      "owned_by": "frontier"
                    },
                    {
                      "id": "frontier-heavy",
                      "object": "model",
                      "owned_by": "frontier"
                    },
                    {
                      "id": "frontier-fast",
                      "object": "model",
                      "owned_by": "frontier"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/usage": {
      "get": {
        "operationId": "getAccountUsage",
        "summary": "Get the current account usage and refill state",
        "description": "Authenticates the bearer API key and derives the account owner from that validated credential. The request accepts no body or query parameters. A valid key without an active allowance returns an inactive snapshot with HTTP 200.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sanitized usage for the account that owns the bearer API key",
            "headers": {
              "Cache-Control": {
                "description": "Usage responses are never cacheable.",
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountUsageSnapshot"
                },
                "example": {
                  "status": "active",
                  "plan": {
                    "key": "build",
                    "displayName": "Build"
                  },
                  "inference": {
                    "capacityPercent": 100,
                    "remainingPercent": 50,
                    "refillPercentPerMinute": 0.00992063492063492,
                    "fullInMs": 302400000
                  },
                  "requests": {
                    "capacity": 500,
                    "available": 250,
                    "refillIntervalMs": 60000,
                    "nextRefillInMs": 30000,
                    "fullInMs": 15000000
                  },
                  "models": [
                    "frontier-auto",
                    "frontier-heavy",
                    "frontier-fast"
                  ],
                  "computedAt": 1800000000000,
                  "accountUrl": "https://openfrontier.dev/account"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "401": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "415": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "502": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "503": {
            "$ref": "#/components/responses/ErrorResponse"
          }
        }
      }
    },
    "/v1/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "summary": "Create one buffered or streaming chat completion",
        "description": "Use `frontier-auto` for local automatic routing, `frontier-fast` for Fast or `frontier-heavy` for Heavy. These public aliases stay stable when the underlying lineup changes. Auto starts ordinary work on Fast and uses Heavy for clearly complex or constrained work without making an extra model call. Merely advertising an optional tool catalog does not force Heavy. Standard OpenAI text and `image_url` content parts are supported on Auto and Heavy; Auto routes image input to Heavy. The routing response headers identify the selected alias, policy and reason. Set `stream` to `true` for SSE or omit it for a buffered JSON response. `n` must be omitted or set to `1`. If both output-token fields are supplied, their values must match.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              },
              "example": {
                "model": "frontier-auto",
                "messages": [
                  {
                    "role": "user",
                    "content": "Translate this into French: Frontier is connected."
                  }
                ],
                "max_tokens": 64
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion",
            "headers": {
              "X-Frontier-Requested-Model": {
                "description": "The public alias sent by the client.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Frontier-Selected-Model": {
                "description": "The concrete Frontier alias authorized and metered for this request.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "frontier-fast",
                    "frontier-heavy"
                  ]
                }
              },
              "X-Frontier-Routing-Policy": {
                "description": "The policy identifier used to select the model.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Frontier-Routing-Reason": {
                "description": "A prompt-free reason code for the decision.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "OpenAI-compatible SSE chunks ending with `data: [DONE]`. A post-start gateway failure is emitted as an SSE error object and closes without a clean terminator."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "401": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "403": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "409": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "413": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "429": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "500": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "502": {
            "$ref": "#/components/responses/ErrorResponse"
          },
          "503": {
            "$ref": "#/components/responses/ErrorResponse"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Frontier API key from the authenticated account page"
      }
    },
    "responses": {
      "ErrorResponse": {
        "description": "The request could not be completed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Model": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "owned_by"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "frontier-auto",
              "frontier-heavy",
              "frontier-fast"
            ]
          },
          "object": {
            "type": "string",
            "const": "model"
          },
          "owned_by": {
            "type": "string",
            "const": "frontier"
          }
        }
      },
      "ModelList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "data"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Model"
            }
          }
        }
      },
      "InferenceUsage": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "capacityPercent",
          "remainingPercent",
          "refillPercentPerMinute",
          "fullInMs"
        ],
        "properties": {
          "capacityPercent": {
            "type": "number",
            "const": 100
          },
          "remainingPercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "refillPercentPerMinute": {
            "type": "number",
            "minimum": 0
          },
          "fullInMs": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "RequestAvailability": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "capacity",
          "available",
          "refillIntervalMs",
          "nextRefillInMs",
          "fullInMs"
        ],
        "properties": {
          "capacity": {
            "type": "integer",
            "minimum": 1
          },
          "available": {
            "type": "integer",
            "minimum": 0,
            "description": "Always less than or equal to capacity."
          },
          "refillIntervalMs": {
            "type": "number",
            "minimum": 0
          },
          "nextRefillInMs": {
            "type": "integer",
            "minimum": 0
          },
          "fullInMs": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "ActiveAccountUsageSnapshot": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "plan",
          "inference",
          "requests",
          "models",
          "computedAt",
          "accountUrl"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "active"
          },
          "plan": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "key",
              "displayName"
            ],
            "properties": {
              "key": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,63}$"
              },
              "displayName": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              }
            }
          },
          "inference": {
            "$ref": "#/components/schemas/InferenceUsage"
          },
          "requests": {
            "$ref": "#/components/schemas/RequestAvailability"
          },
          "models": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "frontier-auto",
                "frontier-heavy",
                "frontier-fast"
              ]
            }
          },
          "computedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix time in milliseconds used to compute this snapshot."
          },
          "accountUrl": {
            "type": "string",
            "const": "https://openfrontier.dev/account"
          }
        }
      },
      "InactiveAccountUsageSnapshot": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "plan",
          "inference",
          "requests",
          "models",
          "computedAt",
          "accountUrl"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "inactive"
          },
          "plan": {
            "type": "null"
          },
          "inference": {
            "type": "null"
          },
          "requests": {
            "type": "null"
          },
          "models": {
            "type": "array",
            "maxItems": 0
          },
          "computedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix time in milliseconds used to compute this snapshot."
          },
          "accountUrl": {
            "type": "string",
            "const": "https://openfrontier.dev/account"
          }
        }
      },
      "AccountUsageSnapshot": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/ActiveAccountUsageSnapshot"
          },
          {
            "$ref": "#/components/schemas/InactiveAccountUsageSnapshot"
          }
        ]
      },
      "ChatMessage": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "role"
        ],
        "properties": {
          "role": {
            "type": "string"
          },
          "content": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/TextContentPart"
                    },
                    {
                      "$ref": "#/components/schemas/ImageUrlContentPart"
                    },
                    {
                      "type": "object",
                      "additionalProperties": true
                    }
                  ]
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TextContentPart": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "type",
          "text"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "text"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "ImageUrlContentPart": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "type",
          "image_url"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "image_url"
          },
          "image_url": {
            "type": "object",
            "additionalProperties": true,
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "HTTPS URL or data URL accepted by the configured Heavy model."
              },
              "detail": {
                "type": "string"
              }
            }
          }
        }
      },
      "ChatCompletionRequest": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "model",
          "messages"
        ],
        "properties": {
          "model": {
            "type": "string",
            "enum": [
              "frontier-auto",
              "frontier-fast",
              "frontier-heavy"
            ]
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            }
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "Set true for a text/event-stream response; false or omitted returns buffered JSON."
          },
          "n": {
            "type": "integer",
            "const": 1,
            "default": 1
          },
          "max_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000000,
            "default": 4096
          },
          "max_completion_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000000
          }
        }
      },
      "ChatCompletionResponse": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "choices",
          "usage"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "created": {
            "type": "integer"
          },
          "model": {
            "type": "string"
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "index": {
                  "type": "integer"
                },
                "message": {
                  "$ref": "#/components/schemas/ChatMessage"
                },
                "finish_reason": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          }
        }
      },
      "Usage": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "prompt_tokens",
          "completion_tokens"
        ],
        "properties": {
          "prompt_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "completion_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "total_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "prompt_tokens_details": {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "cached_tokens": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
