VI ▾
Lấy khóa API

Hướng dẫn tích hợp API không kiểm duyệt: Đăng ký, xác thực, lần gọi đầu tiên

Hướng dẫn này chỉ làm một việc: giúp bạn thực hiện thành công yêu cầu đầu tiên trong mười phút. Không cần SDK, hãy dùng thư viện chuẩn của từng ngôn ngữ để gửi HTTP, vì bản chất chỉ có một endpoint POST. Hiểu cấu trúc yêu cầu sẽ giúp bạn tự tin khi chuyển đổi framework. Ví dụ bao gồm Python requests, Java java.net.http, Go net/http và PHP curl; bạn có thể sao chép và chạy ngay.

Cập nhật lúc

Điểm chính

  • Bạn chỉ cần email và mật khẩu để đăng ký. Tài khoản mới nhận $0.50 tín dụng dùng thử miễn phí, có hiệu lực trong 7 ngày và không cần liên kết thông tin thanh toán.
  • Base URL là https://api.wushenchaapi.com/v1,模型名固定写 uncensored, tiêu đề xác thực là Authorization: Bearer.
  • Đầu tiên GET /v1/models để kiểm tra key, sau đó POST /v1/chat/completions, kiểm tra từng bước riêng biệt sẽ nhanh nhất.
  • Bốn ngôn ngữ đều cần đặt thời gian chờ và đọc error.code thay vì chỉ xem mã trạng thái HTTP.

Danh sách kiểm tra trước khi bắt đầu

Hãy xem qua trước để tránh phải quay lại giữa chừng.

  • Một địa chỉ email có thể nhận thư để đăng ký.
  • Máy bạn có một trong các môi trường: Python 3, JDK 15+, Go hoặc PHP có curl. Ví dụ dùng khối văn bản.
  • Xác nhận bạn là người trưởng thành trên 18 tuổi, dịch vụ chỉ dành cho người dùng trưởng thành.
  • Bạn biết mình cần hội thoại văn bản thuần: ở đây chỉ có một mô hình, không có vector, hình ảnh, giọng nói hay tinh chỉnh.
  • Chuẩn bị lưu khóa trong biến môi trường, không viết vào mã nguồn và đừng commit lên kho lưu trữ.

Quy ước endpoint rất đơn giản: https://api.wushenchaapi.com/v1, tương thích với định dạng chat completion của OpenAI, nên request body bạn đã viết trước đây hầu như có thể giữ nguyên.

Ước tính thời gian: đăng ký mất một phút, cài đặt môi trường tùy thuộc vào máy bạn, lần gọi đầu tiên không quá 30 giây. Nếu vượt quá thời gian này mà chưa có kết quả, khả năng cao là do mạng hoặc khóa, hãy nhảy ngay đến danh sách xử lý lỗi ở cuối trang. Thứ tự đúng: kiểm tra models trước, sau đó đến chat; kiểm tra đồng bộ trước, rồi mới đến streaming. Xác nhận từng bước rồi mới tiếp tục.

Đăng ký và lấy key

Mở /get-api-key/, đăng ký bằng email và mật khẩu. Khóa sẽ hiển thị ngay sau khi đăng ký, bạn chỉ cần sao chép. Một số chi tiết:

  1. Mỗi tài khoản chỉ có một khóa.
  2. Bạn có thể tạo lại khóa, nhưng khóa cũ sẽ mất hiệu lực ngay lập tức. Hãy triển khai giá trị mới trước khi thay khóa trên dịch vụ trực tuyến.
  3. Tài khoản mới được tặng $0.50 tín dụng dùng thử miễn phí, có hiệu lực trong 7 ngày, không cần điền thông tin thanh toán.
  4. Khi hết hạn hoặc hết tín dụng dùng thử miễn phí, yêu cầu sẽ trả về 402 với mã lỗi no_credit. Bạn chỉ cần nạp tiền vào số dư tín dụng trả trước để tiếp tục sử dụng. Đây không phải gói đăng ký, số dư không bao giờ hết hạn.

Đặt khóa vào biến môi trường: macOS/Linux chạy export API_KEY=your_key, PowerShell dùng $env:API_KEY="your_key". Các ví dụ sau đọc từ API_KEY.

Bước 1: Xác minh khả năng kết nối bằng /v1/models

Đừng vội gửi hội thoại. Hãy thực hiện một lệnh GET không tốn phí để xác nhận ba yếu tố: địa chỉ, mạng và key đều hoạt động:

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

Trả về 200 và danh sách mô hình (chỉ có uncensored) là thành công. 401 là khóa sai/thiếu; timeout là kiểm tra mạng/proxy. Tách lỗi kết nối và body giúp bạn tiết kiệm thời gian.

Python: requests

Không cần SDK, một lệnh requests.post là đủ. Lưu ý ba điểm: phải đặt timeout; kiểm tra r.ok trước khi lấy choices; khi lỗi, thân phản hồi là {"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"])

Khi thành công, usage chứa prompt_tokens và completion_tokens. Trong giai đoạn phát triển, bạn nên in ra mọi lúc để nắm rõ chi phí.

Phân tích chi tiết từng trường trong thân yêu cầu

Bốn ngôn ngữ đều gửi cùng một JSON. Hãy hiểu nó trước, viết ngôn ngữ nào cũng chỉ là bản dịch.

TrườngBắt buộcMô tả
modelCóCố định là uncensored.
messagesCóMảng, mỗi mục chứa role và content, role nhận system, user, assistant.
max_tokensKhôngMặc định 2048, giới hạn tối đa mỗi lần là 16,000. Bạn phải tự tăng lên khi viết văn bản dài.
temperature / top_p / stopKhôngCác tham số lấy mẫu tiêu chuẩn, truyền nguyên vẹn.
streamKhôngKhi là true, luồng sẽ chạy theo chuẩn SSE.

Bạn thường chỉ đọc ba phần trong phản hồi: choices[0].message.content là nội dung chính, choices[0].finish_reason cho bạn biết là kết thúc bình thường hay bị cắt do giới hạn độ dài, usage là số token đã dùng cho yêu cầu này. Đọc cả ba phần thì bạn mới tích hợp đầy đủ.

Hai giới hạn cứng: body dưới 8 MB, mỗi khóa 300 yêu cầu/phút. Đừng gửi ồ ạt yêu cầu đồng thời, hãy đặt giới hạn song song trước.

Java: java.net.http

JDK 11 đã tích hợp sẵn HttpClient, bạn không cần thêm bất kỳ thư viện nào. Đoạn mã dưới đây dùng tính năng text block của JDK 15 để viết JSON; nếu dùng phiên bản thấp hơn, bạn có thể chuyển sang nối chuỗi hoặc dùng thư viện JSON quen thuộc để serialize.

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());
    }
}

Lưu ý: Khi nội dung có tiếng Trung, BodyPublishers.ofString sẽ mặc định dùng mã hóa UTF-8, bạn không cần xử lý thêm. Trong môi trường production, bạn hãy triển khai HttpClient dưới dạng singleton để tái sử dụng, đừng tạo mới mỗi lần gửi yêu cầu.

Go: net/http

Thư viện chuẩn của Go cũng đủ dùng. Điểm mấu chốt là bạn đừng dùng http.DefaultClient mặc định mà không đặt thời gian chờ (timeout), nếu không goroutine sẽ bị treo vô hạn khi phía server bị kẹt.

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))
}

Bạn hãy đọc hết response body bằng io.ReadAll rồi mới tiến hành phân tích. Nếu cần xử lý cấu trúc, bạn định nghĩa struct tương ứng rồi dùng encoding/json để deserialize; các trường dữ liệu bao gồm choices, message, content, usage.

PHP: curl

PHP dùng extension curl, bạn nhớ thêm JSON_UNESCAPED_UNICODE khi gọi json_encode, nếu không nội dung tiếng Trung sẽ bị chuyển thành \uXXXX. Dù vẫn hoạt động được nhưng sẽ rất khó đọc khi debug.

<?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";

Bạn cần phân biệt hai loại lỗi: curl_exec trả về false là lỗi tầng mạng; nếu trả về nội dung nhưng mã trạng thái không phải 200 là lỗi tầng API, bạn cần đọc error.code.

Những lỗi thường gặp khi gọi lần đầu

  • 401: Header đã được viết là Authorization: khóa API, thiếu tiền tố Bearer ; hoặc biến môi trường chưa có hiệu lực trong terminal mới được mở.
  • 404: Đường dẫn thiếu /v1, hoặc bạn đã đánh sai chat/completions.
  • 400: JSON không hợp lệ, hoặc prompt cộng max_tokens vượt quá giới hạn 100,000 token.
  • 402: Hết số dư hoặc hết thời hạn dùng thử.
  • Nội dung bị cắt ngắn: max_tokens mặc định là 2048, tối đa một lần gọi là 16,000; bạn cần tăng giá trị này rõ ràng khi viết văn bản dài.
  • Muốn dùng streaming: Bạn thêm "stream": true vào request body. Phản hồi sẽ trả về dạng SSE và cuối cùng sẽ tự động thêm một khối dữ liệu chứa thông tin usage.

Sau khi chạy thành công, bước tiếp theo bạn nên xem Cách viết prompt để cải thiện chất lượng đầu ra; nếu gặp lỗi, hãy tra Sổ tay xử lý lỗi và mã lỗi. Tài liệu đầy đủ về tham số có tại Tài liệu, giá cả xem tại Trang giá cả.

Sau khi chạy thành công, trước khi đưa lên production bạn cần bổ sung ba thứ sau

Các ví dụ trong hướng dẫn chỉ là phiên bản tối thiểu để chạy được; khi đưa vào dịch vụ thực tế, bạn ít nhất cần bổ sung ba mục này.

  1. Thời gian chờ. Ví dụ đặt 120 giây vì sinh văn bản dài chậm. Nếu chờ đồng bộ, hãy giảm thời gian chờ và dùng streaming để người dùng thấy kết quả ngay.
  2. Phân loại lỗi. Các mã 401, 402, 403 là lỗi mà thử lại cũng vô hiệu, bạn cần báo động hoặc thông báo cho người dùng; chỉ có 429 và 503 mới đáng để thử lại với cơ chế backoff. Cách triển khai cụ thể đã có trong sổ tay xử lý lỗi, không trình bày ở đây.
  3. Theo dõi lượng dùng. Mỗi lần phản hồi, bạn hãy ghi log usage, chỉ ghi số liệu, không ghi nội dung của người dùng vào log. Đây là cơ sở để đối chiếu cuối tháng và kiểm tra các mức tiêu thụ bất thường.

Nhắc lại một chút về quản lý khóa: bạn chỉ có một khóa duy nhất, nếu bị lộ thì chỉ có thể tạo lại khóa mới, và việc tạo lại sẽ khiến tất cả các dịch vụ đang sử dụng khóa cũ bị ngắt kết nối đồng thời. Vì vậy, bạn đừng rải khóa này vào nhiều script hay cấu hình trên nhiều máy; hãy tập trung nó vào một nơi quản lý khóa duy nhất để khi thay đổi sẽ không bị sót.

Cuối cùng là giới hạn nội dung: các nội dung người lớn hợp pháp, tiểu thuyết hư cấu và các chủ đề gây tranh cãi sẽ không bị từ chối, nhưng nội dung liên quan đến tình dục của trẻ em sẽ bị chặn hoàn toàn và trả về mã 403, kể cả trong bối cảnh hư cấu hay nhập vai. Nếu ứng dụng của bạn hướng đến người dùng trưởng thành, bạn nên thêm bước xác nhận độ tuổi trong quy trình đăng ký của mình.

Cuối cùng, đây là thứ tự tự kiểm tra, bạn có thể dán nó bên cạnh màn hình: khóa có trong biến môi trường chưa; models có hoạt động không; request body có phải JSON hợp lệ không; model có phải uncensored không; max_tokens có đủ lớn không; finish_reason trong phản hồi là stop hay length; usage đã được ghi log chưa. Nếu cả bảy mục đều xanh, việc tích hợp của bạn được coi là hoàn tất.

Câu hỏi thường gặp

Có bắt buộc phải dùng SDK chính thức để gọi API không?

Không cần. Đây chỉ là yêu cầu HTTPS POST chuẩn kèm JSON, ngôn ngữ nào có thể gửi yêu cầu HTTP đều dùng được, SDK chỉ gói gọn một lớp tiện ích cho bạn.

Trường model nên điền giá trị gì?

Bạn điền cố định là uncensored. Hiện tại chỉ có một mô hình duy nhất này, bạn có thể xác nhận bằng lệnh GET /v1/models.

Sẽ xảy ra gì khi hết số dư dùng thử?

Yêu cầu sẽ trả về mã 402 với lỗi no_credit. Bạn chỉ cần nạp thêm số dư trả trước là có thể tiếp tục sử dụng. Số dư này không bao giờ hết hạn và không có gói đăng ký.

Việc tạo lại khóa có ảnh hưởng đến khóa cũ không?

Có. Khóa cũ sẽ mất hiệu lực ngay lập tức, vì vậy bạn phải thay khóa mới trong dịch vụ trước khi nhấn tạo lại, hoặc chấp nhận một khoảng thời gian gián đoạn ngắn.

Chỉ cần điền biểu mẫu để lấy khóa

Tạo tài khoản, sao chép khóa, sửa Base URL. Cấu hình rất đơn giản như vậy.