Skip to main content

REST API

The Chucky service provides a REST endpoint for one-shot prompts. This is useful when you don’t need a persistent WebSocket session.
For multi-turn conversations or streaming with tools, use the WebSocket API instead.

Endpoint

POST https://conjure.chucky.cloud/prompt

Request

Headers

HeaderRequiredDescription
Content-TypeYesMust be application/json
AcceptNoResponse format: text/event-stream for SSE, application/json for JSON (default)

Body

{
  "message": "What is the capital of France?",
  "options": {
    "token": "your-jwt-token",
    "model": "claude-sonnet-4-5-20250929",
    "systemPrompt": "You are a helpful assistant.",
    "maxTurns": 5
  }
}

Options

FieldTypeRequiredDescription
tokenstringYesJWT authentication token
modelstringNoClaude model (default: claude-sonnet-4-5-20250929)
systemPromptstringNoSystem prompt for Claude
toolsarrayNoTool definitions
allowedToolsstring[]NoWhitelist of allowed tools
disallowedToolsstring[]NoBlacklist of blocked tools
maxTurnsnumberNoMaximum conversation turns
maxBudgetUsdnumberNoMax cost for this request
maxThinkingTokensnumberNoMax tokens for extended thinking
outputFormatobjectNoStructured output schema
mcpServersobjectNoMCP server configurations

Response Formats

JSON Response (Default)

When Accept: application/json or no Accept header:
{
  "result": {
    "type": "result",
    "subtype": "success",
    "text": "The capital of France is Paris.",
    "total_cost_usd": 0.0012,
    "duration_secs": 1.5,
    "usage": {
      "input_tokens": 50,
      "output_tokens": 20
    }
  },
  "messages": [
    {
      "type": "assistant",
      "subtype": "text",
      "text": "The capital of France is Paris."
    },
    {
      "type": "result",
      "subtype": "success",
      "text": "The capital of France is Paris.",
      "total_cost_usd": 0.0012
    }
  ],
  "sessionId": "550e8400-e29b-41d4-a716-446655440000"
}

SSE Response (Streaming)

When Accept: text/event-stream:
event: message
data: {"type":"assistant","subtype":"text","text":"The capital of "}

event: message
data: {"type":"assistant","subtype":"text","text":"France is Paris."}

event: message
data: {"type":"result","subtype":"success","text":"The capital of France is Paris.","total_cost_usd":0.0012}

event: done
data: {"sessionId":"550e8400-e29b-41d4-a716-446655440000"}

Error Responses

Authentication Errors

{
  "error": "Token expired"
}
Status: 401 Unauthorized

Budget Exceeded

{
  "error": "user_budget_exhausted",
  "ai": {
    "used": 1000000,
    "remaining": 0,
    "budget": 1000000
  },
  "compute": {
    "used": 3600,
    "remaining": 0,
    "budget": 3600
  }
}
Status: 429 Too Many Requests

Concurrency Limit

{
  "error": "concurrent_limit_reached",
  "active": 5,
  "max": 5,
  "sessions": [
    { "sessionId": "abc123", "userId": "user1", "ageMs": 45000 }
  ]
}
Status: 429 Too Many Requests

Developer Budget Exceeded

{
  "error": "developer_budget_exhausted",
  "used": 500000,
  "available": 0,
  "planSeconds": 500000,
  "poolSeconds": 0
}
Status: 402 Payment Required

Examples

cURL - JSON Response

curl -X POST https://conjure.chucky.cloud/prompt \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "message": "What is 2 + 2?",
    "options": {
      "token": "your-jwt-token"
    }
  }'

cURL - SSE Streaming

curl -X POST https://conjure.chucky.cloud/prompt \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "message": "Write a haiku about coding",
    "options": {
      "token": "your-jwt-token",
      "model": "claude-sonnet-4-5-20250929"
    }
  }'

JavaScript - Fetch with JSON

const response = await fetch('https://conjure.chucky.cloud/prompt', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  },
  body: JSON.stringify({
    message: 'Explain quantum computing briefly',
    options: {
      token: 'your-jwt-token',
      model: 'claude-sonnet-4-5-20250929',
    },
  }),
});

const data = await response.json();
console.log(data.result.text);

JavaScript - SSE Streaming

const response = await fetch('https://conjure.chucky.cloud/prompt', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'text/event-stream',
  },
  body: JSON.stringify({
    message: 'Write a short story',
    options: { token: 'your-jwt-token' },
  }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const chunk = decoder.decode(value);
  const lines = chunk.split('\n');

  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const data = JSON.parse(line.slice(6));
      if (data.type === 'assistant' && data.subtype === 'text') {
        process.stdout.write(data.text);
      }
    }
  }
}

Python - Requests

import requests

response = requests.post(
    'https://conjure.chucky.cloud/prompt',
    headers={
        'Content-Type': 'application/json',
        'Accept': 'application/json',
    },
    json={
        'message': 'What is the meaning of life?',
        'options': {
            'token': 'your-jwt-token',
        },
    },
)

data = response.json()
print(data['result']['text'])

Usage API

Check current token usage against budget limits.

Endpoint

GET https://conjure.chucky.cloud/usage

Request

Headers

HeaderRequiredDescription
AuthorizationYesBearer token: Bearer your-jwt-token

Response

{
  "user_id": "demo-user",
  "issuer_id": "jd77az049xjwsv0pbjqbrkfjws7z5136",
  "window": "day",
  "window_start": "2026-01-14T00:00:00.000Z",
  "allowed": true,
  "ai": {
    "used": 150000,
    "remaining": 4850000,
    "budget": 5000000
  },
  "compute": {
    "used": 84,
    "remaining": 359916,
    "budget": 360000
  }
}

Response Fields

FieldTypeDescription
user_idstringUser ID from token (sub claim)
issuer_idstringProject ID from token (iss claim)
windowstringBudget window: hour, day, week, month, or lifetime
window_startstringISO timestamp when current window started
allowedbooleanWhether the user can continue (within budget)
ai.usednumberAI cost used in microdollars
ai.remainingnumberAI cost remaining in microdollars
ai.budgetnumberTotal AI budget in microdollars
compute.usednumberCompute time used in seconds
compute.remainingnumberCompute time remaining in seconds
compute.budgetnumberTotal compute budget in seconds
AI cost is tracked in microdollars (1 USD = 1,000,000 microdollars). Compute time is tracked in seconds.

Examples

cURL

curl -H "Authorization: Bearer your-jwt-token" \
  https://conjure.chucky.cloud/usage

JavaScript

const response = await fetch('https://conjure.chucky.cloud/usage', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

const usage = await response.json();

// Check remaining budget
console.log(`AI remaining: $${usage.ai.remaining / 1_000_000}`);
console.log(`Compute remaining: ${usage.compute.remaining}s`);

if (!usage.allowed) {
  console.log('Budget exhausted!');
}

Python

import requests

response = requests.get(
    'https://conjure.chucky.cloud/usage',
    headers={'Authorization': f'Bearer {token}'}
)

usage = response.json()
print(f"AI remaining: ${usage['ai']['remaining'] / 1_000_000:.2f}")
print(f"Compute remaining: {usage['compute']['remaining']}s")

Comparison: REST vs WebSocket

FeatureREST /promptWebSocket /ws
Multi-turn conversationsNoYes
Session persistenceNoYes
StreamingSSE onlyFull duplex
Client-side toolsLimitedFull support
Best forSimple one-shot queriesInteractive apps