RU ▾
https://api.unrestrictedaiapi.com/v1uncensored2026-10-06
Получить API-ключ

Быстрый старт Unrestricted AI API: Python, JavaScript, Go, PHP и Ruby

Вам не нужен SDK для использования Unrestricted AI API. Он работает по обычному HTTP и JSON, поэтому любой язык с HTTP-клиентом подойдет. На этой странице вы найдете по одному проверенному запросу для Python, JavaScript, Go, PHP и Ruby, а также коды состояния для обработки и правило повторных попыток, чтобы скрипты не падали.

Обновлено

Ключевые моменты

  1. Один эндпоинт, один ID модели (uncensored), один токен bearer: одно тело запроса работает на всех языках.
  2. Устанавливайте явные таймауты. Долгие генерации могут превышать стандартные таймауты клиентов.
  3. Проверяйте код состояния перед парсингом; тела 402 и 403 — это валидный JSON без массива choices.
  4. Повторяйте только 429 и 503 с коротким экспоненциальным отступом.

Весь API в одном curl

На минуту забудьте про SDK. Каждый пример ниже отправляет одно и то же: JSON-тело в POST /v1/chat/completions с токеном авторизации. Если вы можете это отправить, задача решена. Получите ключ на странице регистрации (для пробного баланса не нужны данные карты), экспортируйте его как API_KEY и запустите это.

curl https://api.unrestrictedaiapi.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "messages": [{"role": "user", "content": "Write a two-line noir opening set in a laundromat."}],
    "max_tokens": 120
  }'

Ответ — объект в стиле OpenAI. Текст находится по адресу choices[0].message.content, а блок usage сообщает, сколько стоил вызов в токенах. Есть одна модель, uncensored, поэтому поле model никогда не меняется. Вы можете подтвердить это с помощью GET /v1/models.

curl https://api.unrestrictedaiapi.com/v1/models -H "Authorization: Bearer $API_KEY"

Два лимита, которые стоит запомнить перед написанием кода: контекстное окно составляет 100 000 токенов, общих для промпта и ответа, а max_tokens по умолчанию равен 2048, если вы не увеличите его (до 32 000). Если ваш вывод постоянно обрывается на полуслове, причина обычно в этом значении по умолчанию.

Python с httpx

httpx предоставляет синхронный клиент с разумными таймаутами и асинхронную версию, когда она нужна. Установите таймаут явно. Долгие генерации могут занять много времени, а стандартные пять секунд их оборвут.

import os
import httpx

resp = httpx.post(
    "https://api.unrestrictedaiapi.com/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
        "model": "uncensored",
        "messages": [
            {"role": "system", "content": "You are a blunt, vivid fiction writer."},
            {"role": "user", "content": "Pitch a heist where the vault is a night market."},
        ],
        "temperature": 0.9,
        "max_tokens": 300,
    },
    timeout=60.0,
)
resp.raise_for_status()
print(resp.json()["choices"][0]["message"]["content"])

raise_for_status() преобразует любой 4xx или 5xx в исключение, что нормально для скрипта. Для любых длительных операций оберните вызов так, чтобы два статуса получили еще один шанс: 429 (вы достигли лимита в 300 запросов в минуту для ключа) и 503 (upstream_busy, который проходит через несколько секунд). Все остальное, включая 401, 402 и 403, само не исправится при повторной попытке.

import os
import time
import httpx

def chat(messages, retries=3):
    for attempt in range(retries + 1):
        r = httpx.post(
            "https://api.unrestrictedaiapi.com/v1/chat/completions",
            headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
            json={"model": "uncensored", "messages": messages, "max_tokens": 400},
            timeout=60.0,
        )
        if r.status_code in (429, 503) and attempt < retries:
            time.sleep(2 ** attempt)
            continue
        r.raise_for_status()
        return r.json()["choices"][0]["message"]["content"]

print(chat([{"role": "user", "content": "Name five cursed objects found in a thrift store."}]))

Замените httpx.post на httpx.AsyncClient().post внутри async def, и у вас будет асинхронная версия с теми же данными.

JavaScript с fetch

Node 18 и новее поставляются с fetch, поэтому ничего устанавливать не нужно. Сохраните файл как .mjs (или установите "type": "module"), чтобы работал верхнеуровневый await. В браузерах тот же API, но не помещайте ключ в код фронтенда. Проксируйте вызов через свой бэкенд.

const res = await fetch("https://api.unrestrictedaiapi.com/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "uncensored",
    messages: [{ role: "user", content: "Describe a villain's morning routine in four bullets." }],
    max_tokens: 250,
  }),
});

if (!res.ok) {
  const err = await res.json().catch(() => ({}));
  throw new Error(`HTTP ${res.status}: ${err?.error?.message ?? "unknown error"}`);
}

const data = await res.json();
console.log(data.choices[0].message.content);

Обратите внимание на порядок проверок. fetch возвращает ошибку только при сбое сети, поэтому 402 или 403 приходит как обычный ответ. Проверьте res.ok самостоятельно и прочитайте JSON ошибки, который всегда имеет вид {"error":{"code":...,"message":...}}.

Go с net/http

Go требует нескольких дополнительных строк, но не требует зависимостей. Определите только поля структуры, которые вы читаете; encoding/json игнорирует остальные. Чтение тела в байты перед проверкой статуса позволяет вывести сообщение об ошибке сервера, когда что-то идет не так.

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

type reply struct {
	Choices []struct {
		Message struct {
			Content string `json:"content"`
		} `json:"message"`
	} `json:"choices"`
}

func main() {
	payload, _ := json.Marshal(map[string]any{
		"model": "uncensored",
		"messages": []map[string]string{
			{"role": "user", "content": "Give me a ghost story in exactly three sentences."},
		},
		"max_tokens": 200,
	})

	req, _ := http.NewRequest("POST", "https://api.unrestrictedaiapi.com/v1/chat/completions", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusOK {
		panic(fmt.Sprintf("HTTP %d: %s", resp.StatusCode, body))
	}

	var out reply
	if err := json.Unmarshal(body, &out); err != nil {
		panic(err)
	}
	fmt.Println(out.Choices[0].Message.Content)
}

Для продакшена создайте один http.Client{Timeout: 60 * time.Second} и переиспользуйте его. Клиент по умолчанию не имеет таймаута вообще, что превращает зависший запрос в зависший горутину.

PHP с cURL и Ruby с Net::HTTP

Расширение cURL PHP уже есть на большинстве хостов. Создайте тело с помощью json_encode, верните передачу как строку, затем прочитайте статус с помощью curl_getinfo. Пропуск проверки статуса — классическая ошибка: тело 402 успешно декодируется как JSON, и ваш код затем падает из-за отсутствующего ключа choices.

<?php
$payload = json_encode([
    "model" => "uncensored",
    "messages" => [
        ["role" => "user", "content" => "Write a villanelle opening about a broken vending machine."],
    ],
    "max_tokens" => 200,
]);

$ch = curl_init("https://api.unrestrictedaiapi.com/v1/chat/completions");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 60,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => $payload,
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($body === false || $status !== 200) {
    fwrite(STDERR, "HTTP $status: $body\n");
    exit(1);
}

$data = json_decode($body, true);
echo $data["choices"][0]["message"]["content"], "\n";

На общем хосте с низким max_execution_time держите max_tokens умеренным или переместите вызов в воркер очереди.

Стандартной библиотеки здесь также достаточно. ENV.fetch сразу вызывает ошибку, если переменная отсутствует, что лучше, чем отправка пустого токена bearer и отладки 401 в течение десяти минут.

require "net/http"
require "json"
require "uri"

uri = URI("https://api.unrestrictedaiapi.com/v1/chat/completions")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('API_KEY')}"
req["Content-Type"] = "application/json"
req.body = JSON.generate(
  model: "uncensored",
  messages: [{ role: "user", content: "Invent a tavern rumor that sounds too specific to be fake." }],
  max_tokens: 200
)

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true, read_timeout: 60) { |http| http.request(req) }
abort("HTTP #{res.code}: #{res.body}") unless res.is_a?(Net::HTTPSuccess)

puts JSON.parse(res.body).dig("choices", 0, "message", "content")

Если позже вы перейдете на Rails, то же тело работает из фоновой задачи. Держите вызов вне цикла запроса; генерации медленнее, чем запрос к базе данных.

Оба фрагмента отправляют ровно то тело, которое отправляет Python-версия, в чем и суть: если один язык работает, а другой нет, сравнивайте JSON, а не клиент. Выведите сырое тело запроса один раз и сравните побайтово. В девяти случаях из десяти виноват отсутствующий заголовок Content-Type или имя модели, набранное с заглавной буквы.

Потоковая передача без библиотеки

Потоковая передача — единственное место, где обычный HTTP просит от вас немного больше. С stream: true сервер отвечает событиями, отправляемыми сервером: каждая строка начинается с data: , содержит фрагмент JSON, а поток заканчивается с data: [DONE]. Финальный фрагмент usage добавляется автоматически, поэтому вы получаете подсчет токенов даже при потоковой передаче. Этот фрагмент не имеет записей choices, поэтому цикл ниже проверяет перед индексацией.

import json
import os
import httpx

body = {
    "model": "uncensored",
    "messages": [{"role": "user", "content": "Tell a campfire story about a lighthouse keeper."}],
    "stream": True,
    "max_tokens": 400,
}
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}

with httpx.stream("POST", "https://api.unrestrictedaiapi.com/v1/chat/completions",
                  headers=headers, json=body, timeout=60.0) as r:
    r.raise_for_status()
    for line in r.iter_lines():
        if not line.startswith("data: "):
            continue
        data = line[6:]
        if data == "[DONE]":
            break
        chunk = json.loads(data)
        if chunk.get("choices"):
            print(chunk["choices"][0]["delta"].get("content") or "", end="", flush=True)
print()

Та же логика работает напрямую. В JavaScript прочитайте res.body с помощью reader и разбейте по символам новой строки. В Go оберните resp.Body в bufio.Scanner. В Ruby передайте блок в http.request и используйте read_body. В PHP установите колбэк CURLOPT_WRITEFUNCTION. Логика не меняется: удалите префикс, остановитесь на маркере, распарсите JSON, выведите разницу.

Пятиминутный smoke-тест и проверка бюджета

Прежде чем строить что-то на основе этих фрагментов, выполните быструю проверку. Сначала вызовите /v1/models со своим ключом; 200 подтверждает ключ и сетевой путь. Во-вторых, отправьте минимальный запрос чата с max_tokens, установленным в 20. В-третьих, намеренно сломайте что-то, например, пустой токен bearer, и подтвердите, что ваш код четко выводит 401, а не падает из-за отсутствующего поля.

Затем выполните арифметику один раз, чтобы вас ничего не удивило. Цены: $0,25 за миллион входных токенов и $1,00 за миллион выходных токенов. Для иллюляции предположим, что запрос отправляет 600 промпт-токенов и получает 400 токенов в ответ. Это 600 x $0,25 / 1 000 000 = $0,00015 на вход, плюс 400 x $1,00 / 1 000 000 = $0,0004 на выход, около $0,00055 за вызов. Пробный баланс в $0,50 покроет примерно 900 вызовов такого размера. Ваши реальные промпты будут отличаться, поэтому прочитайте блок usage в нескольких ответах и умножьте от туда.

Пробный баланс действует семь дней и не требует данных карты, что вполне достаточно для тестирования всех пяти языков. Если вам нужен пример использования, руководство по NSFW-контенту показывает полный пример. Помните, что один ключ принадлежит одному аккаунту; если вы сгенерируете его заново, обновите все скрипты одновременно, так как старый ключ перестанет работать немедленно.

Ошибки, которые выглядят одинаково на всех языках

Поскольку API — это обычный HTTP, обработка сбоев идентична независимо от выбранного языка. Запомните эту таблицу, и вы сможете портировать любой фрагмент выше.

СтатусЗначениеДействие
400Неверный запрос, например, промпт плюс max_tokens более 100 тыс.Уменьшите промпт или снизьте max_tokens
401Отсутствующий или недействительный ключПроверьте API_KEY; при регенерации старый ключ мгновенно становится недействительным
402no_credit: баланс исчерпан или пробный период истёкПополните предоплаченный баланс
403content_blockedНе повторяйте запрос; контент сексуального характера с участием несовершеннолетних блокируется всегда
429Более 300 запросов в минутуСделайте паузу и повторите запрос
503upstream_busyПовторите запрос через несколько секунд

Когда основы заработают, установите stream: true для вывода токенов по одному и читайте потоковые события построчно. Улучшайте промпты с помощью руководства по промптам или подключите тот же вызов к чат-платформе с помощью инструкции по созданию бота. Тарифы указаны на странице цен.

Вопросы и ответы

Нужен ли мне SDK OpenAI для вызова этого API?

Нет. Примеры здесь используют только стандартные HTTP-инструменты каждого языка. SDK от OpenAI тоже работают, если указать их базовый URL на https://api.unrestrictedaiapi.com/v1.

Какой идентификатор модели мне отправить?

Всегда «без цензуры». Существует одна модель, и GET /v1/models её перечисляет.

Почему мой ответ оборвался посреди предложения?

Значение max_tokens по умолчанию равно 2048. Увеличивайте его для каждого запроса до 32 000, пока сумма промпта и ответа не превысит 100 000 токенов.

При каких ошибках мой код должен повторять запрос?

Повторяйте запросы с кодами 429 (лимит запросов) и 503 (upstream_busy) после небольшой задержки. Ошибки 400, 401, 402 и 403 требуют изменений на вашей стороне, поэтому повторные запросы будут тратить вызовы впустую.

Ваш ключ — в одной форме от вас

Создайте аккаунт, скопируйте ключ, измените базовый URL. Это вся настройка.

Получить API-ключ