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)

This page as Markdown: /docs/api.md