Get your free API key
Visit /signup or POST to /v1/signup. You get 1,000 requests/day free — no credit card needed.
curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/signup \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'
Response
{
  "api_key": "cf-xxxxxxxxxxxxxxxxxxxxxxxx",
  "tier":    "free",
  "message": "Save this key — it is shown only once."
}
Preprocess a file
Send any file's content as a string. ContextForge strips boilerplate, extracts structure, and returns the dense version — typically 50–80% smaller.
curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/preprocess_content \
  -H "X-Api-Key: cf-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{"content": "...your file text...", "filename": "report.csv"}'
Response
{
  "processed_content":          "...compressed text...",
  "original_token_count":        4200,
  "processed_token_count":       980,
  "reduction_pct":               76.7,
  "processor_used":              "csv_processor",
  "smart_query_available":        true,
  "smart_query_hint":            "Ask COUNT/SUM/FILTER questions via /v1/smart_query"
}
Pass the result to your AI
Use processed_content wherever you would have sent the original file. Your AI now has the same information in a fraction of the tokens.
python
import anthropic, requests

# Step 1 — compress
r = requests.post(
    "https://contextforge-api-production.up.railway.app/v1/preprocess_content",
    headers={"X-Api-Key": "cf-your-key"},
    json={"content": open("report.csv").read(), "filename": "report.csv"},
)
compressed = r.json()["processed_content"]

# Step 2 — profit: send fewer tokens to Claude
client = anthropic.Anthropic()
msg = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": f"Analyze this data:

{compressed}"}],
)
print(msg.content[0].text)

A Authentication

Add your key to every authenticated request as a header. Both forms are accepted:

Header (preferred)
X-Api-Key: cf-your-key-here
Bearer token
Authorization: Bearer cf-your-key-here
Keys start with cf-. Get a free key in under 10 seconds — no credit card, no OAuth dance. Visit your account page to check usage and tier.
POST /v1/preprocess_content Key required

The core endpoint. Send any file's text content; receive a compressed, structured version optimised for LLM consumption. Supports CSV, JSON, PDF text, Word, Markdown, code files, images (OCR), and more. Use the hint field to bias extraction toward your question.

FieldTypeRequiredDescription
contentstringYesRaw file content as a string (or base64 for binary files)
filenamestringYesOriginal filename — used to select the right processor (e.g. data.csv)
hintstringNoNatural-language question or task — biases extraction toward relevant sections
max_tokensintegerNoTarget output token budget (default: 2000)
curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/preprocess_content \
  -H "X-Api-Key: cf-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "content":  "date,sales,region
2024-01-01,1200,US
2024-01-02,980,EU",
    "filename": "sales.csv",
    "hint":     "What are the total sales by region?"
  }'
python
import requests

resp = requests.post(
    "https://contextforge-api-production.up.railway.app/v1/preprocess_content",
    headers={
        "X-Api-Key": "cf-your-key",
        "Content-Type": "application/json",
    },
    json={
        "content":  open("sales.csv").read(),
        "filename": "sales.csv",
        "hint":     "What are the total sales by region?",
    },
)
data = resp.json()
print(f"Reduced {data['reduction_pct']}% via {data['processor_used']}")
print(data["processed_content"])
javascript (fetch)
const resp = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/preprocess_content",
  {
    method:  "POST",
    headers: { "X-Api-Key": "cf-your-key", "Content-Type": "application/json" },
    body: JSON.stringify({
      content:  fileText,
      filename: "sales.csv",
      hint:     "Total sales by region",
    }),
  }
);
const { processed_content, reduction_pct, processor_used } = await resp.json();
console.log(`Saved ${reduction_pct}% via ${processor_used}`);
POST /v1/smart_query Key required

Zero-cost CSV answers. For COUNT, SUM, FILTER, and GROUP BY questions on tabular data, ContextForge answers directly using pandas — no LLM tokens spent at all. Returns a structured answer you can display immediately or pass to your AI as context.

FieldTypeRequiredDescription
querystringYesNatural-language question: "How many rows?", "Sum of revenue by country"
contentstringYesRaw CSV or JSON table content
filenamestringYesFilename with extension (e.g. data.csv)
curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/smart_query \
  -H "X-Api-Key: cf-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "query":    "How many rows have sales > 1000?",
    "content":  "date,sales,region
2024-01-01,1200,US
2024-01-02,980,EU",
    "filename": "sales.csv"
  }'
python
import requests

resp = requests.post(
    "https://contextforge-api-production.up.railway.app/v1/smart_query",
    headers={"X-Api-Key": "cf-your-key"},
    json={
        "query":    "How many rows have sales > 1000?",
        "content":  open("sales.csv").read(),
        "filename": "sales.csv",
    },
)
data = resp.json()
# data["answer"] has the direct result — no LLM tokens used
print(data["answer"])
javascript
const { answer } = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/smart_query",
  {
    method:  "POST",
    headers: { "X-Api-Key": "cf-your-key", "Content-Type": "application/json" },
    body: JSON.stringify({ query: "Total sales by region", content: csvText, filename: "data.csv" }),
  }
).then(r => r.json());
console.log(answer);
POST /v1/preprocess_batch Key required

Process 1–10 files in one request. Each file in the array is processed independently and returned in the same order. Ideal for batch document ingestion pipelines.

curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/preprocess_batch \
  -H "X-Api-Key: cf-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      {"content": "# Report
Q1 revenue was $1.2M...", "filename": "q1.md"},
      {"content": "date,amount
2024-01-01,1200",      "filename": "data.csv"}
    ]
  }'
python
import requests, pathlib

files = [
    {"content": pathlib.Path(p).read_text(), "filename": p}
    for p in ["q1.md", "data.csv", "notes.txt"]
]

resp = requests.post(
    "https://contextforge-api-production.up.railway.app/v1/preprocess_batch",
    headers={"X-Api-Key": "cf-your-key"},
    json={"files": files},
)
for result in resp.json()["results"]:
    print(result["filename"], "-", result["reduction_pct"], "%")
javascript
const { results } = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/preprocess_batch",
  {
    method:  "POST",
    headers: { "X-Api-Key": "cf-your-key", "Content-Type": "application/json" },
    body: JSON.stringify({ files: [
      { content: text1, filename: "q1.md"   },
      { content: text2, filename: "data.csv" },
    ]}),
  }
).then(r => r.json());
results.forEach(r => console.log(r.filename, r.reduction_pct + "% saved"));
POST /v1/estimate_tokens No auth

Estimate token count for a piece of text without an API key. Useful for pre-flight checks before sending to an LLM. Uses a tiktoken-compatible estimator.

curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/estimate_tokens \
  -H "Content-Type: application/json" \
  -d '{"text": "Your document text here...", "filename": "doc.txt"}'
python
import requests
r = requests.post(
    "https://contextforge-api-production.up.railway.app/v1/estimate_tokens",
    json={"text": open("doc.txt").read(), "filename": "doc.txt"},
)
print(r.json()["token_count"])  # e.g. 4200
javascript
const { token_count } = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/estimate_tokens",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ text: fileText, filename: "doc.txt" }),
  }
).then(r => r.json());
console.log(`~${token_count} tokens`);
GET /v1/provider-status No auth

Check which AI providers (Claude, OpenAI, Gemini, etc.) are currently configured and reachable on this server. Useful for health dashboards and before routing requests.

curl
curl https://contextforge-api-production.up.railway.app/v1/provider-status
python
import requests
r = requests.get("https://contextforge-api-production.up.railway.app/v1/provider-status")
print(r.json())
javascript
const status = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/provider-status"
).then(r => r.json());
console.log(status.providers);
GET /v1/quickstart Key required

Returns a personalized integration guide based on your tier, quota, and usage history. Includes MCP config snippet, code examples tailored to your account, and recommended next steps.

curl
curl https://contextforge-api-production.up.railway.app/v1/quickstart \
  -H "X-Api-Key: cf-your-key"
python
import requests
r = requests.get(
    "https://contextforge-api-production.up.railway.app/v1/quickstart",
    headers={"X-Api-Key": "cf-your-key"},
)
guide = r.json()
print(guide["mcp_config"])  # paste into Claude settings
javascript
const guide = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/quickstart",
  { headers: { "X-Api-Key": "cf-your-key" } }
).then(r => r.json());
console.log(guide.mcp_config);
GET /v1/recommend No auth

Returns the best endpoint to use for a given file type and query — no auth required. Pass a filename and optional query string; get back a recommendation of preprocess_content, smart_query, or another tool.

curl
curl "https://contextforge-api-production.up.railway.app/v1/recommend?filename=data.csv&query=total+sales"
python
import requests
r = requests.get(
    "https://contextforge-api-production.up.railway.app/v1/recommend",
    params={"filename": "data.csv", "query": "total sales by region"},
)
print(r.json()["recommended"])  # e.g. "smart_query"
javascript
const { recommended } = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/recommend?filename=data.csv&query=total+sales"
).then(r => r.json());
console.log(recommended);
GET /v1/leaderboard No auth

Returns the top 5 file types by average compression ratio across all users (anonymised). Useful for benchmarking expectations before processing your own files.

curl
curl https://contextforge-api-production.up.railway.app/v1/leaderboard
python
import requests
r = requests.get("https://contextforge-api-production.up.railway.app/v1/leaderboard")
for entry in r.json()["leaderboard"]:
    print(entry["file_type"], entry["avg_reduction_pct"])
javascript
const { leaderboard } = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/leaderboard"
).then(r => r.json());
leaderboard.forEach(e => console.log(e.file_type, e.avg_reduction_pct + "% avg reduction"));
POST /v1/compress Key required

Simple alias for /v1/preprocess_content. Accepts the same body; returns the same response. Use this if you want a shorter, more memorable URL.

curl
curl -X POST https://contextforge-api-production.up.railway.app/v1/compress \
  -H "X-Api-Key: cf-your-key" \
  -H "Content-Type: application/json" \
  -d '{"content": "...your text...", "filename": "doc.txt"}'
python
import requests
r = requests.post(
    "https://contextforge-api-production.up.railway.app/v1/compress",
    headers={"X-Api-Key": "cf-your-key"},
    json={"content": text, "filename": "doc.txt"},
)
print(r.json()["processed_content"])
javascript
const { processed_content } = await fetch(
  "https://contextforge-api-production.up.railway.app/v1/compress",
  {
    method:  "POST",
    headers: { "X-Api-Key": "cf-your-key", "Content-Type": "application/json" },
    body: JSON.stringify({ content: text, filename: "doc.txt" }),
  }
).then(r => r.json());

S System & discovery endpoints

EndpointDescription
GET /v1/info All key product info in one call — version, features, supported file types, and links. No auth required.
GET /v1/health Server status, supported file types, and available tools.
GET /v1/ping Ultra-lightweight liveness check (<1 ms, no DB). For load balancers.
GET /v1/version Returns just the server version string.
GET /v1/processors Available file processors with supported extensions.
GET /v1/analytics Aggregate usage stats across all users (anonymous).
GET /v1/history Last 50 processing events — filename, tokens saved, processor, timestamp. Key required.
GET /v1/changelog Latest release notes as JSON.
GET /openapi.json Full OpenAPI 3.0 schema — use with any client or code generator. View JSON →

R Response fields reference

Field Type Meaning
reduction_pct float Percentage of tokens removed vs. the original. 76.7 means the output uses 76.7% fewer tokens. Higher is better.
processor_used string Name of the processor that handled the file (e.g. csv_processor, pdf_extractor, markdown_processor). Useful for debugging unexpected results.
smart_query_available boolean true when the file is tabular (CSV/Excel/JSON array) and can be queried via /v1/smart_query for free COUNT/SUM/FILTER answers.
smart_query_hint string Human-readable hint explaining what kinds of questions can be answered for free via smart_query. Empty string when smart_query_available is false.
original_content_preview string First 200 characters of the original input — useful for UI display and confirming you sent the right file.
original_token_count integer Estimated token count of the content you sent in. Used to compute reduction_pct.
processed_token_count integer Estimated token count of processed_content. This is what you actually send to the LLM.
processed_content string The compressed, structured output ready to paste into an LLM prompt.

Copy the JSON block below and import it into Postman via File → Import → Raw text. All endpoints are pre-filled with the production base URL and a {{api_key}} variable — set that in your Postman environment.

After importing, create a Postman Environment with variable api_key = your cf-... key. Every request will pick it up automatically from the X-Api-Key header.
Postman Collection v2.1 JSON
{
  "info": {
    "name":   "ContextForge API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "base_url", "value": "https://contextforge-api-production.up.railway.app" },
    { "key": "api_key",  "value": "cf-your-key-here" }
  ],
  "item": [
    {
      "name": "Signup — get free API key",
      "request": {
        "method": "POST",
        "header": [{ "key": "Content-Type", "value": "application/json" }],
        "url": "{{base_url}}/v1/signup",
        "body": {
          "mode": "raw",
          "raw": "{\"name\": \"Alice\", \"email\": \"alice@example.com\"}"
        }
      }
    },
    {
      "name": "Preprocess content",
      "request": {
        "method": "POST",
        "header": [
          { "key": "X-Api-Key",     "value": "{{api_key}}" },
          { "key": "Content-Type", "value": "application/json" }
        ],
        "url": "{{base_url}}/v1/preprocess_content",
        "body": {
          "mode": "raw",
          "raw": "{\"content\": \"date,sales\\n2024-01-01,1200\", \"filename\": \"data.csv\"}"
        }
      }
    },
    {
      "name": "Smart query (CSV)",
      "request": {
        "method": "POST",
        "header": [
          { "key": "X-Api-Key",     "value": "{{api_key}}" },
          { "key": "Content-Type", "value": "application/json" }
        ],
        "url": "{{base_url}}/v1/smart_query",
        "body": {
          "mode": "raw",
          "raw": "{\"query\": \"How many rows?\", \"content\": \"date,sales\\n2024-01-01,1200\", \"filename\": \"data.csv\"}"
        }
      }
    },
    {
      "name": "Batch preprocess",
      "request": {
        "method": "POST",
        "header": [
          { "key": "X-Api-Key",     "value": "{{api_key}}" },
          { "key": "Content-Type", "value": "application/json" }
        ],
        "url": "{{base_url}}/v1/preprocess_batch",
        "body": {
          "mode": "raw",
          "raw": "{\"files\": [{\"content\": \"# Report\", \"filename\": \"q1.md\"}]}"
        }
      }
    },
    {
      "name": "Estimate tokens (no auth)",
      "request": {
        "method": "POST",
        "header": [{ "key": "Content-Type", "value": "application/json" }],
        "url": "{{base_url}}/v1/estimate_tokens",
        "body": {
          "mode": "raw",
          "raw": "{\"text\": \"Sample document text here...\"}"
        }
      }
    },
    {
      "name": "Provider status (no auth)",
      "request": {
        "method": "GET",
        "url": "{{base_url}}/v1/provider-status"
      }
    },
    {
      "name": "Quickstart guide",
      "request": {
        "method": "GET",
        "header": [{ "key": "X-Api-Key", "value": "{{api_key}}" }],
        "url": "{{base_url}}/v1/quickstart"
      }
    },
    {
      "name": "Compress alias",
      "request": {
        "method": "POST",
        "header": [
          { "key": "X-Api-Key",     "value": "{{api_key}}" },
          { "key": "Content-Type", "value": "application/json" }
        ],
        "url": "{{base_url}}/v1/compress",
        "body": {
          "mode": "raw",
          "raw": "{\"content\": \"Your text here\", \"filename\": \"doc.txt\"}"
        }
      }
    },
    {
      "name": "Health check",
      "request": {
        "method": "GET",
        "url": "{{base_url}}/v1/health"
      }
    },
    {
      "name": "Rate limit info",
      "request": {
        "method": "GET",
        "header": [{ "key": "X-Api-Key", "value": "{{api_key}}" }],
        "url": "{{base_url}}/v1/rate-limit"
      }
    }
  ]
}

ContextForge exposes an OpenAI-compatible chat completions endpoint at /v1/chat/completions. Change one line in your existing code — the base_url — and every file you send in a user message is automatically compressed before being forwarded to the underlying model.

Zero migration effort. All OpenAI SDK features work: streaming, function calling, system prompts, multi-turn conversations. ContextForge is transparent middleware — it only touches the file content, not the conversation logic.

Python (openai SDK)

python — before (standard OpenAI)
from openai import OpenAI

client = OpenAI(api_key="sk-your-openai-key")  # original

resp = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Analyze: " + large_document}],
)
print(resp.choices[0].message.content)
python — after (ContextForge drop-in)
from openai import OpenAI

client = OpenAI(
    api_key="cf-your-contextforge-key",             # ← changed
    base_url="https://contextforge-api-production.up.railway.app/v1",  # ← added
)

resp = client.chat.completions.create(
    model="gpt-4o",  # any model name — ContextForge routes it
    messages=[{"role": "user", "content": "Analyze: " + large_document}],
)
# large_document was compressed before it left your machine
print(resp.choices[0].message.content)

TypeScript / Node.js

typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey:  "cf-your-contextforge-key",
  baseURL: "https://contextforge-api-production.up.railway.app/v1",
});

const stream = await client.chat.completions.create({
  model:    "gpt-4o",
  stream:   true,
  messages: [{ role: "user", content: `Summarize: ${largeDocument}` }],
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

LangChain

python — LangChain
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="gpt-4o",
    openai_api_key="cf-your-key",
    openai_api_base="https://contextforge-api-production.up.railway.app/v1",
)
# Use llm exactly as before — files are compressed in transit

Available model names

Pass any OpenAI model name — ContextForge routes all of them through the same compression pipeline. To see the full list of recognised names, call GET /v1/models.

Supported model names (sample)
gpt-4o              gpt-4o-mini
gpt-4-turbo         gpt-3.5-turbo
claude-opus-4-5     claude-sonnet-4-5
gemini-1.5-pro      gemini-1.5-flash

E Error codes

All errors return JSON with detail and optionally hint fields.

Error response shape
{
  "detail": "Invalid or missing API key.",
  "hint":   "Get a free key at /signup",
  "code":   "MISSING_KEY"
}
Status Name Cause & fix
401 Unauthorized
Missing or invalid X-Api-Key header.
Fix: Add X-Api-Key: cf-your-key to the request. Keys start with cf-. Get a free key →
413 Payload Too Large
The content string exceeds the free-tier limit (≈ 500 KB raw text).
Fix: Upgrade to Pro for the 200 MB limit, or split the file and use /v1/preprocess_batch.
422 Unprocessable Entity
Request body failed schema validation — missing required field, wrong type, etc.
Fix: Check the detail array in the response; FastAPI lists exactly which fields are wrong.
429 Rate Limited
You have exceeded your tier's request limit.
Free: 60 req/min · 1,000 req/day. Pro: 300 req/min · 50,000 req/day. The Retry-After header tells you when to retry.
503 Service Unavailable
The requested AI provider (e.g. OpenAI, Gemini) is not configured on this server.
Fix: Switch to a different provider via the model field, or check /v1/provider-status to see what is available.

L Rate limits by tier

Free
Requests / minute20
Requests / day200
Max file size500 KB
Batch filesup to 5
Smart queryincluded
Pro
Requests / minute120
Requests / day5,000
Max file size25 MB
Batch filesup to 10
Smart queryincluded
Check remaining quota for your key anytime: GET /v1/quota — returns how many requests you have left today and when the window resets. See your account dashboard for historical usage.