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

Руководство по интеграции API без цензуры: регистрация, проверка, первый вызов

Это руководство делает одно: позволяет выполнить первый запрос за десять минут. Не нужно SDK — используйте стандартные библиотеки для HTTP-запросов, так как API представляет собой один POST-эндпоинт. Понимание структуры запроса поможет легко перейти на любой фреймворк. Примеры для Python (requests), Java (java.net.http), Go (net/http) и PHP (curl) можно сразу скопировать и запустить.

Обновлено

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

  • Для регистрации нужны только email и пароль. Новый аккаунт получает $0.50 пробного баланса, действительного в течение 7 дней. Привязка платёжной информации не требуется.
  • Базовый URL — https://api.wushenchaapi.com/v1,模型名固定写 uncensored, заголовок авторизации — Authorization: Bearer.
  • Сначала выполните GET /v1/models для проверки ключа, затем POST /v1/chat/completions. Раздельная диагностика по этим двум шагам — самый быстрый способ найти проблему.
  • Во всех четырёх языках необходимо установить тайм-аут и считывать error.code, а не полагаться только на HTTP-статус.

Чек-лист перед началом работы

Пройдитесь по списку заранее, чтобы избежать возвратов в процессе.

  • Действующий адрес электронной почты для регистрации.
  • На вашем компьютере установлена любая из сред: Python 3, JDK 15+ (для примера с текстовыми блоками), Go или PHP с расширением curl.
  • Убедитесь, что вам исполнилось 18 лет, так как сервис предназначен только для совершеннолетних пользователей.
  • Помните, что сервис предназначен исключительно для текстовых диалогов: здесь доступна только одна модель, без поддержки векторов, изображений, аудио или дообучения.
  • Подготовьте сохранение ключа в переменных окружения, не записывайте его в исходный код и тем более не коммитьте в репозиторий.

Спецификация API минимальна: адрес https://api.wushenchaapi.com/v1 совместим с форматом OpenAI chat completion, поэтому вы можете использовать ваши старые тела запросов без изменений.

Ожидаемое время: регистрация — одна минута, установка среды зависит от вашего компьютера, первый запрос занимает не более тридцати секунд. Если по истечении этого времени результат ещё не получен, скорее всего, проблема в сети или ключе. Перейдите к списку устранения неполадок в конце статьи. Действуйте строго по порядку: сначала models, затем chat; сначала синхронно, затем потоковая передача. Подтверждайте каждый шаг, прежде чем переходить к следующему.

Регистрация и получение ключа

Откройте /get-api-key/ и зарегистрируйтесь, указав адрес электронной почты и пароль. После завершения регистрации ключ отображается сразу; просто скопируйте его. Обратите внимание на следующие детали:

  1. У каждого аккаунта есть только один ключ.
  2. Ключ можно перегенерировать, но старый ключ немедленно становится недействительным. Перед заменой ключа на продакшене убедитесь, что новое значение уже развёрнуто.
  3. Новый аккаунт получает пробный баланс $0.50, действительный в течение 7 дней; никакая платёжная информация не требуется.
  4. По истечении срока действия пробного баланса или при его исчерпании запросы возвращают статус 402 с кодом ошибки no_credit. Пополните предоплаченный баланс, чтобы продолжить работу. Это не подписка, и баланс не истекает.

Сохраните ключ в переменной окружения: macOS / Linux: export API_KEY=ваш_ключ; Windows PowerShell: $env:API_KEY="ваш_ключ". Все примеры ниже используют значение из API_KEY.

Шаг 1: проверка доступности через /v1/models

Не спешите отправлять диалоговые запросы. Сначала выполните бесплатный GET-запрос, чтобы убедиться, что адрес, сеть и ключ работают корректно:

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

Возврат статуса 200 и списка моделей (содержащего только uncensored) означает успешное подключение. Статус 401 указывает на неверный ключ или его отсутствие; тайм-аут требует проверки сети и прокси на вашем компьютере. Разделение проблем подключения и структуры запроса — лучшая привычка для ускорения интеграции.

Python: requests

Без SDK: одного requests.post достаточно. Важно: укажите timeout; проверяйте r.ok перед доступом к choices; при ошибке тело: {"error":{"code":...,"message":...}}.

import os
import requests

url = "https://api.wushenchaapi.com/v1/chat/completions"
headers = {
    "Authorization": "Bearer " + os.environ["API_KEY"],
    "Content-Type": "application/json",
}
payload = {
    "model": "uncensored",
    "messages": [{"role": "user", "content": "用两句话描述一场雨夜里的追逐戏。"}],
    "max_tokens": 300,
}
r = requests.post(url, headers=headers, json=payload, timeout=120)
print(r.status_code)
data = r.json()
if r.ok:
    print(data["choices"][0]["message"]["content"])
    print(data["usage"])
else:
    print(data["error"]["code"], data["error"]["message"])

При успешном ответе в поле usage содержатся prompt_tokens и completion_tokens. Рекомендуется выводить их при каждом запросе во время разработки, чтобы контролировать расходы.

Разбор тела запроса по полям

Все четыре языка отправляют один и тот же JSON. Разберитесь в его структуре, и перевод на любой язык будет простым.

ПолеОбязательноОписание
modelДаФиксированное значение: uncensored.
messagesДаМассив объектов, каждый из которых содержит role и content. Допустимые значения role: system, user, assistant.
max_tokensНетЗначение по умолчанию — 2048, максимальное ограничение на один запрос — 16,000. Для генерации длинных текстов необходимо увеличить это значение вручную.
temperature / top_p / stopНетСтандартные параметры выборки, передаются без изменений.
streamНетПри значении true используется потоковая передача через SSE.

В ответе вы будете читать три поля: choices[0].message.content — это текст, choices[0].finish_reason — причина завершения (нормальная или обрезка по длине), usage — использование токенов. Для полноценной интеграции необходимо прочитать все три поля.

Запомните ещё два жёстких ограничения: тело запроса не должно превышать 8 МБ, лимит составляет 300 запросов в минуту на ключ. Не запускайте все параллельные запросы сразу — установите разумный лимит параллельности.

Java: java.net.http

Начиная с JDK 11 HttpClient идёт в комплекте, никаких дополнительных зависимостей не требуется. В примере ниже используется текстовый блок JDK 15 для записи JSON; в более старых версиях можно заменить его на конкатенацию строк или использовать любую знакомую вам JSON-библиотеку для сериализации.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Demo {
    public static void main(String[] args) throws Exception {
        String key = System.getenv("API_KEY");
        String body = """
            {"model":"uncensored",
             "messages":[{"role":"user","content":"写一段两百字以内的悬疑小说开头。"}],
             "max_tokens":400}
            """;
        HttpRequest req = HttpRequest.newBuilder(
                URI.create("https://api.wushenchaapi.com/v1/chat/completions"))
            .timeout(Duration.ofSeconds(120))
            .header("Authorization", "Bearer " + key)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        HttpResponse<String> resp = HttpClient.newHttpClient()
            .send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println(resp.statusCode());
        System.out.println(resp.body());
    }
}

Совет: если контент содержит китайский текст, BodyPublishers.ofString кодирует его в UTF-8 по умолчанию, дополнительная обработка не нужна. В продакшене используйте HttpClient как синглтон, не создавая его для каждого запроса.

Go: net/http

Стандартная библиотека Go также вполне подходит. Главное — не используйте http.DefaultClient без установки таймаута, иначе при зависании сервера goroutine будет висеть бесконечно.

package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	body := []byte(`{"model":"uncensored","messages":[{"role":"user","content":"给一个反派角色写三句独白。"}],"max_tokens":300}`)
	req, err := http.NewRequest("POST", "https://api.wushenchaapi.com/v1/chat/completions", bytes.NewReader(body))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 120 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	out, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(out))
}

Прочитайте тело ответа полностью с помощью io.ReadAll, прежде чем парсить. Для структурированной обработки определите соответствующую struct и десериализуйте данные с помощью encoding/json. Поля будут содержать choices, message, content, usage.

PHP: curl

В PHP используйте расширение curl. При использовании json_encode обязательно добавьте флаг JSON_UNESCAPED_UNICODE, иначе китайские символы будут преобразованы в \uXXXX. Хотя это будет работать, отлаживать такой вывод будет неудобно.

<?php
$payload = [
    "model" => "uncensored",
    "messages" => [["role" => "user", "content" => "写一首八行的现代诗,主题是末班地铁。"]],
    "max_tokens" => 300,
];
$ch = curl_init("https://api.wushenchaapi.com/v1/chat/completions");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
$res = curl_exec($ch);
if ($res === false) {
    die("curl 错误: " . curl_error($ch) . "\n");
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, "\n";
$data = json_decode($res, true);
echo $data["choices"][0]["message"]["content"] ?? $res, "\n";

Обратите внимание на различие между двумя типами ошибок: если curl_exec возвращает false, это проблема на сетевом уровне; если ответ получен, но код состояния не 200, это проблема на уровне API — необходимо прочитать error.code.

Типичные проблемы при первом вызове

  • 401: Заголовок записан как Authorization: ключ, пропущен префикс Bearer ; или переменная окружения не подгрузилась в новом терминале.
  • 404: В URL отсутствует путь /v1 или неправильно набран путь chat/completions.
  • 400: JSON некорректен или суммарный размер промпта и max_tokens превышает лимит в 100,000 токенов.
  • 402: Закончился баланс или истёк срок действия пробного периода.
  • Вывод обрезан: max_tokens по умолчанию равен 2048, максимум — 16,000. Для генерации длинных текстов необходимо явно увеличить это значение.
  • Нужна потоковая передача: добавьте в тело запроса "stream": true. Ответ приходит через SSE, в конце автоматически добавляется блок данных с usage.

После успешного запуска изучите форматирование промптов для улучшения качества вывода. При ошибках обращайтесь к справочнику по кодам ошибок. Полное описание параметров — в документации, цены — на странице с ценами.

После того как запросы начнут работать, перед запуском в продакшен добавьте три элемента

Примеры в этом руководстве — минимально рабочая версия. Для интеграции в реальный сервис необходимо добавить как минимум три элемента.

  1. Тайм-аут. В примере установлено 120 секунд, так как генерация длинных текстов действительно медленная. Если ваш сценарий требует синхронного ожидания, сократите тайм-аут до приемлемого значения и используйте потоковую передачу, чтобы пользователь видел текст сразу.
  2. Разделение ошибок. Ошибки 401, 402, 403 не требуют повторных попыток — отправляйте алерт или сообщение пользователю. Повторные попытки с backoff уместны только для 429 и 503. Детали см. в руководстве по устранению ошибок.
  3. Учёт расходов. Записывайте в лог значение usage из каждого ответа. В лог заносите только цифры, не сохраняйте пользовательский контент. Эти данные понадобятся для сверки счетов в конце месяца и анализа аномальных расходов.

Ещё раз о управлении ключами: ключ только один. После утечки его можно только перегенерировать, а перегенерация приведёт к одновременному отключению всех работающих сервисов. Поэтому не разбрасывайте его по конфигурациям множества скриптов и машин, а храните централизованно в одном месте для ключей, чтобы при замене ничего не упустить.

Границы контента: допустимый контент для взрослых, художественная литература и спорные темы не блокируются. Однако контент сексуального характера с участием несовершеннолетних всегда блокируется с кодом 403, даже в ролевых играх. Если ваше приложение для взрослых, добавьте проверку возраста в процесс регистрации.

Порядок самопроверки: есть ли ключ в переменной окружения; доступны ли models; является ли тело запроса валидным JSON; является ли модель uncensored; достаточно ли max_tokens; finish_reason — stop или length; записан ли usage. Если все семь пунктов зелёные, интеграция завершена.

Часто задаваемые вопросы

Обязательно ли использовать официальный SDK для вызова API?

Нет. Это стандартный HTTPS POST с JSON-телом, его можно использовать из любого языка, поддерживающего HTTP-запросы. SDK лишь оборачивает этот вызов в удобную обёртку.

Какое значение указать в поле model?

Укажите фиксированное значение uncensored. На данный момент доступна только одна модель; её наличие можно проверить запросом GET /v1/models.

Что произойдёт, когда закончится пробный баланс?

Запрос вернёт код 402 с ошибкой no_credit. Вы сможете продолжить работу, пополнив предоплаченный баланс. Баланс не имеет срока действия, подписка не требуется.

Повлияет ли перегенерация ключа на старый ключ?

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

Для получения ключа достаточно заполнить форму

Создайте аккаунт, скопируйте ключ, измените Base URL. Настройка настолько проста.