{"openapi":"3.1.0","info":{"title":"Morsmorii API","version":"2026-10-01","description":"OpenAI-совместимый API (chat/completions, responses, embeddings, images) и Anthropic-совместимый Messages API (/v1/messages) к моделям Morsmorii. Расход считается в рублях (с копейками) и виден в /billing и в GET /v1/usage. Ключи создаются в https://app.morsmorii.ru/developers; ключ можно ограничить списком моделей и месячным бюджетом.","contact":{"url":"https://morsmorii.ru","email":"support@morsmorii.ru"}},"servers":[{"url":"https://api.morsmorii.ru"}],"security":[{"bearer":[]}],"tags":[{"name":"OpenAI-compatible","description":"Те же пути и тела, что у OpenAI: подходит любому клиенту с настраиваемым base URL."},{"name":"Anthropic-compatible","description":"Messages API для Claude Code и SDK Anthropic: ANTHROPIC_BASE_URL=https://api.morsmorii.ru"},{"name":"Account","description":"Расход по ключам и сотрудникам компании."}],"paths":{"/v1/models":{"get":{"tags":["OpenAI-compatible"],"summary":"Список моделей, доступных ключу","description":"Модели каталога без картиночных и устаревших, плюс агенты владельца ключа как agent:Имя. Ключ с ограничением по моделям видит только разрешённые.","responses":{"200":{"description":"Список","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelList"},"example":{"object":"list","data":[{"id":"gpt-6-luna","object":"model","created":0,"owned_by":"openai"}]}}}},"401":{"description":"Нет ключа или ключ недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.morsmorii.ru/v1/models\" \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\""},{"lang":"Python","label":"Python","source":"from openai import OpenAI\nimport os\n\nclient = OpenAI(base_url=\"https://api.morsmorii.ru/v1\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nfor m in client.models.list():\n    print(m.id)\nprint(client.models.retrieve(\"gpt-6-luna\"))"},{"lang":"JavaScript","label":"Node.js","source":"import OpenAI from \"openai\";\n\nconst client = new OpenAI({ baseURL: \"https://api.morsmorii.ru/v1\", apiKey: process.env.MORSMORII_API_KEY });\nfor await (const m of client.models.list()) console.log(m.id);\nconsole.log(await client.models.retrieve(\"gpt-6-luna\"));"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\treq, _ := http.NewRequest(\"GET\", \"https://api.morsmorii.ru/v1/models\", nil)\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/models/{id}":{"get":{"tags":["OpenAI-compatible"],"summary":"Одна модель (models.retrieve)","description":"Модель, доступная ключу на его тарифе; иначе 404 model_not_found.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","examples":["gpt-6-luna"]}}],"responses":{"200":{"description":"Модель","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Model"},"example":{"id":"gpt-6-luna","object":"model","created":0,"owned_by":"openai"}}}},"401":{"description":"Нет ключа или ключ недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Модели нет или она недоступна ключу (model_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/messages/count_tokens":{"post":{"tags":["Anthropic-compatible"],"summary":"Подсчёт входных токенов (Anthropic)","description":"Тело — как у /v1/messages без max_tokens (model, messages, system, tools, tool_choice, thinking). Считает провайдер модели. Бесплатно: квоту и баланс не тратит, в /v1/usage не попадает. agent:Имя — с инструкциями агента, без фрагментов базы знаний.","security":[{"anthropicKey":[]},{"bearer":[]}],"parameters":[{"name":"anthropic-version","in":"header","required":false,"schema":{"type":"string","example":"2023-06-01"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","description":"Один из claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-4-5 или agent:Имя"},"messages":{"type":"array","items":{"type":"object"}},"system":{},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{},"thinking":{"type":"object"}},"required":["model","messages"]},"example":{"model":"claude-haiku-4-5","messages":[{"role":"user","content":"Привет! Ответь одной фразой."}]}}}},"responses":{"200":{"description":"Число входных токенов","content":{"application/json":{"schema":{"type":"object","properties":{"input_tokens":{"type":"integer"}},"required":["input_tokens"]},"example":{"input_tokens":16}}}},"400":{"description":"Неверный запрос","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"401":{"description":"Нет ключа или ключ недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"403":{"description":"Модель запрещена ключу","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"404":{"description":"Модель не Anthropic или не существует","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/messages/count_tokens \\\n  -H \"x-api-key: $MORSMORII_API_KEY\" \\\n  -H \"anthropic-version: 2023-06-01\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"claude-haiku-4-5\",\"messages\":[{\"role\":\"user\",\"content\":\"Привет! Ответь одной фразой.\"}]}'"},{"lang":"Python","label":"Python","source":"import anthropic  # pip install anthropic\nimport os\n\nclient = anthropic.Anthropic(base_url=\"https://api.morsmorii.ru\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nr = client.messages.count_tokens(\n    model=\"claude-haiku-4-5\",\n    messages=[{\"role\": \"user\", \"content\": \"Привет! Ответь одной фразой.\"}],\n)\nprint(r.input_tokens)"},{"lang":"JavaScript","label":"Node.js","source":"import Anthropic from \"@anthropic-ai/sdk\"; // npm i @anthropic-ai/sdk\n\nconst client = new Anthropic({ baseURL: \"https://api.morsmorii.ru\", apiKey: process.env.MORSMORII_API_KEY });\nconst r = await client.messages.countTokens({\n  model: \"claude-haiku-4-5\",\n  messages: [{ role: \"user\", content: \"Привет! Ответь одной фразой.\" }],\n});\nconsole.log(r.input_tokens);"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := strings.NewReader(`{\"model\":\"claude-haiku-4-5\",\"messages\":[{\"role\":\"user\",\"content\":\"Привет! Ответь одной фразой.\"}]}`)\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/messages/count_tokens\", body)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"anthropic-version\", \"2023-06-01\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/chat/completions":{"post":{"tags":["OpenAI-compatible"],"summary":"Chat Completions","description":"Формат OpenAI, включая stream, tools/tool_calls, response_format и stream_options.include_usage. model — id из /v1/models или agent:Имя (запрос пойдёт с инструкциями и базой знаний агента).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"},"example":{"model":"gpt-6-luna","messages":[{"role":"user","content":"Привет! Ответь одной фразой."}],"max_tokens":100}}}},"responses":{"200":{"description":"Ответ (JSON) или поток SSE при stream: true","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletion"},"example":{"id":"chatcmpl-…","object":"chat.completion","model":"gpt-6-luna","choices":[{"index":0,"message":{"role":"assistant","content":"Привет! Чем помочь?"},"finish_reason":"stop"}],"usage":{"prompt_tokens":14,"completion_tokens":7,"total_tokens":21}}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Неверный запрос","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа или ключ недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Модель не входит в тариф (model_not_in_plan) или запрещена ключу (model_not_allowed_for_key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Модель не найдена (model_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Квота тарифа (quota_exceeded), месячный бюджет ключа (key_budget_exceeded), бюджет компании — ключа за день, сотрудника или отдела (budget_exceeded) или частота (rate_limit_exceeded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Ошибка провайдера","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/chat/completions \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"gpt-6-luna\",\"messages\":[{\"role\":\"user\",\"content\":\"Привет! Ответь одной фразой.\"}],\"max_tokens\":100}'"},{"lang":"Python","label":"Python","source":"from openai import OpenAI  # pip install openai\nimport os\n\nclient = OpenAI(base_url=\"https://api.morsmorii.ru/v1\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nr = client.chat.completions.create(\n    model=\"gpt-6-luna\",\n    messages=[{\"role\": \"user\", \"content\": \"Привет! Ответь одной фразой.\"}],\n    max_tokens=100,\n)\nprint(r.choices[0].message.content)"},{"lang":"JavaScript","label":"Node.js","source":"import OpenAI from \"openai\"; // npm i openai\n\nconst client = new OpenAI({ baseURL: \"https://api.morsmorii.ru/v1\", apiKey: process.env.MORSMORII_API_KEY });\nconst r = await client.chat.completions.create({\n  model: \"gpt-6-luna\",\n  messages: [{ role: \"user\", content: \"Привет! Ответь одной фразой.\" }],\n  max_tokens: 100,\n});\nconsole.log(r.choices[0].message.content);"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := strings.NewReader(`{\"model\":\"gpt-6-luna\",\"messages\":[{\"role\":\"user\",\"content\":\"Привет! Ответь одной фразой.\"}],\"max_tokens\":100}`)\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/chat/completions\", body)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/messages":{"post":{"tags":["Anthropic-compatible"],"summary":"Messages API (Anthropic)","description":"Тело и события стрима — как у Anthropic: system, messages с блоками text/image/tool_use/tool_result, tools, max_tokens (обязателен), stream. Ключ — в заголовке x-api-key или Authorization: Bearer. Заголовок anthropic-version передаётся провайдеру. Только модели Anthropic: claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-4-5, или agent:Имя — свой агент или общий агент команды на модели Claude (инструкции, база знаний и параметры агента подставляются на сервере, system клиента идёт после инструкций агента; агент на модели другого провайдера — 400 invalid_request_error). Ошибки — в формате Anthropic.","security":[{"anthropicKey":[]},{"bearer":[]}],"parameters":[{"name":"anthropic-version","in":"header","required":false,"schema":{"type":"string","example":"2023-06-01"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagesRequest"},"example":{"model":"claude-haiku-4-5","max_tokens":100,"messages":[{"role":"user","content":"Привет! Ответь одной фразой."}]}}}},"responses":{"200":{"description":"Сообщение (JSON) или поток SSE с событиями message_start, content_block_start, content_block_delta, content_block_stop, message_delta, message_stop","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"example":{"id":"msg_…","type":"message","role":"assistant","model":"claude-haiku-4-5","content":[{"type":"text","text":"Привет! Чем помочь?"}],"stop_reason":"end_turn","usage":{"input_tokens":14,"output_tokens":9}}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Неверный запрос (в том числе без max_tokens)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"401":{"description":"Нет ключа или ключ недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"403":{"description":"Модель не в тарифе или запрещена ключу","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"404":{"description":"Модель не Anthropic или не существует","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"429":{"description":"Квота или бюджет ключа исчерпаны","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}},"529":{"description":"Провайдер перегружен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/messages \\\n  -H \"x-api-key: $MORSMORII_API_KEY\" \\\n  -H \"anthropic-version: 2023-06-01\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"claude-haiku-4-5\",\"max_tokens\":100,\"messages\":[{\"role\":\"user\",\"content\":\"Привет! Ответь одной фразой.\"}]}'"},{"lang":"Python","label":"Python","source":"import anthropic  # pip install anthropic\nimport os\n\nclient = anthropic.Anthropic(base_url=\"https://api.morsmorii.ru\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nmsg = client.messages.create(\n    model=\"claude-haiku-4-5\",\n    max_tokens=100,\n    messages=[{\"role\": \"user\", \"content\": \"Привет! Ответь одной фразой.\"}],\n)\nprint(msg.content[0].text)"},{"lang":"JavaScript","label":"Node.js","source":"import Anthropic from \"@anthropic-ai/sdk\"; // npm i @anthropic-ai/sdk\n\nconst client = new Anthropic({ baseURL: \"https://api.morsmorii.ru\", apiKey: process.env.MORSMORII_API_KEY });\nconst msg = await client.messages.create({\n  model: \"claude-haiku-4-5\",\n  max_tokens: 100,\n  messages: [{ role: \"user\", content: \"Привет! Ответь одной фразой.\" }],\n});\nconsole.log(msg.content[0].type === \"text\" ? msg.content[0].text : msg.content);"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := strings.NewReader(`{\"model\":\"claude-haiku-4-5\",\"max_tokens\":100,\"messages\":[{\"role\":\"user\",\"content\":\"Привет! Ответь одной фразой.\"}]}`)\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/messages\", body)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"anthropic-version\", \"2023-06-01\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/responses":{"post":{"tags":["OpenAI-compatible"],"summary":"Responses API (для Codex CLI)","description":"input строкой или списком, instructions, tools, previous_response_id (состояние хранится сутки), stream.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsesRequest"},"example":{"model":"gpt-6-luna","input":"Назови три планеты одной строкой."}}}},"responses":{"200":{"description":"Объект response или поток SSE","content":{"application/json":{"schema":{"type":"object"},"example":{"id":"resp_…","object":"response","status":"completed","model":"gpt-6-luna","output":[{"type":"message","role":"assistant","content":[{"type":"output_text","text":"Марс, Венера, Юпитер."}]}]}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Неверный запрос","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Модель недоступна","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"previous_response_id не найден или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Квота","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/responses \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"gpt-6-luna\",\"input\":\"Назови три планеты одной строкой.\"}'"},{"lang":"Python","label":"Python","source":"from openai import OpenAI\nimport os\n\nclient = OpenAI(base_url=\"https://api.morsmorii.ru/v1\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nr = client.responses.create(model=\"gpt-6-luna\", input=\"Назови три планеты одной строкой.\")\nprint(r.output_text)"},{"lang":"JavaScript","label":"Node.js","source":"import OpenAI from \"openai\";\n\nconst client = new OpenAI({ baseURL: \"https://api.morsmorii.ru/v1\", apiKey: process.env.MORSMORII_API_KEY });\nconst r = await client.responses.create({ model: \"gpt-6-luna\", input: \"Назови три планеты одной строкой.\" });\nconsole.log(r.output_text);"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := strings.NewReader(`{\"model\":\"gpt-6-luna\",\"input\":\"Назови три планеты одной строкой.\"}`)\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/responses\", body)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/responses/{id}":{"get":{"tags":["OpenAI-compatible"],"summary":"Последний ход сохранённого ответа","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Объект response"},"404":{"description":"Не найден или истёк","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["OpenAI-compatible"],"summary":"Забыть сохранённый ответ","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Удалено"},"404":{"description":"Не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/embeddings":{"post":{"tags":["OpenAI-compatible"],"summary":"Эмбеддинги","description":"Модель text-embedding-3-small (1536 измерений). До 2048 строк за запрос, 60 запросов в минуту на ключ.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","default":"text-embedding-3-small"},"input":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":2048}]}},"required":["input"]},"example":{"model":"text-embedding-3-small","input":"Договор поставки № 17"}}}},"responses":{"200":{"description":"Список векторов в формате OpenAI"},"400":{"description":"Неверный запрос","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Частота или квота","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/embeddings \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"text-embedding-3-small\",\"input\":\"Договор поставки № 17\"}'"},{"lang":"Python","label":"Python","source":"from openai import OpenAI\nimport os\n\nclient = OpenAI(base_url=\"https://api.morsmorii.ru/v1\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nr = client.embeddings.create(model=\"text-embedding-3-small\", input=\"Договор поставки № 17\")\nprint(len(r.data[0].embedding))  # 1536"},{"lang":"JavaScript","label":"Node.js","source":"import OpenAI from \"openai\";\n\nconst client = new OpenAI({ baseURL: \"https://api.morsmorii.ru/v1\", apiKey: process.env.MORSMORII_API_KEY });\nconst r = await client.embeddings.create({ model: \"text-embedding-3-small\", input: \"Договор поставки № 17\" });\nconsole.log(r.data[0].embedding.length); // 1536"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := strings.NewReader(`{\"model\":\"text-embedding-3-small\",\"input\":\"Договор поставки № 17\"}`)\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/embeddings\", body)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/images/generations":{"post":{"tags":["OpenAI-compatible"],"summary":"Картинка по описанию","description":"Модели: gpt-image-2, nano-banana, nano-banana-pro, yandex-art. Ответ всегда b64_json, одна картинка за запрос, 10 запросов в минуту на ключ. quality (medium, high) — у gpt-image-2; size (1K, 2K, 4K) — у nano-banana-pro.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","enum":["gpt-image-2","nano-banana","nano-banana-pro","yandex-art"]},"prompt":{"type":"string"},"quality":{"type":"string","enum":["medium","high"]},"size":{"type":"string","enum":["1K","2K","4K"]}},"required":["model","prompt"]},"example":{"model":"nano-banana","prompt":"Рыжий кот в очках читает книгу, акварель"}}}},"responses":{"200":{"description":"{ created, data: [{ b64_json }] }"},"400":{"description":"Неверный запрос","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Частота или квота","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/images/generations \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"nano-banana\",\"prompt\":\"Рыжий кот в очках читает книгу, акварель\"}'"},{"lang":"Python","label":"Python","source":"from openai import OpenAI\nimport base64, os\n\nclient = OpenAI(base_url=\"https://api.morsmorii.ru/v1\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nr = client.images.generate(model=\"nano-banana\", prompt=\"Рыжий кот в очках читает книгу, акварель\")\nopen(\"cat.png\", \"wb\").write(base64.b64decode(r.data[0].b64_json))"},{"lang":"JavaScript","label":"Node.js","source":"import OpenAI from \"openai\";\nimport { writeFileSync } from \"node:fs\";\n\nconst client = new OpenAI({ baseURL: \"https://api.morsmorii.ru/v1\", apiKey: process.env.MORSMORII_API_KEY });\nconst r = await client.images.generate({ model: \"nano-banana\", prompt: \"Рыжий кот в очках читает книгу, акварель\" });\nwriteFileSync(\"cat.png\", Buffer.from(r.data![0].b64_json!, \"base64\"));"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tbody := strings.NewReader(`{\"model\":\"nano-banana\",\"prompt\":\"Рыжий кот в очках читает книгу, акварель\"}`)\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/images/generations\", body)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}},"/v1/images/edits":{"post":{"tags":["OpenAI-compatible"],"summary":"Правка картинки по описанию","description":"multipart/form-data: model, prompt, image (файл). Правят gpt-image-2, nano-banana, nano-banana-pro; yandex-art отвечает model_cannot_edit. Маски не поддерживаются.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"model":{"type":"string"},"prompt":{"type":"string"},"image":{"type":"string","format":"binary"}},"required":["model","prompt","image"]}}}},"responses":{"200":{"description":"{ created, data: [{ b64_json }] }"},"400":{"description":"Неверный запрос или модель не правит (model_cannot_edit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Частота или квота","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://api.morsmorii.ru/v1/images/edits \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\" \\\n  -F model=gpt-image-2 \\\n  -F prompt=\"Сделай фон белым\" \\\n  -F image=@photo.png"},{"lang":"Python","label":"Python","source":"from openai import OpenAI\nimport base64, os\n\nclient = OpenAI(base_url=\"https://api.morsmorii.ru/v1\", api_key=os.environ[\"MORSMORII_API_KEY\"])\nr = client.images.edit(model=\"gpt-image-2\", prompt=\"Сделай фон белым\", image=open(\"photo.png\", \"rb\"))\nopen(\"edited.png\", \"wb\").write(base64.b64decode(r.data[0].b64_json))"},{"lang":"JavaScript","label":"Node.js","source":"import OpenAI, { toFile } from \"openai\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\n\nconst client = new OpenAI({ baseURL: \"https://api.morsmorii.ru/v1\", apiKey: process.env.MORSMORII_API_KEY });\nconst r = await client.images.edit({\n  model: \"gpt-image-2\",\n  prompt: \"Сделай фон белым\",\n  image: await toFile(readFileSync(\"photo.png\"), \"photo.png\"),\n});\nwriteFileSync(\"edited.png\", Buffer.from(r.data![0].b64_json!, \"base64\"));"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tvar buf bytes.Buffer\n\tw := multipart.NewWriter(&buf)\n\tw.WriteField(\"model\", \"gpt-image-2\")\n\tw.WriteField(\"prompt\", \"Сделай фон белым\")\n\tf, _ := os.Open(\"photo.png\")\n\tpart, _ := w.CreateFormFile(\"image\", \"photo.png\")\n\tio.Copy(part, f)\n\tw.Close()\n\treq, _ := http.NewRequest(\"POST\", \"https://api.morsmorii.ru/v1/images/edits\", &buf)\n\treq.Header.Set(\"Content-Type\", w.FormDataContentType())\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, len(out))\n}"}]}},"/v1/usage":{"get":{"tags":["Account"],"summary":"Расход по ключам, сотрудникам, отделам и моделям за период","description":"Владелец или админ компании видит всю компанию (scope org), руководитель отдела — свои отделы (scope department), остальные — свой расход (scope user). Период по умолчанию — текущий месяц (по Москве), максимум 366 дней. group_by — разрез (groups), detail=true — строки до запроса без содержимого с курсором (data, next_cursor). Фильтр по чужому отделу или сотруднику — 403 forbidden. Суммы — в рублях (*_rub).","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Включительно"},{"name":"group_by","in":"query","required":false,"schema":{"type":"string","enum":["department","member","key","model","kind","source","day"]},"description":"Разрез: отделы, сотрудники, ключи, модели, виды (text, api, image, media, search, voice, kb, other), источники (portal, api, claude-code, codex, cursor, cline, continue, jetbrains, aider, zed, windsurf, roo, kilo, n8n, dify, sdk-python, sdk-node, curl), дни"},{"name":"detail","in":"query","required":false,"schema":{"type":"boolean"},"description":"Детализация до запроса"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100},"description":"Строк детализации на страницу"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"next_cursor из прошлой страницы детализации"},{"name":"member","in":"query","required":false,"schema":{"type":"string"},"description":"Сотрудники: id или почта через запятую"},{"name":"department","in":"query","required":false,"schema":{"type":"string"},"description":"Отделы: id через запятую; none — без отдела"},{"name":"key","in":"query","required":false,"schema":{"type":"string"},"description":"Ключи: id через запятую; none — без ключа (портал)"},{"name":"model","in":"query","required":false,"schema":{"type":"string"},"description":"Модели через запятую"},{"name":"kind","in":"query","required":false,"schema":{"type":"string"},"description":"Виды: text, api, image, media, search, voice, kb, other"},{"name":"source","in":"query","required":false,"schema":{"type":"string"},"description":"Источники через запятую"}],"responses":{"200":{"description":"Сводка или детализация","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/UsageReport"},{"$ref":"#/components/schemas/UsageDetail"}]},"example":{"object":"usage","period":{"from":"2026-10-01T00:00:00+03:00","to":"…"},"total_rub":12.4,"groups":[{"key":"gpt-6-luna","cost_rub":1.2,"requests":40}]}}}},"400":{"description":"Неверный период или group_by","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Нет ключа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Фильтр вне вашей области (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://api.morsmorii.ru/v1/usage?group_by=model\" \\\n  -H \"Authorization: Bearer $MORSMORII_API_KEY\""},{"lang":"Python","label":"Python","source":"import os, requests  # pip install requests\n\nr = requests.get(\n    \"https://api.morsmorii.ru/v1/usage\",\n    params={\"group_by\": \"model\"},\n    headers={\"Authorization\": f\"Bearer {os.environ['MORSMORII_API_KEY']}\"},\n)\nprint(r.json()[\"total_rub\"])"},{"lang":"JavaScript","label":"Node.js","source":"const r = await fetch(\"https://api.morsmorii.ru/v1/usage?group_by=model\", {\n  headers: { Authorization: `Bearer ${process.env.MORSMORII_API_KEY}` },\n});\nconsole.log((await r.json()).total_rub);"},{"lang":"Go","label":"Go","source":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\treq, _ := http.NewRequest(\"GET\", \"https://api.morsmorii.ru/v1/usage?group_by=model\", nil)\n\treq.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"MORSMORII_API_KEY\"))\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer resp.Body.Close()\n\tout, _ := io.ReadAll(resp.Body)\n\tfmt.Println(resp.Status, resp.Header.Get(\"x-request-id\"))\n\tfmt.Println(string(out))\n}"}]}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Authorization: Bearer sk-..."},"anthropicKey":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string","enum":["invalid_request_error","authentication_error","rate_limit_error","api_error"]},"param":{"type":["string","null"]},"code":{"type":"string"}},"required":["message","type","code"]}},"required":["error"]},"AnthropicError":{"type":"object","properties":{"type":{"type":"string","const":"error"},"error":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"}},"required":["type","message"]}}},"Model":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","const":"model"},"created":{"type":"integer"},"owned_by":{"type":"string"}},"required":["id","object","created","owned_by"]},"ModelList":{"type":"object","properties":{"object":{"type":"string","const":"list"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string"},"created":{"type":"integer"},"owned_by":{"type":"string"}}}}}},"ChatCompletionRequest":{"type":"object","properties":{"model":{"type":"string","description":"Один из gpt-6-astra, gpt-6.1-sol, gpt-6-luna, claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-4-5, gemini-pro, gemini-flash, grok-4.7, deepseek-chat, deepseek-reasoner, qwen3.6-35b или agent:Имя","examples":["claude-sonnet-5-5"]},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["system","user","assistant","tool"]},"content":{},"tool_calls":{},"tool_call_id":{"type":"string"}},"required":["role"]}},"stream":{"type":"boolean"},"stream_options":{"type":"object","properties":{"include_usage":{"type":"boolean"}}},"temperature":{"type":"number"},"top_p":{"type":"number"},"max_tokens":{"type":"integer"},"tools":{"type":"array","items":{"type":"object"}},"tool_choice":{},"response_format":{"type":"object"}},"required":["model","messages"]},"ChatCompletion":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","const":"chat.completion"},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object"}},"usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}}}}},"MessagesRequest":{"type":"object","properties":{"model":{"type":"string","description":"Один из claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-4-5 или agent:Имя (агент на модели Claude)","examples":["claude-sonnet-5-5","agent:Ревьюер кода"]},"max_tokens":{"type":"integer","minimum":1},"system":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"object"}}]},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"object"}}]}},"required":["role","content"]}},"tools":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"input_schema":{"type":"object"}}}},"tool_choice":{"type":"object"},"stream":{"type":"boolean"},"temperature":{"type":"number"},"stop_sequences":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object"}},"required":["model","max_tokens","messages"]},"Message":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","const":"message"},"role":{"type":"string","const":"assistant"},"model":{"type":"string"},"content":{"type":"array","items":{"type":"object"}},"stop_reason":{"type":["string","null"],"enum":["end_turn","max_tokens","stop_sequence","tool_use",null]},"usage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"}}}}},"ResponsesRequest":{"type":"object","properties":{"model":{"type":"string"},"input":{},"instructions":{"type":"string"},"previous_response_id":{"type":"string"},"tools":{"type":"array","items":{"type":"object"}},"stream":{"type":"boolean"},"store":{"type":"boolean"},"max_output_tokens":{"type":"integer"}},"required":["model","input"]},"UsageReport":{"type":"object","properties":{"object":{"type":"string","const":"usage"},"scope":{"type":"string","enum":["org","department","user"]},"org":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"period":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"currency":{"type":"string","const":"RUB"},"total_rub":{"type":"number","description":"Расход за период, ₽ с копейками"},"requests":{"type":"integer"},"tokens":{"type":"object","properties":{"prompt":{"type":"integer"},"completion":{"type":"integer"},"cache_read":{"type":"integer"},"cache_write":{"type":"integer"}}},"group_by":{"type":"string"},"groups":{"type":"array","description":"Разрез при group_by","items":{"type":"object","properties":{"id":{"type":["string","null"]},"label":{"type":"string"},"detail":{"type":["string","null"]},"cost_rub":{"type":"number"},"requests":{"type":"integer"},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"cache_read_tokens":{"type":"integer"},"cache_write_tokens":{"type":"integer"},"share":{"type":"number","description":"Доля от итога, 0…1"}}}},"by_key":{"type":"array","items":{"type":"object","properties":{"key_id":{"type":"string"},"name":{"type":["string","null"]},"key_preview":{"type":["string","null"]},"email":{"type":["string","null"]},"revoked":{"type":["boolean","null"]},"budget_rub":{"type":["integer","null"],"description":"Месячный бюджет ключа, ₽ (null — только квота тарифа)"},"cost_rub":{"type":"number","description":"Расход ключа за период, ₽"},"requests":{"type":"integer"}}}},"by_member":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":["string","null"]},"name":{"type":["string","null"]},"cost_rub":{"type":"number","description":"Расход сотрудника за период, ₽"},"requests":{"type":"integer"},"by_kind":{"type":"object","additionalProperties":{"type":"number"},"description":"₽ по видам расхода (chat, api, image…)"}}}}}},"UsageDetail":{"type":"object","properties":{"object":{"type":"string","const":"usage.detail"},"scope":{"type":"string","enum":["org","department","user"]},"period":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"currency":{"type":"string","const":"RUB"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"user_id":{"type":"string"},"email":{"type":["string","null"]},"department_id":{"type":["string","null"]},"department":{"type":"string"},"key_id":{"type":["string","null"]},"model":{"type":"string"},"kind":{"type":"string"},"source":{"type":["string","null"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"cache_read_tokens":{"type":"integer"},"cache_write_tokens":{"type":"integer"},"cost_rub":{"type":"number"}}}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}}}}}