Quick Start

paypertoken gives you OpenAI-compatible LLM access paid with USDC micropayments. No signup, no API keys.

  1. Install a tempo-compatible client
  2. Open a payment session against paypertoken.dev
  3. Send requests — pay per token as you stream
curl https://paypertoken.dev/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

This requires an active tempo session. See Payment below.

Payment

paypertoken uses the mppx / tempo protocol instead of API keys. Here's the flow:

  1. Client opens a tempo session → server returns session ID
  2. Client deposits USDC → server acknowledges
  3. Client sends requests with voucher headers → tokens deducted per SSE event
  4. Client closes session → unused USDC returned

Any mppx-compatible client handles this automatically. You just point it at paypertoken.dev and send requests.

Payments use USDC on Base. Testnet mode available via the TEMPO_TESTNET flag.

Endpoints

GET /health

Health check endpoint.

{ "status": "ok" }

GET /v1/models

Returns all available models with pricing. No payment required.

{
  "object": "list",
  "data": [
    {
      "id": "gpt-4o-mini",
      "object": "model",
      "owned_by": "openai",
      "pricing": { "input_per_1m": 0.15, "output_per_1m": 0.6, "currency": "USD" }
    }
  ]
}

POST /v1/chat/completions

Create a chat completion. Requires an active tempo session (returns 402 if missing).

FieldTypeRequiredDescription
modelstringYesModel ID (see Models & Pricing)
messagesarrayYesArray of {role, content} objects
temperaturenumberNoSampling temperature (0–2)
max_tokensnumberNoMax output tokens (default 4096)
top_pnumberNoNucleus sampling
frequency_penaltynumberNoFrequency penalty (−2 to 2)
presence_penaltynumberNoPresence penalty (−2 to 2)
stopstring | string[]NoStop sequences
toolsarrayNoTool/function definitions
tool_choicestring | objectNoTool selection strategy
nnumberNoNumber of completions

stream is always forced to true with include_usage: true. Response is an SSE stream of OpenAI-compatible chunks.

POST /v1/chat/completions (no body)

Management operations. Send a POST with no body for session open/close/voucher handling. The tempo protocol headers control the operation.

Models & Pricing

All prices include a 10% service fee over upstream provider costs. The cheapest available provider is auto-selected per model.

ModelInput / 1M tokensOutput / 1M tokens
gpt-4o-mini$0.165$0.660
google/gemini-2.5-flash$0.165$0.660
meta-llama/llama-4-maverick$0.220$0.660
anthropic/claude-haiku-4$0.880$4.40
o3-mini$1.21$4.84
gpt-4o$2.75$11.00
google/gemini-2.5-pro$1.38$11.00
anthropic/claude-sonnet-4$3.30$16.50

Code Examples

curl

# Open a tempo session first, then:
curl https://paypertoken.dev/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Python

from openai import OpenAI

client = OpenAI(
    base_url="https://paypertoken.dev/v1",
    api_key="unused",  # auth via tempo session
)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)

TypeScript

import OpenAI from 'openai'

const client = new OpenAI({
  baseURL: 'https://paypertoken.dev/v1',
  apiKey: 'unused', // auth via tempo session
})

const completion = await client.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: 'Hello!' }],
})
console.log(completion.choices[0].message.content)

Errors

All errors return JSON with an error object containing message and type fields.

StatusTypeDescription
400invalid_request_errorInvalid JSON or schema validation failure
402payment_error / budget_exceededNo tempo session or budget exceeded
404invalid_request_errorModel not found
413invalid_request_errorRequest body exceeds 1MB
429upstream_errorUpstream provider rate limited
500server_errorInternal server error
502upstream_errorUpstream provider unavailable