{
 "openapi": "3.1.0",
 "info": {
  "title": "Candor API",
  "version": "1.0.0",
  "description": "OpenAI-compatible chat completions for uncensored models. Getting started: sign in at https://candorai.dev (New accounts get $0.47 of free credit to try the API, once per person.); then subscribe at https://candorai.dev/?panel=account (Monthly $19.99/month, includes 8,500 credits ($20.00 of API usage); Plus $99/month, includes 42,500 credits ($100.00 of API usage)); optional top-ups ($9.99 for 4,250 credits ($10.00 of API usage), subscribers only); create a key under Account > API keys. 1 USD = 425 app credits. A 402 insufficient_quota response explains how to add credits. Prices per 1M tokens are listed in GET /v1/models."
 },
 "servers": [
  {
   "url": "https://candorai.dev/v1"
  }
 ],
 "security": [
  {
   "bearer": []
  }
 ],
 "components": {
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer",
    "description": "API key starting with sk-unc-"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "message",
       "type"
      ],
      "properties": {
       "message": {
        "type": "string"
       },
       "type": {
        "type": "string"
       },
       "param": {
        "type": [
         "string",
         "null"
        ]
       },
       "code": {
        "type": [
         "string",
         "null"
        ]
       }
      }
     }
    }
   },
   "Message": {
    "type": "object",
    "required": [
     "role"
    ],
    "properties": {
     "role": {
      "type": "string",
      "enum": [
       "system",
       "developer",
       "user",
       "assistant",
       "tool"
      ]
     },
     "content": {
      "oneOf": [
       {
        "type": "string"
       },
       {
        "type": "array",
        "items": {
         "type": "object"
        }
       },
       {
        "type": "null"
       }
      ]
     },
     "name": {
      "type": "string"
     },
     "tool_calls": {
      "type": "array",
      "items": {
       "type": "object"
      }
     },
     "tool_call_id": {
      "type": "string"
     }
    }
   },
   "Usage": {
    "type": "object",
    "properties": {
     "prompt_tokens": {
      "type": "integer"
     },
     "completion_tokens": {
      "type": "integer"
     },
     "total_tokens": {
      "type": "integer"
     },
     "prompt_tokens_details": {
      "type": "object",
      "properties": {
       "cached_tokens": {
        "type": "integer"
       }
      }
     },
     "completion_tokens_details": {
      "type": "object",
      "properties": {
       "reasoning_tokens": {
        "type": "integer"
       }
      }
     },
     "cost_usd": {
      "type": "number",
      "description": "What this request was charged, in USD."
     },
     "web_search_cost_usd": {
      "type": "number",
      "description": "The part of cost_usd that paid for the web search, when one ran."
     }
    }
   },
   "Character": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "object": {
      "const": "character"
     },
     "owned_by": {
      "type": "string",
      "enum": [
       "candor",
       "you"
      ]
     },
     "name": {
      "type": "string"
     },
     "age": {
      "type": "integer"
     },
     "category": {
      "type": "string",
      "enum": [
       "girlfriends",
       "boyfriends",
       "roleplay",
       "games",
       "advisors"
      ]
     },
     "format": {
      "type": "string",
      "enum": [
       "text",
       "story"
      ]
     },
     "tagline": {
      "type": "string"
     },
     "tags": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "greeting": {
      "type": "string"
     },
     "opener": {
      "type": "string"
     },
     "image_url": {
      "type": "string"
     },
     "avatar_url": {
      "type": "string"
     },
     "added": {
      "type": "string"
     },
     "prompt_tokens_estimate": {
      "type": "integer"
     }
    }
   },
   "ChatCompletionRequest": {
    "type": "object",
    "required": [
     "model",
     "messages"
    ],
    "properties": {
     "model": {
      "type": "string",
      "enum": [
       "candor-fast",
       "candor-classic",
       "candor-smart"
      ]
     },
     "messages": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Message"
      }
     },
     "stream": {
      "type": "boolean"
     },
     "stream_options": {
      "type": "object",
      "properties": {
       "include_usage": {
        "type": "boolean"
       }
      }
     },
     "max_tokens": {
      "type": "integer"
     },
     "max_completion_tokens": {
      "type": "integer"
     },
     "temperature": {
      "type": "number",
      "minimum": 0,
      "maximum": 2
     },
     "top_p": {
      "type": "number"
     },
     "frequency_penalty": {
      "type": "number"
     },
     "presence_penalty": {
      "type": "number"
     },
     "stop": {
      "oneOf": [
       {
        "type": "string"
       },
       {
        "type": "array",
        "items": {
         "type": "string"
        },
        "maxItems": 4
       }
      ]
     },
     "seed": {
      "type": "integer"
     },
     "tools": {
      "type": "array",
      "items": {
       "type": "object"
      }
     },
     "tool_choice": {
      "oneOf": [
       {
        "type": "string"
       },
       {
        "type": "object"
       }
      ]
     },
     "parallel_tool_calls": {
      "type": "boolean"
     },
     "response_format": {
      "type": "object"
     },
     "reasoning_effort": {
      "type": "string",
      "enum": [
       "none",
       "low",
       "medium",
       "high",
       "max"
      ]
     },
     "character": {
      "type": "string",
      "description": "Id of a character from GET /characters: the model answers as that character."
     },
     "web_search": {
      "description": "Search the web first and give the model the results: true, or the words to search.",
      "oneOf": [
       {
        "type": "boolean"
       },
       {
        "type": "object",
        "properties": {
         "query": {
          "type": "string",
          "minLength": 2,
          "maxLength": 300
         }
        }
       }
      ]
     }
    }
   },
   "ChatCompletion": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "object": {
      "const": "chat.completion"
     },
     "created": {
      "type": "integer"
     },
     "model": {
      "type": "string"
     },
     "choices": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "index": {
         "type": "integer"
        },
        "message": {
         "type": "object"
        },
        "finish_reason": {
         "type": [
          "string",
          "null"
         ]
        }
       }
      }
     },
     "usage": {
      "$ref": "#/components/schemas/Usage"
     },
     "web_search": {
      "type": "object",
      "description": "Present when the request asked for a web search: what was searched and the results the model was given.",
      "properties": {
       "id": {
        "type": "string"
       },
       "query": {
        "type": "string"
       },
       "results": {
        "type": "array",
        "items": {
         "type": "object",
         "properties": {
          "title": {
           "type": "string"
          },
          "url": {
           "type": "string"
          },
          "snippet": {
           "type": "string"
          }
         }
        }
       },
       "cost_usd": {
        "type": "number"
       }
      }
     }
    }
   },
   "Model": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "object": {
      "const": "model"
     },
     "owned_by": {
      "type": "string"
     },
     "context_length": {
      "type": "integer"
     },
     "max_output_tokens": {
      "type": "integer"
     },
     "capabilities": {
      "type": "object"
     },
     "pricing": {
      "type": "object",
      "properties": {
       "currency": {
        "type": "string"
       },
       "input_per_million": {
        "type": "number"
       },
       "cached_input_per_million": {
        "type": "number"
       },
       "output_per_million": {
        "type": "number"
       }
      }
     }
    }
   }
  }
 },
 "paths": {
  "/chat/completions": {
   "post": {
    "operationId": "createChatCompletion",
    "summary": "Create a chat completion",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ChatCompletionRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Completion (JSON), or text/event-stream of chat.completion.chunk when stream=true",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ChatCompletion"
        }
       },
       "text/event-stream": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "description": "Invalid request",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Missing, invalid, revoked or expired API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "Not enough credits, the request could cost more than the balance, or the key reached its spending limit: the message says what to do",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Unknown model, id or endpoint",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "413": {
      "description": "Request body over 5 MB",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "The model returned an incomplete response; what was written is charged at an estimate",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Model backend unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "The model took too long to answer",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/models": {
   "get": {
    "operationId": "listModels",
    "summary": "List models and prices",
    "security": [],
    "responses": {
     "200": {
      "description": "Models",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "object": {
           "const": "list"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Model"
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/models/{id}": {
   "get": {
    "operationId": "getModel",
    "summary": "Get one model",
    "security": [],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "candor-fast",
        "candor-classic",
        "candor-smart"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Model",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Model"
        }
       }
      }
     },
     "404": {
      "description": "Invalid request",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/balance": {
   "get": {
    "operationId": "getBalance",
    "summary": "Prepaid balance",
    "responses": {
     "200": {
      "description": "Balance",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "object": {
           "const": "balance"
          },
          "currency": {
           "type": "string"
          },
          "available_usd": {
           "type": "number"
          },
          "reserved_usd": {
           "type": "number"
          },
          "available_credits": {
           "type": "number"
          },
          "minimum_request_usd": {
           "type": "number"
          },
          "can_request": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing, invalid, revoked or expired API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/usage/summary": {
   "get": {
    "operationId": "usageSummary",
    "summary": "What was spent by day, by model and by key",
    "parameters": [
     {
      "name": "days",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 90,
       "default": 30
      }
     },
     {
      "name": "key_id",
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Totals over the last days (UTC)",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "object": {
           "const": "usage.summary"
          },
          "days": {
           "type": "integer"
          },
          "from": {
           "type": "string"
          },
          "to": {
           "type": "string"
          },
          "totals": {
           "type": "object"
          },
          "by_day": {
           "type": "array",
           "items": {
            "type": "object"
           }
          },
          "by_model": {
           "type": "array",
           "items": {
            "type": "object"
           }
          },
          "by_key": {
           "type": "array",
           "items": {
            "type": "object"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing, invalid, revoked or expired API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/usage": {
   "get": {
    "operationId": "listUsage",
    "summary": "Per-request usage and cost",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 100
      }
     },
     {
      "name": "before",
      "in": "query",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "key_id",
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Usage records",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "Missing, invalid, revoked or expired API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/web/search": {
   "post": {
    "operationId": "searchWeb",
    "summary": "Search the web",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "query"
        ],
        "properties": {
         "query": {
          "type": "string",
          "minLength": 2,
          "maxLength": 300
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results (empty when nothing was found)",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "id": {
           "type": "string"
          },
          "object": {
           "const": "web_search"
          },
          "created": {
           "type": "integer"
          },
          "query": {
           "type": "string"
          },
          "results": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "title": {
              "type": "string"
             },
             "url": {
              "type": "string"
             },
             "snippet": {
              "type": "string"
             }
            }
           }
          },
          "usage": {
           "type": "object",
           "properties": {
            "cost_usd": {
             "type": "number"
            },
            "credits": {
             "type": "number"
            }
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "Invalid request",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Missing, invalid, revoked or expired API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "Not enough credits, the request could cost more than the balance, or the key reached its spending limit: the message says what to do",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Unknown model, id or endpoint",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "413": {
      "description": "Request body over 5 MB",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "The search could not run; nothing was charged",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Model backend unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "The model took too long to answer",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/characters": {
   "get": {
    "operationId": "listCharacters",
    "summary": "List the characters that can be played",
    "parameters": [
     {
      "name": "category",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "format",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "text",
        "story"
       ]
      }
     },
     {
      "name": "search",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "owner",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "candor",
        "you"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Characters",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "object": {
           "const": "list"
          },
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Character"
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing, invalid, revoked or expired API key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/characters/{id}": {
   "get": {
    "operationId": "getCharacter",
    "summary": "Get one character",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Character",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Character"
        }
       }
      }
     },
     "404": {
      "description": "Invalid request",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 }
}