Switch an existing OpenAI SDK project to FishToken in two lines
FishToken is OpenAI-compatible. If your project already uses the OpenAI SDK, you change the base URL and the API key and keep the rest. This guide shows both lines in Python and Node.js, an environment-variable version that changes no code at all, and what to do when a request fails.
The two lines
Create a key at fishtoken.ai/console/token and store it as FISHTOKEN_API_KEY. Then change the client constructor.
from openai import OpenAI
client = OpenAI(
base_url="https://fishtoken.ai/v1", # line 1: was the SDK default
api_key=os.environ["FISHTOKEN_API_KEY"], # line 2: your FishToken key
)
# everything below this line stays as it wasimport OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://fishtoken.ai/v1", // line 1: was the SDK default
apiKey: process.env.FISHTOKEN_API_KEY, // line 2: your FishToken key
});
// everything below this line stays as it wasZero-code version: environment variables
If you would rather not touch the source, set the two variables the SDK already looks for. This is handy for switching a deployed service without a new build.
# The OpenAI SDKs for Python and Node.js read these two variables on startup.
# With them set, OpenAI() / new OpenAI() need no arguments and your code does not change at all.
export OPENAI_BASE_URL="https://fishtoken.ai/v1"
export OPENAI_API_KEY="your-fishtoken-key-here"Pick one approach. Arguments passed to the constructor win over environment variables. If both are set and point to different places, requests go where the constructor says.
Text: chat completions
After the switch, a normal chat call with deepseek-v4-flash looks like this. It is the same code as in the quickstart.
from openai import OpenAI
import os
client = OpenAI(
base_url="https://fishtoken.ai/v1",
api_key=os.environ["FISHTOKEN_API_KEY"],
)
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "user", "content": "Write a two-line caption for a handmade batik tote bag."}
],
)
print(resp.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://fishtoken.ai/v1",
apiKey: process.env.FISHTOKEN_API_KEY,
});
const resp = await client.chat.completions.create({
model: "deepseek-v4-flash",
messages: [
{ role: "user", content: "Write a two-line caption for a handmade batik tote bag." },
],
});
console.log(resp.choices[0].message.content);Video: the one endpoint the SDK does not cover
Video generation is POST https://fishtoken.ai/v1/video/generations. The OpenAI SDK has no method for it, so call it with a plain HTTP client and the same key. It returns a task ID; poll GET /v1/video/generations/TASK_ID until the video is ready.
import os
import requests
API = "https://fishtoken.ai/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['FISHTOKEN_API_KEY']}"}
task = requests.post(f"{API}/video/generations", headers=HEADERS, json={
"model": "doubao-seedance-2-0-fast-260128",
"prompt": "Vertical shot: a woven rattan handbag turning slowly on a sunlit wooden table, soft shadows",
}, timeout=60)
task.raise_for_status()
print(task.json()) # keep the task ID, then poll GET /v1/video/generations/TASK_IDconst API = "https://fishtoken.ai/v1";
const res = await fetch(`${API}/video/generations`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FISHTOKEN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "doubao-seedance-2-0-fast-260128",
prompt: "Vertical shot: a woven rattan handbag turning slowly on a sunlit wooden table, soft shadows",
}),
});
console.log(await res.json()); // keep the task ID, then poll GET /v1/video/generations/TASK_IDExample fields. The exact parameters each model accepts (duration, size, reference images and so on) and the response format are defined in the FishToken docs. Check them before you build on these examples.
Model IDs for the four video families are on the comparison page; a complete submit-and-poll script is in the Seedance Python example.
Troubleshooting
- 401 Unauthorized
- Wrong or missing key. Check that the key is a FishToken key from the console (not a key from another provider left in
OPENAI_API_KEY), that it is sent asAuthorization: Bearer ..., and that the base URL ishttps://fishtoken.ai/v1. - 429 Too Many Requests
- Rate limit. Standard accounts can send 60 requests per minute; accounts that have topped up can send 120. Wait a few seconds and retry with a short back-off; the SDK's built-in retries handle this for chat calls.
- Model not found
- The
modelvalue must match a FishToken model ID exactly, for exampledeepseek-v4-flashorwan2.7-t2v. The list is on the models page. - Balance or quota error
- FishToken is prepaid. Add balance on the top-up page and retry; the balance does not expire.
- Requests still go to the old provider
- The constructor argument was not applied: check that
base_url(Python) orbaseURL(Node.js) is spelled as the SDK expects, or thatOPENAI_BASE_URLis set in the process that actually runs the code. - Still stuck
- Email support@fishtoken.ai with the time of the request and the error message. Do not send your API key.
Make the switch
Create an account, add balance, create a key, change two lines.