Use with Claude Code

Use PageGrid as your Claude Code backend. Same models, lower cost. Takes 30 seconds to set up.

Step 1: Get your API key

  1. Create an account at PageGrid
  2. Go to Dashboard → API Keys → Create New Key
  3. Copy your key (starts with sk-pgrid-)

Step 2: Set environment variables

Add these to your shell profile (~/.bashrc, ~/.zshrc, or ~/.profile):

bash
export ANTHROPIC_API_KEY="sk-pgrid-your-key-here"
export ANTHROPIC_BASE_URL="https://api.pagegrid.in/v1"

Then reload your shell:

bash
source ~/.zshrc  # or ~/.bashrc

Step 3: Use Claude Code normally

bash
claude

That's it. Claude Code will now route all requests through PageGrid. You can use all models:

bash
# Use Sonnet (default, fast)
claude

# Use Opus (most intelligent)
claude --model claude-opus-4-6

# Use Haiku (cheapest, fastest)
claude --model claude-haiku-4-5

Verify it works

Run this to confirm PageGrid is being used:

bash
echo $ANTHROPIC_BASE_URL
# Should output: https://api.pagegrid.in/v1

For Windows (PowerShell)

bash
$env:ANTHROPIC_API_KEY = "sk-pgrid-your-key-here"
$env:ANTHROPIC_BASE_URL = "https://api.pagegrid.in/v1"
claude

For Windows (CMD)

bash
set ANTHROPIC_API_KEY=sk-pgrid-your-key-here
set ANTHROPIC_BASE_URL=https://api.pagegrid.in/v1
claude

Works with any Anthropic SDK

The same environment variables work with the Python and JavaScript SDKs too — any tool that uses the Anthropic API will automatically route through PageGrid.

python
# Python — no code changes needed
# Just set ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL env vars

from anthropic import Anthropic
client = Anthropic()  # reads from env automatically

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)
print(message.content[0].text)
javascript
// JavaScript — no code changes needed
// Just set ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL env vars

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic(); // reads from env automatically

const message = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello!" }]
});
console.log(message.content[0].text);

Troubleshooting

  • 401 error: Check your API key is correct and starts with sk-pgrid-
  • 402 error: Your wallet balance is $0. Add funds in the dashboard.
  • 404 error: The model isn't available. Check /v1/models for active models.
  • Connection error: Make sure ANTHROPIC_BASE_URL ends with /v1 (not /v1/messages)

Use with OpenClaw

Use PageGrid as the AI backend for OpenClaw — the open-source AI agent with 300K+ GitHub stars. Run Claude models through PageGrid at lower cost.

Option 1: Config file (recommended)

Edit ~/.openclaw/openclaw.json and add PageGrid as a provider:

json
{
  "models": {
    "providers": [
      {
        "name": "pagegrid",
        "api": "anthropic-messages",
        "baseUrl": "https://api.pagegrid.in",
        "apiKey": "sk-pgrid-your-key-here"
      }
    ]
  }
}

Important: Do NOT include /v1 in the baseUrl. OpenClaw appends /v1/messages automatically.

Option 2: Environment variables

bash
export ANTHROPIC_BASE_URL="https://api.pagegrid.in"
export ANTHROPIC_API_KEY="sk-pgrid-your-key-here"

Option 3: CLI onboarding

bash
openclaw onboard --non-interactive \
  --provider anthropic \
  --custom-base-url "https://api.pagegrid.in" \
  --api-key "sk-pgrid-your-key-here"

Choosing a model

Set the default model in your OpenClaw config or per-conversation:

json
{
  "models": {
    "default": "claude-sonnet-4-6",
    "providers": [
      {
        "name": "pagegrid",
        "api": "anthropic-messages",
        "baseUrl": "https://api.pagegrid.in",
        "apiKey": "sk-pgrid-your-key-here",
        "models": [
          "claude-opus-4-6",
          "claude-sonnet-4-6",
          "claude-haiku-4-5"
        ]
      }
    ]
  }
}

Supported features

  • Streaming: Full SSE streaming support for real-time responses
  • Tools: Function calling and tool use work natively
  • Vision: Image analysis via base64 content blocks
  • Extended thinking: Thinking blocks pass through correctly
  • Multi-turn: Conversation history maintained by OpenClaw

Verify it works

bash
# Start OpenClaw
openclaw

# In the chat, ask:
> What model are you using?

# It should respond with the model name from PageGrid

Troubleshooting

  • 404 errors: Make sure baseUrl is https://api.pagegrid.in without /v1
  • 401 errors: Check your API key starts with sk-pgrid-
  • 402 errors: Add funds to your PageGrid wallet
  • Model not found: Check available models at GET /v1/models

Getting Started

PageGrid provides fast, affordable access to Claude models including Opus, Sonnet, and Haiku. Get an API key, add funds, and start building.

Quick Start

  1. Login to your account (created by admin)
  2. Go to API Keys and create a new key
  3. Copy your key (shown only once!)
  4. Make your first API call
bash
curl -X POST https://api.pagegrid.in/v1/messages \
  -H "Content-Type: application/json" \
  -H "api-key: sk-pgrid-your-key-here" \
  -d '{
    "model": "claude-opus-4-6",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "What is the capital of France?"}
    ]
  }'

Response:

json
{
  "id": "msg_01XFDUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-4-6",
  "content": [
    {"type": "text", "text": "The capital of France is Paris."}
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 14,
    "output_tokens": 10
  }
}

Authentication

All API requests require an API key. You can send it in two ways:

Option 1: api-key header (recommended)

bash
curl -H "api-key: sk-pgrid-your-key-here" ...

Option 2: Authorization Bearer header

bash
curl -H "Authorization: Bearer sk-pgrid-your-key-here" ...

API Key Format

Keys start with sk-pgrid- followed by 64 hex characters:

text
sk-pgrid-65b03b3c7bcab0bb1e865676f971c29fb86e403ed89f91234ca747e1a19169d0

Key Management

  • Keys are shown once at creation. Store them securely.
  • Revoke compromised keys instantly from the dashboard.
  • Rotate to get a new key without losing your settings.
  • Set per-key rate limits and model restrictions.

Messages API

POST/v1/messages

Send messages and receive AI responses.

Request Body

ParameterTypeRequiredDescription
modelstringrequiredModel ID (e.g., "claude-opus-4-6")
messagesarrayrequiredArray of message objects with role and content
max_tokensintegerrequiredMaximum tokens to generate (1 to model max)
systemstringoptionalSystem prompt (top-level, not in messages)
temperaturenumberoptionalRandomness 0.0-1.0 (default: 1.0)
top_pnumberoptionalNucleus sampling threshold
top_kintegeroptionalTop-K sampling
stop_sequencesstring[]optionalCustom stop sequences
streambooleanoptionalEnable SSE streaming (default: false)
toolsarrayoptionalTool definitions for function calling
tool_choiceobjectoptionalauto, any, tool, or none
thinkingobjectoptional{type: "enabled"|"disabled"|"adaptive", budget_tokens?}
metadataobjectoptional{user_id} for tracking

Response Body

ParameterTypeRequiredDescription
idstringrequiredUnique message ID (e.g., "msg_...")
typestringrequiredAlways "message"
rolestringrequiredAlways "assistant"
modelstringrequiredModel that generated the response
contentarrayrequiredArray of content blocks (text, tool_use, thinking)
stop_reasonstringrequiredend_turn, max_tokens, stop_sequence, or tool_use
usageobjectrequired{input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens}

Message Object

json
{
  "role": "user",       // "user" or "assistant"
  "content": "Hello!"   // string or array of content blocks
}

Content Block Types

javascript
// Text
{"type": "text", "text": "Hello!"}

// Image (base64)
{"type": "image", "source": {"type": "base64", "data": "...", "media_type": "image/png"}}

// Tool use (in response)
{"type": "tool_use", "id": "toolu_...", "name": "get_weather", "input": {"city": "Paris"}}

// Tool result (in request)
{"type": "tool_result", "tool_use_id": "toolu_...", "content": "22 degrees"}

// Thinking (in response, when thinking enabled)
{"type": "thinking", "thinking": "Let me analyze...", "signature": "..."}

Multi-turn Conversation

json
{
  "model": "claude-opus-4-6",
  "max_tokens": 1024,
  "messages": [
    {"role": "user", "content": "What is 2+2?"},
    {"role": "assistant", "content": "2+2 = 4."},
    {"role": "user", "content": "Multiply that by 10."}
  ]
}

Streaming

Set "stream": true to receive Server-Sent Events (SSE) as the model generates tokens.

bash
curl -N -X POST https://api.pagegrid.in/v1/messages \
  -H "api-key: sk-pgrid-..." \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-opus-4-6","max_tokens":1024,"stream":true,
       "messages":[{"role":"user","content":"Write a poem"}]}'

SSE Event Flow

1. message_start — contains input_tokens
2. content_block_start — opens a content block
3. content_block_delta — incremental text chunks (repeated)
4. content_block_stop — closes the block
5. message_delta — stop_reason + final output_tokens
6. message_stop — stream complete

Delta Types

ParameterTypeRequiredDescription
text_deltaobjectrequired{type: "text_delta", text: "Hello"}
input_json_deltaobjectrequiredPartial JSON for tool_use blocks
thinking_deltaobjectrequiredExtended thinking content
signature_deltaobjectrequiredThinking block signature

Token Usage in Streaming

  • message_start event contains usage.input_tokens + cache token counts
  • message_delta event contains cumulative usage.output_tokens
  • You are charged after the stream completes

Token Counting

POST/v1/messages/count_tokens

Count tokens before sending a request. This endpoint is free — no charge to your wallet.

bash
curl -X POST https://api.pagegrid.in/v1/messages/count_tokens \
  -H "api-key: sk-pgrid-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-opus-4-6",
    "messages": [{"role": "user", "content": "Hello, world!"}]
  }'

Response:

json
{"input_tokens": 12}

Models

GET/v1/models

List all available models with capabilities and pricing.

ModelIDContextMax OutputBest For
Loading models...

Model availability may vary. Use GET /v1/models to see currently active models with live pricing.

Pricing

Pay per token. No monthly fees. No subscriptions. No minimums.

Token Rates

ModelInput /1MOutput /1MCache Write /1MCache Read /1M
Loading pricing...

Cache Token Pricing

Cache pricing is shown in the table above. When users add cache_control to their requests, tokens are billed at the cache write rate (on first request) and cache read rate (on subsequent requests).

  • Cache write tokens: Charged when content is first cached (cache miss)
  • Cache read tokens: Charged when content is read from cache (cache hit — much cheaper)
  • Regular input tokens: Content not marked for caching
  • Output tokens: Always charged at the output rate

How Billing Works

text
Cost per request = (input_tokens / 1M × input_rate)
                 + (output_tokens / 1M × output_rate)
                 + (cache_write_tokens / 1M × cache_write_rate)
                 + (cache_read_tokens / 1M × cache_read_rate)

All four rates are shown in the pricing table above.
Use GET /v1/models for live pricing.

Use GET /v1/models for real-time pricing. Prices shown here are examples and may change.

Error Handling

All errors return a consistent JSON format:

json
{
  "error": {
    "type": "invalid_request_error",
    "message": "max_tokens is required"
  }
}

Error Types

HTTPTypeDescription
400invalid_request_errorBad request format or missing fields
401authentication_errorInvalid, expired, or missing API key
402billing_errorInsufficient wallet balance
403permission_errorKey lacks access to requested model
404not_found_errorModel not found or inactive
429rate_limit_errorRate or daily/monthly limit exceeded
500api_errorInternal server error
502api_errorService temporarily unavailable

Retry Strategy

  • 429: Wait and retry with exponential backoff
  • 502/500: Retry after 1-5 seconds
  • 401/402/403: Do not retry — fix credentials or add funds

Rate Limits

Rate limits are set per API key. Each key can have its own limits:

LimitDefaultDescription
Rate Limit (RPM)10Maximum requests per minute
Daily Request LimitUnlimitedMaximum requests per day (0 = unlimited)
Monthly Token LimitUnlimitedMaximum tokens per month (0 = unlimited)

Set custom limits when creating a key, or contact support for higher limits.

Wallet & Billing

Prepaid wallet system. Add funds, use tokens, track everything.

How It Works

  1. Add funds to your wallet (any amount)
  2. Each API call deducts based on actual token usage
  3. Every transaction is logged with full breakdown
  4. View balance, usage, and history in the dashboard

Important

  • Balance of $0 blocks all API requests
  • Funds never expire
  • No minimum top-up amount
  • Full transaction history available in dashboard

SDK Examples

Works with popular AI SDKs. Here are examples in Python, JavaScript, and cURL.

Python

python
from anthropic import Anthropic

client = Anthropic(
    api_key="sk-pgrid-your-key-here",
    base_url="https://api.pagegrid.in"
)

# Non-streaming
message = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)
print(message.content[0].text)

# Streaming
with client.messages.stream(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a story"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

JavaScript / TypeScript

javascript
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: "sk-pgrid-your-key-here",
  baseURL: "https://api.pagegrid.in"
});

// Non-streaming
const message = await client.messages.create({
  model: "claude-opus-4-6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello!" }]
});
console.log(message.content[0].text);

// Streaming
const stream = client.messages.stream({
  model: "claude-opus-4-6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Write a story" }]
});
for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

cURL with Streaming

bash
curl -N -X POST https://api.pagegrid.in/v1/messages \
  -H "Content-Type: application/json" \
  -H "api-key: sk-pgrid-your-key" \
  -d '{
    "model": "claude-opus-4-6",
    "max_tokens": 1024,
    "stream": true,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'