← Back to chat

CrypTok AI/SI API

Build with CrypTok's in-house AI/SI engine. OpenAI-compatible response shape, one model (Lumen) running on the team's own GPU server (rgb).

Base URL: https://cryptok.ai/api/v1Auth: Bearer API keyFormat: JSON or streaming text/plain

Quick start

Three steps to your first response:

  1. API keys come with AI/SI Pro or a Killer Whale membership on cryptok.me.
  2. Generate an API key at /upgrade — copy it once (shown only at creation).
  3. Hit the endpoint:
curl
curl https://cryptok.ai/api/v1/chat \
  -H "Authorization: Bearer cak_<keyId>.<secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "user", "content": "What is $CRYPTOK?"}
    ],
    "model": "cryptok-lumen"
  }'

Response is an OpenAI-style chat.completion object — drop it into existing tooling that expects that shape.

Authentication

Every request requires Authorization: Bearer cak_<keyId>.<secret> where the key was generated for an account with API access (AI/SI Pro or a Killer Whale membership). The secret half is hashed at rest (SHA-256), only the prefix is recoverable — store the full key in your env vars at creation time.

Key format

text
cak_<keyId16>.<secret32>

Example:
cak_a17c07022795d3a3.177a41a921924696175292845bbbdf35
└─┬─┘└──────┬───────┘└──────────────┬─────────────────┘
  prefix   public id (16 hex)        secret (32 hex)

Limits

POST /api/v1/chat

Send messages, get a response. Stateless — you manage conversation history client-side and pass the full messages array each request.

Request body

json
{
  "messages": [
    {"role": "system", "content": "(optional) Custom system prompt"},
    {"role": "user", "content": "What is $CRYPTOK?"},
    {"role": "assistant", "content": "(optional) Prior assistant turn"},
    {"role": "user", "content": "Tell me more about its tokenomics."}
  ],
  "model": "cryptok-lumen",
  "stream": false
}
FieldTypeRequiredDescription
messagesarrayyesConversation turns. Must include at least one role: "user". Roles: user, assistant, system.
modelstringnoOne of the 7 model ids below. Defaults to cryptok-lumen.
streambooleannoIf true, response is text/plain streaming of tokens as they generate. Default false = JSON.

Response (JSON mode)

json
{
  "id": "chatcmpl-s46v1rjzx6g",
  "object": "chat.completion",
  "created": 1780525913,
  "model": "cryptok-lumen",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "$CRYPTOK is the native Solana token..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_chars": 17,
    "completion_chars": 412,
    "credits_charged": 3,
    "source": "quota"
  },
  "knowledge": {
    "hits": 5,
    "top_score": 0.81
  }
}

The knowledge object reports how many sanitized snippets from CrypTok's internal knowledge base were retrieved and the top similarity score. usage.source is either "quota" (drawn from your daily allowance) or "credits" (drawn from your credit balance).

Models

There is one model: cryptok-lumen (Lumen), the same engine every CrypTok AI/SI user chats with. The model field is optional; older ids (cryptok-lumen-pro, -nova, -forge, -spark, -coder-mini, -comet, -pico) are still accepted and run on Lumen.

Model idContextBest for
cryptok-lumen32K tokensEverything — conversation, research, code, crypto and on-chain questions.

Streaming

Pass "stream": true in the request to receive tokens as a text/plain stream — same format as the cryptok.ai web UI uses. Time to first byte is typically ~200ms even on Lumen.

javascript
const res = await fetch('https://cryptok.ai/api/v1/chat', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer cak_<keyId>.<secret>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    messages: [{role: 'user', content: 'Explain Solana validators briefly.'}],
    model: 'cryptok-lumen',
    stream: true,
  }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  process.stdout.write(decoder.decode(value, {stream: true}));
}

Response headers (live quota tracking)

Every successful response includes headers so you can show live usage in your app without a separate quota call:

HeaderTypeExample
X-CrypTok-AI-Usedint1247 messages used today
X-CrypTok-AI-Capint5000 daily cap
X-CrypTok-AI-Creditsfloat247.5 credits in balance
X-CrypTok-AI-Costfloat3 credits this call cost
X-CrypTok-AI-Sourceenumquota or credits
X-Request-Idstringchatcmpl-s46v1rjzx6g

Errors

Errors are returned as JSON with an error object containing a code and message:

json
{
  "error": {
    "code": "rate_limited",
    "message": "Daily cap reached",
    "used": 5000,
    "cap": 5000,
    "credit_balance": 0
  }
}
CodeHTTPWhenHow to fix
invalid_api_key401Authorization header missing or key is malformed/revoked.Send Authorization: Bearer cak_<keyId>.<secret>. Verify the key on /upgrade.
tier_required403Your account doesn't include API access.API keys come with AI/SI Pro or a Killer Whale membership (cryptok.me/packages).
bad_request400Invalid JSON in request body.Ensure Content-Type: application/json and the body is valid JSON.
no_messages400messages[] is empty or has no user-role message.Include at least one {"role": "user", "content": "..."} entry.
rate_limited429Daily message limit reached.Wait for the rolling 24h refill, or move to AI/SI Pro (250 messages a day). The error body includes used/cap.
engine_error502Inference backend (rgb) returned an error or timed out.Retry with backoff. Persistent failure → contact support.

Rate limits

One model, one plan. Every call counts as one message against the key owner's daily limit — the same limits as the cryptok.ai chat.

AccountMessages / dayImages / dayAPI keys
Free CrypTok account253No
AI/SI Pro ($29/mo · $78/3 mo · $290/yr)25030✓ Yes
Degen membership (includes AI/SI Pro limits)25030No
Killer Whale membership (includes AI/SI Pro)25030✓ Yes

Limits refill on a rolling 24-hour window, not calendar-day midnight. When they run out you get a 429 rate_limited error until they refill.

SDK examples

Node.js / TypeScript

typescript
async function chat(message: string): Promise<string> {
  const res = await fetch('https://cryptok.ai/api/v1/chat', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CRYPTOK_AI_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      messages: [{role: 'user', content: message}],
      model: 'cryptok-lumen',
    }),
  });
  if (!res.ok) {
    const err = await res.json();
    throw new Error(`${err.error.code}: ${err.error.message}`);
  }
  const data = await res.json();
  return data.choices[0].message.content;
}

console.log(await chat('Whats the price of SOL?'));

Python

python
import os
import requests

def chat(message: str) -> str:
    res = requests.post(
        'https://cryptok.ai/api/v1/chat',
        headers={
            'Authorization': f'Bearer {os.environ["CRYPTOK_AI_KEY"]}',
            'Content-Type': 'application/json',
        },
        json={
            'messages': [{'role': 'user', 'content': message}],
            'model': 'cryptok-lumen',
        },
        timeout=120,
    )
    res.raise_for_status()
    data = res.json()
    return data['choices'][0]['message']['content']

print(chat('Whats the price of SOL?'))

OpenAI SDK (drop-in replacement)

The response shape is compatible with the OpenAI chat.completion object, so you can use the official OpenAI SDK by changing the baseURL:

typescript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.CRYPTOK_AI_KEY,
  baseURL: 'https://cryptok.ai/api/v1',
});

const completion = await client.chat.completions.create({
  model: 'cryptok-lumen',
  messages: [{role: 'user', content: 'Hello!'}],
});

console.log(completion.choices[0].message.content);

Note: OpenAI SDK quirks like tools array, function calls, response_format: json, and seed may behave differently or not be supported. Stick with the simple messages → choices path for guaranteed compatibility.