Complete developer guide — curl, Python, and JavaScript examples for every endpoint.
/v1/signup. You get 1,000 requests/day free — no credit card needed.curl -X POST https://contextforge-api-production.up.railway.app/v1/signup \ -H "Content-Type: application/json" \ -d '{"name": "Alice", "email": "alice@example.com"}'
{
"api_key": "cf-xxxxxxxxxxxxxxxxxxxxxxxx",
"tier": "free",
"message": "Save this key — it is shown only once."
}
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"}'
{
"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"
}
processed_content wherever you would have sent the original file. Your AI now has the same information in a fraction of the tokens.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)
Add your key to every authenticated request as a header. Both forms are accepted:
X-Api-Key: cf-your-key-here
Authorization: Bearer cf-your-key-here
cf-. Get a free key in under 10 seconds — no credit card, no OAuth dance. Visit your account page to check usage and tier.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.
| Field | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Raw file content as a string (or base64 for binary files) |
| filename | string | Yes | Original filename — used to select the right processor (e.g. data.csv) |
| hint | string | No | Natural-language question or task — biases extraction toward relevant sections |
| max_tokens | integer | No | Target output token budget (default: 2000) |
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?" }'
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"])
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}`);
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.
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | Natural-language question: "How many rows?", "Sum of revenue by country" |
| content | string | Yes | Raw CSV or JSON table content |
| filename | string | Yes | Filename with extension (e.g. data.csv) |
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" }'
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"])
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);
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 -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"} ] }'
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"], "%")
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"));
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 -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"}'
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
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`);
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 https://contextforge-api-production.up.railway.app/v1/provider-status
import requests r = requests.get("https://contextforge-api-production.up.railway.app/v1/provider-status") print(r.json())
const status = await fetch( "https://contextforge-api-production.up.railway.app/v1/provider-status" ).then(r => r.json()); console.log(status.providers);
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 https://contextforge-api-production.up.railway.app/v1/quickstart \ -H "X-Api-Key: cf-your-key"
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
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);
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 "https://contextforge-api-production.up.railway.app/v1/recommend?filename=data.csv&query=total+sales"
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"
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);
Returns the top 5 file types by average compression ratio across all users (anonymised). Useful for benchmarking expectations before processing your own files.
curl https://contextforge-api-production.up.railway.app/v1/leaderboard
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"])
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"));
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 -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"}'
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"])
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());
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.
api_key = your cf-... key. Every request will pick it up automatically from the X-Api-Key header.{
"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.
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)
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)
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 ?? ""); }
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
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.
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
All errors return JSON with detail and optionally hint fields.
{
"detail": "Invalid or missing API key.",
"hint": "Get a free key at /signup",
"code": "MISSING_KEY"
}
GET /v1/quota — returns how many requests you have left today and when the window resets. See your account dashboard for historical usage.