Developer Portal
API keys, webhooks & integration reference
Create API Key
Your API Keys
Loadingβ¦
Key created β copy it now, it won't be shown again
Register Webhook
Registered Webhooks
Loadingβ¦
Delivery Logs
REST API Reference
BASE URL
AUTHENTICATION
All API requests must include an Authorization header with either a JWT token (for browser sessions) or an API key:
Authorization: Bearer cper_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Integration Examples
import requests
API_KEY = "cper_live_your_key_here"
BASE = "https://your-app.railway.app"
headers = {"Authorization": f"Bearer {API_KEY}"}
# List projects
projects = requests.get(f"{BASE}/api/projects", headers=headers).json()
for p in projects:
print(p["name"], p["total_carbon_kg"], "kg COβe")
# Analyze a document
with open("delivery.pdf", "rb") as f:
resp = requests.post(
f"{BASE}/api/projects/{projects[0]['id']}/analyze",
headers=headers,
files={"file": ("delivery.pdf", f, "application/pdf")},
)
result = resp.json()
print(f"Matched {result['items_matched']}/{result['items_processed']} items")
print(f"Total carbon: {result['total_carbon_kg_co2e']:.1f} kg COβe")
const API_KEY = "cper_live_your_key_here";
const BASE = "https://your-app.railway.app";
const headers = { Authorization: `Bearer ${API_KEY}` };
// List projects
const res = await fetch(`${BASE}/api/projects`, { headers });
const projects = await res.json();
// Upload and analyze
const form = new FormData();
form.append("file", fileInput.files[0]);
const analysis = await fetch(
`${BASE}/api/projects/${projects[0].id}/analyze`,
{ method: "POST", headers, body: form }
).then(r => r.json());
console.log(`${analysis.total_carbon_kg_co2e.toFixed(1)} kg COβe`);
# List projects
curl -H "Authorization: Bearer cper_live_your_key_here" \
https://your-app.railway.app/api/projects
# Analyze a document
curl -X POST \
-H "Authorization: Bearer cper_live_your_key_here" \
-F "file=@delivery.pdf" \
https://your-app.railway.app/api/projects/1/analyze
# Get portfolio analytics
curl -H "Authorization: Bearer cper_live_your_key_here" \
https://your-app.railway.app/api/analytics/portfolio
import hmac, hashlib, time
from flask import Flask, request, abort
WEBHOOK_SECRET = "your_webhook_secret"
app = Flask(__name__)
@app.post("/webhook")
def webhook():
ts = request.headers.get("X-CPER-Timestamp", "")
sig = request.headers.get("X-CPER-Signature", "")
# Reject stale requests (replay protection)
if abs(time.time() - int(ts)) > 300:
abort(400, "Stale timestamp")
expected = "sha256=" + hmac.new(
WEBHOOK_SECRET.encode(),
f"{ts}.".encode() + request.data,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(sig, expected):
abort(401, "Invalid signature")
payload = request.json
print(f"Event: {payload['event']}")
print(f"Carbon: {payload['total_carbon_kg']} kg COβe")
return "", 200