API
Base URL: https://api.ravenoutreach.com. All endpoints are under /v1. The OpenAPI 3.1 description is at /v1/openapi.json.
Conventions
| Auth | Authorization: Bearer <key or token>; see authentication |
| Versioning | Responses carry Api-Version: 2026-11-01. You can send the same header to pin a version. |
| Rate limit | 20 requests per second per key. Every response has X-RateLimit-Limit, -Remaining, -Reset and -Policy. A 429 has Retry-After. |
| Long polls | wait=N (up to 55 seconds) on team, message and lead reads answers as soon as something changes |
| Paging | Lead lists return next_cursor, also sent in X-Next-Cursor. Pass it back as cursor until it's absent. |
| Retries | Send Idempotency-Key: <uuid> on a POST, PATCH or DELETE you might retry. For 24 hours, a retry with the same key gets the first response back, marked Idempotent-Replayed: true. A retry while the first call is still running gets 409. Creating a team with the same brief within 10 minutes also returns the first team, even without a key. |
| Errors | One envelope with a code and a fix; see errors |
Endpoints
| Method and path | What it does |
|---|---|
GET /v1/account |
The account, its credit by kind, held credit, this month's usage, top_up_url |
POST /v1/teams |
Starts a team. Body: brief (required), product, name, daily_budget_usd, spend_limit_usd, researchers, verifiers, auto_add_campaigns. Returns 201. Returns 402 if the account can't pay for planning. |
GET /v1/teams |
The account's teams (include_archived=true for all) |
GET /v1/teams/{id} |
One team. wait and wait_for (status, plan, leads or messages) long-poll for a change. |
PATCH /v1/teams/{id} |
name, daily_budget_usd, spend_limit_usd, auto_add_campaigns |
POST /v1/teams/{id}/pause, /resume, /archive |
Stops or restarts spending |
GET /v1/teams/{id}/plan |
The current plan, as JSON and as markdown |
POST /v1/teams/{id}/plan/approve |
Body: {"version": N}, the version the user reviewed. Starts paid research. |
POST /v1/teams/{id}/messages |
Body: {"body": "…"}. Sends a message to the supervisor. Returns 202. |
GET /v1/teams/{id}/messages |
Messages and replies. after and wait wait for new ones. |
GET /v1/teams/{id}/campaigns |
The team's lead lists and their progress |
GET /v1/campaigns/{id}, PATCH /v1/campaigns/{id} |
One campaign. PATCH changes status (active or paused) or target_verified. |
GET /v1/leads |
Leads, oldest first. Filter with team_id or campaign_id, plus since, cursor, limit (up to 1000), format, max_tokens and wait. |
GET /v1/leads/{id} |
One lead |
DELETE /v1/leads/{id} |
Removes a lead from lists and exports. The person won't be researched again. |
GET /v1/teams/{id}/runs |
Agent runs: role, status, cost, summary |
GET /v1/teams/{id}/candidates |
Everyone found and what verification decided (status=rejected shows why) |
Leads
| Field | Meaning |
|---|---|
email |
Published on the person's own site and checked on source_url |
first_name, last_name, company, title, website |
As the site shows them |
source_url |
The page the email is on |
evidence |
The text around the email on that page, or mailto:… when it's only a link |
found_via |
What led to the site: search:<query> or list:<site> |
fit_reason |
Why the person fits the campaign |
line |
One personal sentence, written per the campaign's brief |
campaign_id, team_id, verified_at |
Where the lead belongs and when it was verified |
Formats
format sets the shape of GET /v1/leads:
| Format | Shape |
|---|---|
json (default) |
{"leads": [...], "next_cursor": "..."} |
jsonl |
One lead per line |
csv |
A header row, then one lead per row |
markdown |
A compact table for language models, cut to fit max_tokens (default 4000) |