Creator API keys

An OpenAI-compatible API key per creator per coin, paid from the coin’s AI vault.

The creator of an AI coin can get their own API key for that coin's AI and use it from any app, bot or script that speaks the OpenAI chat API. Requests are paid from the coin's AI vault in USDC, under the coin's rules, with the same receipts as every other request.

Keys work for every AI coin, whichever mode (Dark Room or Build) it launched with. Each creator has one active key per coin.

Get a key#

  1. Open the API key tab

    On your coin page, open the AI settings panel (visible only to the creator wallet) and choose the API key tab.
  2. Optional: label and spend limit

    A label of up to 60 characters, and a spend limit in USD (up to $10,000). With no limit only the coin's rules apply.
  3. Sign

    Your wallet signs a message (free, moves no funds). Each signature can change your keys only once.
  4. Copy it now

    The key starts with pp_live_ and is shown once. Only a hash of it is stored, so it cannot be shown again. Generating a new key stops the old one immediately; “Revoke key” stops it without a new one.

What a key can spend#

LimitValue
TierPremium: every model the coin’s rules allow, at any tier
Requests per dayNo daily request quota
Per requestThe coin’s max per request (default $0.25), what is left of the key’s spend limit and of today’s budget, and the platform hard cap
Per dayThe coin’s daily budget (default $20), shared with every other caller
Key spend limitOptional, set when you create the key
Rate60 requests per minute per key (the platform can change it)

While a request runs, its cap is reserved against the key's limit, so a burst of parallel requests cannot all pass the same check (per server process). What each request paid is added to the key's spend when it ends, including a stream you stopped halfway.

Endpoints#

The base URL is https://pairity.wtf/api/v1. Send the key as Authorization: Bearer pp_live_….

EndpointWhat it does
POST /api/v1/chat/completionsOpenAI-compatible chat, with or without streaming.
GET /api/v1/modelsThe models this key may use, with tier, context length, price per 1M tokens, tool support and which one is the default.
GET /api/v1/keyThe key’s limit, what it spent, what is left, and the AI vault’s USDC and address.

A request

bash
curl https://pairity.wtf/api/v1/chat/completions \
  -H "Authorization: Bearer pp_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-chat",
    "max_tokens": 300,
    "messages": [{ "role": "user", "content": "Write a gm for our holders" }]
  }'
Response (example)
{
  "id": "chatcmpl-pp1234",
  "object": "chat.completion",
  "created": 1760875200,
  "model": "deepseek/deepseek-chat",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "gm, tentacle fam…" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 14, "completion_tokens": 42, "total_tokens": 56 },
  "pairpad": {
    "request_id": 1234,
    "cost_usd": 0.001,
    "payment_sig": "5Kq…",
    "receipt_url": "https://pairity.wtf/verify?id=1234"
  }
}

The pairpad object is the only addition to the OpenAI format:

  • request_id: the request's number, used for its receipt.
  • cost_usd: what the AI vault paid for this request, in USD (USDC).
  • payment_sig: the Solana transaction of the USDC payment, when the provider returned one (otherwise null).
  • receipt_url: the public page that checks this request against the Merkle root on Solana. See Verify AI receipts.

Choosing a model

  • model must be one of GET /api/v1/models; any other id is refused with 400 model_not_found.
  • Leave it out to use the default: the coin's default model for the premium tier if the creator set one, else the coin's own paired model, else the cheapest allowed premium model.

Streaming

Add "stream": true to get Server-Sent Events in the OpenAI chunk format. The last chunk carries finish_reason, usage and the same pairpad object, then data: [DONE]. Refusals that happen before the first token (no funds, over the cap, bad model) come back as a normal HTTP error; an error after streaming started arrives as a chunk with an error object.

With an OpenAI SDK

ts
import OpenAI from 'openai'

const ai = new OpenAI({ apiKey: process.env.PAIRPAD_KEY, baseURL: 'https://pairity.wtf/api/v1' })
const r = await ai.chat.completions.create({
  messages: [{ role: 'user', content: 'Three facts about our coin, please' }],
  max_tokens: 300,
})
console.log(r.choices[0].message.content, (r as any).pairpad.receipt_url)

Check what is left

bash
curl -s https://pairity.wtf/api/v1/key -H "Authorization: Bearer pp_live_…"
Response (example)
{
  "data": {
    "coin": "<MINT>",
    "label": "My bot",
    "limit": 50,
    "usage": 1.234,
    "limit_remaining": 21.5,
    "vault_usdc": 21.5,
    "vault_address": "<the coin's AI vault>"
  }
}

limit_remaining is what the key may still spend, never more than the vault holds (here the vault has less than the key's $48.77 left). limit is null for a key without a spend limit. The vault figures can be up to about a minute old.

Format limits#

  • Text only: no images, audio or files. developer messages are treated as system messages.
  • Up to 500 messages and a 400,000-character body.
  • max_tokens (or max_completion_tokens) defaults to 1,024 and is capped at 4,096. A lower value is cheaper.
  • temperature from 0 to 2.
  • Up to 64 function tools are passed to the model; the model must support tools. Your app runs the tools.

Errors#

Errors use the OpenAI shape: {"error":{"message":"…","type":"…","code":"…"}}.

StatusType / codeWhy
401authentication_errorMissing, invalid or revoked key.
429rate_limit_errorMore than 60 requests per minute on this key.
402insufficient_quotaThe key reached its spend limit, the vault is out of USDC (no_funds), or the request would cost more than its cap (over_cap).
429insufficient_quotaThe coin used its daily budget. Resets at 00:00 UTC.
400invalid_request_errorBad body, a model that is not allowed (model_not_found), or a model that cannot use tools.
403permission_errorThe key no longer belongs to the coin’s creator.
503service_unavailable or invalid_request_errorAI turned off, the coin’s AI paused, or no model available right now.
502 / 503api_errorThe AI provider failed or was busy, or its payment terms were refused.

Keep the key secret

Anyone with the key can spend the coin's AI budget. If it leaks, generate a new one. Answers from the API go straight to your app: they do not pass through the filter that protects the coin page, so check what you show your users.