fishtoken Sign up
GuidePythonNode.js

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.

Python
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 was
Node.js
import 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 was

Zero-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.

Terminal
# 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.

Python
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)
Node.js
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.

Python (requests)
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_ID
Node.js (fetch)
const 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_ID

Example 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 as Authorization: Bearer ..., and that the base URL is https://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 model value must match a FishToken model ID exactly, for example deepseek-v4-flash or wan2.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) or baseURL (Node.js) is spelled as the SDK expects, or that OPENAI_BASE_URL is 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.