API Reference
Base URL https://api.reviewintelligence.dev/v1 · local
http://localhost:3000/v1. All responses are JSON and include an
X-Request-Id header plus X-RateLimit-* headers.
Quickstart
Run the API locally in mock mode (no credentials needed):
npm install
npm run dev # boots on :3000 in mock mode
# authenticate with the dev key printed at startup:
curl localhost:3000/v1/analyze \
-H "Authorization: Bearer rik_local_dev_key" \
-H "Content-Type: application/json" \
-d '{"text":"Great product, slow shipping","options":{"suggest_reply":true}}'
Authentication
Send your key as a bearer token. Keys are shown once and stored only as a hash.
Authorization: Bearer rik_live_xxx
Errors
Every error uses a stable envelope:
{ "error": { "code": "rate_limited", "message": "Too many requests", "request_id": "req_..." } }
| HTTP | code |
|---|---|
| 400 | invalid_request |
| 401 | unauthorized |
| 402 | quota_exceeded |
| 404 | not_found |
| 422 | unprocessable |
| 429 | rate_limited |
| 503 | ai_unavailable |
POST /v1/analyze · 1 AU + 1/4,000 chars
{ "text": "Checkout was fast but support never replied.",
"rating": 3, "options": { "suggest_reply": true, "reply_tone": "professional" } }
{ "id": "...", "sentiment": { "score": -0.18, "label": "negative", "confidence": 0.81 },
"emotion": "frustration", "topics": ["checkout speed","support"], "language": "en",
"suggested_reply": "Thanks for the feedback...", "usage": { "au_cost": 1 } }
POST /v1/analyze/batch · 1 AU/review + 1/4,000 chars
Asynchronous. Returns 202 with a job id; poll /v1/jobs/:id or receive a signed webhook.
{ "reviews": [ { "external_id": "r1", "text": "Love it" } ], "webhook_url": "https://..." }
→ { "job_id": "...", "status": "queued", "review_count": 1, "estimated_au": 1 }
POST /v1/themes · 4 AU + 1/1,250 chars
{ "reviews": ["...","..."], "max_themes": 8 }
→ { "themes": [ { "label": "onboarding", "frequency": 14, "sentiment": -0.42, "examples": ["..."] } ] }
POST /v1/summarize · 6 AU + 1/1,250 chars
{ "reviews": ["...","..."], "audience": "product_team" }
→ { "summary": { "headline": "...", "highlights": [], "lowlights": [], "recommended_actions": [] } }
POST /v1/respond · 1 AU
{ "text": "Waited 40 minutes and the food was cold.", "tone": "apologetic" }
→ { "reply": "We're truly sorry...", "tone": "apologetic", "usage": { "au_cost": 1 } }
Projects & ingestion
POST /v1/projects { "name": "Acme", "store_text": true }
POST /v1/projects/:id/ingest { "reviews": [ { "text": "..." } ] }
GET /v1/jobs/:id
{ "job_id": "...", "status": "completed", "result": { "reviews": [...], "aggregate": {...} } }
GET /v1/usage
{ "plan": "growth", "period": "2026-06", "included_au": 40000,
"used_au": 12480, "remaining_au": 27520, "overage_au": 0,
"rate_limit": { "limit_per_min": 240 } }
POST /v1/webhooks
Deliveries are signed: header X-Webhook-Signature: sha256=<hmac> over the raw body.
{ "url": "https://example.com/hooks/ria", "events": ["job.completed","job.failed"] }
→ { "id": "...", "signing_secret": "whsec_review_intelligence_...", "active": true }