Checklist voor aanvang
Loop dit eerst na, zodat je niet halverwege hoeft terug te keren.
- Een e-mailadres waarop je berichten kunt ontvangen, voor registratie.
- Je hebt lokaal een van de volgende omgevingen: Python 3, JDK 15 of hoger (voor tekstblokken in de voorbeelden), Go, of PHP met de curl-extensie.
- Je bent 18 jaar of ouder; de dienst is alleen voor volwassenen.
- Je wilt een puur tekstgesprek: er is slechts één model, geen vectoren, afbeeldingen, spraak of fine-tuning.
- Bewaar je sleutel in een omgevingsvariabele, niet in de broncode, en commit deze zeker niet naar de repository.
De interface-eisen zijn minimaal: de endpoint is https://api.wushenchaapi.com/v1 en de indeling is compatibel met OpenAI's chat completion. Je kunt de meeste van je bestaande verzoeklichamen dus gewoon overnemen.
Geschatte tijd: registratie duurt één minuut, de omgeving installeren hangt af van je systeem. Het eerste verzoek zelf duurt niet langer dan dertig seconden. Als het langer duurt, zijn er waarschijnlijk netwerk- of sleutelproblemen; ga dan direct naar de foutopsporingslijst onderaan de pagina. Volg deze volgorde: eerst models, dan chat; eerst synchroon, dan streaming. Bevestig elke stap voordat je doorgaat.
Registreren en key krijgen
Ga naar /get-api-key/ en registreer je met e-mail en wachtwoord. Je sleutel wordt direct na registratie weergegeven; kopieer deze. Let op de volgende details:
- Elk account heeft slechts één key.
- Je kunt een nieuwe genereren, maar de oude vervalt direct. Zorg dat je de nieuwe waarde hebt gedeployed voordat je hem in productie gebruikt.
- Nieuwe accounts krijgen $0,50 proeftegoed, geldig voor 7 dagen. Geen betalingsgegevens nodig.
- Als de proefperiode eindigt of het tegoed op is, retourneert het verzoek 402 met foutcode
no_credit. Laad je prepaid tegoed op om door te gaan. Het is geen abonnement en het tegoed verloopt niet.
Zet je key in een omgevingsvariabele: macOS/Linux voer uit export API_KEY=je_sleutel, Windows PowerShell: $env:API_KEY="je_sleutel". Alle voorbeelden lezen uit API_KEY.
Stap één: controleer verbinding met /v1/models
Stuur niet direct een gesprek. Doe eerst een verzoek met nul tokenkosten (GET) om te controleren of adres, netwerk en sleutel correct zijn:
curl https://api.wushenchaapi.com/v1/models \
-H "Authorization: Bearer $API_KEY"Een 200-antwoord met de modellenlijst (alleen uncensored) betekent dat het werkt. 401 betekent een verkeerde of ontbrekende key; time-outs duiden op netwerk- of proxyproblemen. Verbinding en verzoeklichaam apart controleren bespaart tijd tijdens de integratie.
Python: requests
Geen SDK nodig, één requests.post is genoeg. Let op drie dingen: stel timeout in; controleer eerst r.ok voordat je choices leest; bij een fout is de response {"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"])Bij succes zie je in usage prompt_tokens en completion_tokens. Log deze tijdens de ontwikkeling om je kosten te bewaken.
Verzoeklichaam veld voor veld
Alle vier de talen sturen dezelfde JSON. Begrijp deze eerst; voor elke taal is het slechts vertalen.
| Veld | Verplicht | Beschrijving |
|---|---|---|
| model | Ja | Standaard ingesteld op uncensored. |
| messages | Ja | Een array met items die een role en content bevatten. role kan system, user of assistant zijn. |
| max_tokens | Nee | Standaard 2048, maximum per verzoek 16.000. Verhoog dit zelf voor lange teksten. |
| temperature / top_p / stop | Nee | Standaard samplingparameters, worden doorgegeven zoals ze zijn. |
| stream | Nee | Als true, dan wordt er gebruikgemaakt van SSE-streaming. |
De drie velden die je in het antwoord het vaakst leest zijn: choices[0].message.content is de inhoud, choices[0].finish_reason vertelt of het normaal is afgesloten of door de lengte is afgekapt, en usage is het token-gebruik voor dit verzoek. Lees alle drie om de integratie volledig te begrijpen.
Onthoud ook twee harde limieten: het verzoeklichaam mag niet groter zijn dan 8 MB en per sleutel zijn er maximaal 300 verzoeken per minuut. Voer batchtaken niet massaal parallel uit; stel eerst een eenvoudige limiet voor gelijktijdige verzoeken in.
Java: java.net.http
Sinds JDK 11 zit HttpClient er standaard bij, dus je hebt geen extra afhankelijkheden nodig. In het voorbeeld gebruiken we tekstblokken van JDK 15 voor JSON; bij oudere versies kun je dit aanpassen naar stringconcatenatie of een JSON-bibliotheek gebruiken om te serialiseren.
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());
}
}Tip: als de inhoud Chinese tekens bevat, codeert BodyPublishers.ofString standaard UTF-8, dus je hoeft niets extraats te doen. Gebruik in productieomgevingen HttpClient als singleton om te hergebruiken en maak geen nieuwe instantie aan voor elk verzoek.
Go: net/http
De standaardbibliotheek van Go is ook voldoende. Het belangrijkste is dat je geen standaard http.DefaultClient zonder timeout gebruikt, anders blijven goroutines hangen als de server vastloopt.
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))
}Lees de response body volledig uit met io.ReadAll voordat je hem parset. Voor gestructureerde verwerking definieer je de bijbehorende struct en deserialiseer je deze met encoding/json. De velden zijn choices, message, content en usage.
PHP: curl
PHP gebruikt de curl-extensie. Vergeet niet JSON_UNESCAPED_UNICODE toe te voegen aan json_encode, anders wordt Chinees omgezet naar \uXXXX. Dat werkt wel, maar is lastig te lezen tijdens het debuggen.
<?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";Maak onderscheid tussen twee soorten fouten: als curl_exec false retourneert, is het een netwerkfout; als er wel inhoud wordt geretourneerd maar de statuscode niet 200 is, is het een API-fout en moet je error.code lezen.
Veelgemaakte fouten bij de eerste call
- 401: De header was geschreven als
Authorization: sleutel, maar deBearervoorvoegsel ontbrak; of de omgevingsvariabele was niet actief in het nieuw geopende terminalvenster. - 404: Het pad mist de
/v1, ofchat/completionsis verkeerd gespeld. - 400: Ongeldige JSON, of de som van prompt en max_tokens overschrijdt de limiet van 100.000 tokens.
- 402: Saldo is op of de proefperiode is verlopen.
- Uitvoer afgekapt:
max_tokensis standaard 2048, maximaal 16.000 per verzoek. Voor lange teksten moet je dit expliciet verhogen. - Streaming willen: voeg
"stream": truetoe aan de request body. De response is SSE en aan het einde wordt automatisch een data-blok met usage toegevoegd.
Nadat het werkt, bekijk Prompt-schrijfwijze om de outputkwaliteit te controleren. Bij fouten raadpleeg Foutcodes en foutopsporing. De volledige parameterbeschrijving staat in Documentatie, prijzen zie Prijzen.
Als het werkt, voeg dan voor de productiegang deze drie dingen toe
De voorbeelden in de tutorial zijn de minimale werkende versie. Als je het echt in een service wilt gebruiken, voeg dan minstens deze drie dingen toe.
- Time-out. In het voorbeeld is 120 seconden gekozen omdat het genereren van lange tekst langzaam kan zijn. Als je zakelijke toepassing synchroon wacht, pas dan de tolerantietijd aan op de pagina aan en combineer dit met streaming output, zodat de gebruiker de tekst al te zien krijgt.
- Foutdoorstroom. 401, 402 en 403 zijn fouten waarbij herhalen niet helpt; alarmeer of waarschuw de gebruiker. Alleen 429 en 503 zijn waard om back-off en opnieuw proberen uit te voeren. De specifieke implementatie staat in de foutopsporingshandleiding, hier niet uitgewerkt.
- Verbruiksregistratie. Log bij elk antwoord de usage-waarde als één regel; noteer alleen de cijfers en schrijf de gebruikersinhoud niet in de logs. Dit is essentieel voor de maandafrekening en het opsporen van abnormaal verbruik.
Een woordje over sleutelbeheer: je hebt maar één sleutel. Als deze lekraakt, moet je een nieuwe genereren. Het opnieuw genereren maakt alle actieve services onmiddellijk offline. Verspreid de sleutel dus niet over meerdere scripts of machines; sla hem centraal op voor eenvoudig wisselen zonder dat je iets mist.
Tot slot de inhoudsgrenzen: legaal volwassen materiaal, fictie en controversiële onderwerpen worden niet afgewezen. Seksuele inhoud met minderjarigen wordt echter altijd geblokkeerd met 403, ook in fictie en roleplay. Als je applicatie zich richt op volwassenen, voeg dan een leeftijdverificatie toe in je eigen registratieproces.
Hier is een zelfcontrole-lijst, die je ook naast je monitor kunt plakken: staat de sleutel in de omgevingsvariabelen? Werken models? Is de verzoeklichaam geldige JSON? Is het model ongecensureerd? Is max_tokens voldoende? Is finish_reason in het antwoord 'stop' of 'length'? Is usage geregistreerd? Als alle zeven punten groen zijn, is de integratie voltooid.