API reference
TransTok serves GPT, Claude and Gemini through one endpoint that speaks the OpenAI Chat Completions format. Point any OpenAI SDK at it and change nothing else.
Getting started
- Sign up in the dashboard. You get your first API key (
tt_…) right away; create or revoke more in the Account tab. - Top up your balance in the Wallet tab.
- Set your OpenAI SDK's
base_urltohttps://transtok.pairful.ai/v1.
from openai import OpenAI
client = OpenAI(base_url="https://transtok.pairful.ai/v1", api_key="tt_…")
res = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
print(res.choices[0].message.content)
import OpenAI from 'openai'
const client = new OpenAI({ baseURL: 'https://transtok.pairful.ai/v1', apiKey: 'tt_…' })
const res = await client.chat.completions.create({
model: 'claude-sonnet-5-5',
messages: [{ role: 'user', content: 'Hello' }],
})
console.log(res.choices[0].message.content)
curl https://transtok.pairful.ai/v1/chat/completions \
-H "Authorization: Bearer tt_…" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-2.5-flash", "messages": [{"role": "user", "content": "Hello"}]}'
Authentication
Send your key as Authorization: Bearer tt_…. API keys work for the /v1 proxy, reading your account,
and managing listings. Actions that move money out or change credentials — withdrawals, refunds, creating or revoking keys,
changing your password — only work from a signed-in dashboard session, so a leaked key can never cash out or lock you out.
Models & pricing
List prices are each provider's official rates in USD per 1M tokens. You pay list price minus the discount of whichever seller
fills your request. Models with no supply right now return 503 no_capacity.
| Model | Provider | Input | Output | Cached input | Best discount now |
|---|---|---|---|---|---|
| Loading… | |||||
Gemini Pro models switch to long-context rates for the whole request once the prompt exceeds 200k tokens. Claude cache-write tokens are billed at the cache-write rate.
Limit orders
Send a minimum discount (percent) in the X-TT-Min-Discount header and supply below that discount is never used.
If nothing qualifies you get 503 no_capacity and are not charged.
client.chat.completions.create(
model="gpt-4o",
messages=[...],
extra_headers={"X-TT-Min-Discount": "25"}, # only fill at 25% off or better
)
Response headers
| Header | Meaning |
|---|---|
x-tt-discount | Discount applied to this request, in percent. |
x-tt-cost-usd | Amount charged for this request, in USD. Not sent on streaming responses — see your usage history instead. |
x-tt-attempts | How many sellers were tried. If a seller's key fails, the request moves to the next one automatically. |
Streaming
stream: true works as usual. To bill accurately the server turns on stream_options.include_usage,
so you may receive one extra final chunk carrying only usage (choices: []). If you disconnect early, you're charged
for what was generated up to that point.
Claude
Use a claude-… model name; the server translates the request to the Anthropic Messages API and the response back.
| OpenAI request | Becomes |
|---|---|
system / developer messages | System prompt |
tools, tool_choice, tool_calls, tool messages | Tool definitions, calls and results |
image_url (data URL or http URL) | Image blocks |
max_tokens / max_completion_tokens | Max output (default 16,000; 64,000 when streaming) |
stop | Stop sequences |
reasoning_effort | Effort setting |
temperature, top_p | Ignored (current Claude models don't accept them) |
Gemini
Requests pass straight through Google's OpenAI-compatible API. Model names prefixed with models/ are accepted.
Thinking tokens are billed at the output rate.
Errors
Errors use the OpenAI shape: {"error": {"message", "type", "code"}}. Problems with a seller's key are retried on other
supply automatically, so the errors you see are almost always one of these:
| Status | code | Meaning · what to do |
|---|---|---|
| 400 | invalid_request | Malformed request. Requests the provider rejects are passed through as-is (not charged). |
| 400 | model_not_supported | Model isn't on the price list. |
| 400 | content_policy_violation | Blocked as a policy violation. Repeated violations suspend the account. |
| 401 | invalid_api_key | Missing or revoked key. |
| 402 | insufficient_balance | Balance too low — top up. |
| 403 | account_suspended | The account is suspended. |
| 403 | session_required | Withdrawals, refunds and key management need a signed-in dashboard session, not an API key. |
| 413 | request_too_large | Request body over 20 MB. |
| 429 | rate_limited | Per-minute request limit reached — retry shortly. |
| 429 | daily_limit | Daily spend limit for unverified accounts reached. |
| 503 | no_capacity | No supply matches (not charged). Retry later or lower your minimum discount. |
Limits
- Requests: 60 per minute per account (default).
- Unverified accounts have a daily spend limit, shown in the dashboard's Wallet tab.
- Request body: 20 MB.
Seller guide
1. Prepare a key to sell
In your provider console, create a dedicated project (or workspace) for selling and issue the key there. Set its spend limit to match what you list, so the key you sell never shares a balance with your own usage. Keys are checked when you list them and stored encrypted.
2. Set your price
Quote a discount between 15% and 70% in 0.5% steps. Buyers see your discount minus 10 points. Higher discounts fill first; at equal discounts, the listing that expires sooner fills first. Your listings show their queue position and the discount you'd need to be first in line.
3. Auto-ramp
Set a maximum discount and your price rises toward it over the final 7 days before expiry, so credits that would otherwise go to waste sell first.
4. Prove ownership
Verify once with an org admin key — sk-admin-… for OpenAI, sk-ant-admin… for Anthropic — and your earnings
hold drops from 14 to 3 days and listing limits lift. The admin key is used once to find your listed
key in your organization's key list and is never stored; you can delete it afterwards. Gemini keys can't be verified yet.
5. Earnings & withdrawals
Earnings become withdrawable after the hold period. Withdrawals require identity verification and can only be requested from a signed-in dashboard (not with an API key). Topped-up balance can't be withdrawn — unused top-ups are refunded to the card they came from.
API keys & security
- API keys call
/v1, read your account and manage listings. They cannot withdraw, refund, create keys or change your password — those require a signed-in dashboard session. - If a key leaks, revoke it in the Account tab. Other keys keep working.
- Prompts and responses are not stored. Requests do reach the provider through a seller's key, so don't send sensitive data.