Developers
JSON API
We run Little Outreach as a public directory backed by provenance and citations; this HTTP API is how you query and add that data from apps, automations, and agents.
It is versioned under
/api/v1.
It powers search, profiles, organizations, memberships, places, aliases, and provenance-backed citations.
Everything below is public — no account is required to read the spec or try read-only requests if you have a key.
Authentication
Send your API key on every request (same value everywhere):
Authorization: Bearer <your-api-key>X-Api-Key: <your-api-key>
Keys are issued per user.
Sign in
from the header, then open Account to copy a key.
Requests without a valid key receive 401 Unauthorized.
Credits & billing
Each /api/v1 request uses one credit (site admins are not metered).
New accounts include 1,000 free credits.
Responses include X-API-Credits-Remaining; at zero credits you receive 402 Payment Required.
Call GET /api/v1/me to read your balance without spending a credit.
After sign in, use Account to top up with Stripe when the operator has configured billing.
Adding a person
The directory is citation-backed, so every write needs a source reference. Pick the path that matches your situation — they all produce the same data.
Prefer a form to curl? Try the
People playground — labelled fields for the same endpoint, no JSON typing required.
Option A — one call (recommended)
POST /api/v1/people/quick_add takes a flat body. Only first_name, last_name, and a citation signal are required.
curl -X POST https://www.littleoutreach.com/api/v1/people/quick_add \
-H "Authorization: Bearer $LITTLE_OUTREACH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ada",
"last_name": "Lovelace",
"email": "ada@example.com",
"aliases": ["Ada L"],
"linkedin_url": "https://www.linkedin.com/in/ada-lovelace",
"source_url": "https://example.com/press/ada-joins",
"source_category": "news"
}'
Valid source_category values:
social,
news,
organization,
public_data,
academic,
legal,
regulatory,
website,
database,
broadcast,
publication,
communication,
professional_directory,
survey,
internal.
Add organization_public_id (plus optional role, title, start_date) and the membership is created in the same transaction — no follow-up call needed. The response includes both person and membership.
Option B — canonical POST /api/v1/people
Use this when you want the full feature surface: setting public_id, birthday, description, or crafting nested citations by hand. The canonical shape uses a person wrapper plus a source_reference sibling.
curl -X POST https://www.littleoutreach.com/api/v1/people \
-H "Authorization: Bearer $LITTLE_OUTREACH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"person": {
"first_name": "Ada",
"last_name": "Lovelace",
"linkedin_url": "https://www.linkedin.com/in/ada-lovelace",
"aliases": ["Ada L"],
"emails": ["ada@example.com"]
},
"source_reference": {
"source_category": "social",
"url": "https://www.linkedin.com/in/ada-lovelace",
"title": "LinkedIn profile"
}
}'
Friendlier aliases that the endpoint accepts:
sourceorcitationin place ofsource_reference.categoryin place ofsource_categoryinside the citation.- Flat top-level fields — skip the
person:wrapper entirely and sendfirst_name/last_nameat the root. emailsandaliasesarrays (strings or objects) rewrite to Rails-nested attributes server-side.
Adding a person to an organization
In two separate calls:
-
Find or create the organization:
GET /api/v1/organizations?domain=acme.com, orPOST /api/v1/organizationswhen it doesn't exist. -
Create the person with the membership in one call:
POST /api/v1/people/quick_addwithorganization_public_id. Or keep them separate withPOST /api/v1/people+POST /api/v1/memberships.
When things go wrong
400 provenance_required— include a citation. The response body'sdetails.expectedshows the exact shape plus the accepted aliases.403 forbidden— the API key is read-only. Ask a site admin to grantcan_editbefore retrying.422 unprocessable_entity— validation failed (e.g. the email is already on another record). Inspectdetails.messagesanddetails.field_errors.
Adding an organization
Organizations anchor memberships, places, and email patterns. Every write needs a source reference, but the shorthand keeps that boilerplate to a single URL.
Want to click through it instead of composing JSON? The Organizations playground wraps the same endpoint in a form.
Option A — one call (recommended)
POST /api/v1/organizations/quick_add takes a flat body. Only name, domain, organization_type, and a citation signal are required.
curl -X POST https://www.littleoutreach.com/api/v1/organizations/quick_add \
-H "Authorization: Bearer $LITTLE_OUTREACH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Analytical Engine Ltd.",
"domain": "analyticalengine.example.com",
"organization_type": "company",
"aliases": ["AEL"],
"source_url": "https://analyticalengine.example.com/about",
"source_category": "organization"
}'
Pass a nested person block (with optional role, title, start_date, email) to bootstrap the first member in the same transaction. The response includes organization, person, and membership:
curl -X POST https://www.littleoutreach.com/api/v1/organizations/quick_add \
-H "Authorization: Bearer $LITTLE_OUTREACH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Analytical Engine Ltd.",
"domain": "analyticalengine.example.com",
"organization_type": "company",
"source_url": "https://analyticalengine.example.com/about",
"person": {
"first_name": "Ada",
"last_name": "Lovelace",
"email": "ada@analyticalengine.example.com",
"role": "founder",
"title": "Chief Analytical Officer",
"start_date": "1843-10-01"
}
}'
Option B — canonical POST /api/v1/organizations
Use this when you want the full feature surface: parent_organization_public_id, email_local_part_pattern, or hand-crafted citations. The canonical shape uses an organization wrapper plus a source_reference sibling.
curl -X POST https://www.littleoutreach.com/api/v1/organizations \
-H "Authorization: Bearer $LITTLE_OUTREACH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"organization": {
"name": "Analytical Engine Ltd.",
"domain": "analyticalengine.example.com",
"organization_type": "company",
"description": "Mechanical computing pioneers.",
"aliases": ["AEL"]
},
"source_reference": {
"source_category": "website",
"url": "https://analyticalengine.example.com/about",
"title": "About us"
}
}'
Friendlier aliases that the endpoint accepts:
sourceorcitationin place ofsource_reference.categoryin place ofsource_categoryinside the citation.- Flat top-level fields — skip the
organization:wrapper and sendname/domain/organization_typeat the root. aliases(orname_aliases) andemailsarrays rewrite to Rails-nested attributes server-side./api/v1/advertisersis a drop-in alias — same behaviour, JSON usesadvertiser/advertiserskeys instead.
Before you create — check for duplicates
Domains are unique. A quick lookup avoids a 422 round-trip and keeps the directory clean:
curl https://www.littleoutreach.com/api/v1/organizations?domain=analyticalengine.example.com \
-H "Authorization: Bearer $LITTLE_OUTREACH_API_KEY"
An empty result queues the domain for research automatically. If a result comes back, reuse its public_id with POST /api/v1/people/quick_add or POST /api/v1/memberships.
When things go wrong
400 provenance_required— include a citation. The response body'sdetails.expectedshows the exact shape plus accepted aliases.422 unprocessable_entity— the domain is missing, isn't a public web hostname, or is already taken. Inspectdetails.field_errorsfor the specific field.403 forbidden— the API key is read-only. Ask a site admin to grantcan_editbefore retrying.
Adding data (agents & automations)
Independent agents and integrations populate the directory by calling
POST and
PATCH
under /api/v1.
Use an API key with can_edit.
Most creates require a nested source_reference (citation URL + category)—see
Writes & provenance
and the OpenAPI schemas.
Suggested flow
-
Optional: Unified search
(
GET) to avoid duplicate people or orgs. - Create or update people and organizations (order can swap if you already have ids).
- Add memberships to link a person to an organization.
- Add places, name aliases, and source references as needed.
Create endpoints (POST)
Start here when inserting new records. Each row links to the full doc page and opens the same operation in Swagger UI.
- Create person /api/v1/people
- Quick add person /api/v1/people/quick_add
- Create organization /api/v1/organizations
- Quick add organization /api/v1/organizations/quick_add
- Create membership /api/v1/memberships
- Create place /api/v1/places
- Create name alias /api/v1/name_aliases
- Create source reference /api/v1/source_references
All write operations
Updates and deletes, plus every mutating method, in resource order—use when fixing or removing data.
| Method | Operation | Path | Open in Swagger |
|---|---|---|---|
| POST | Create person | /api/v1/people | Open |
| POST | Quick add person | /api/v1/people/quick_add | Open |
| PATCH | Update person | /api/v1/people/{public_id} | Open |
| POST | Create organization | /api/v1/organizations | Open |
| POST | Quick add organization | /api/v1/organizations/quick_add | Open |
| PATCH | Update organization | /api/v1/organizations/{public_id} | Open |
| POST | Create membership | /api/v1/memberships | Open |
| PATCH | Update membership | /api/v1/memberships/{public_id} | Open |
| DELETE | Delete membership | /api/v1/memberships/{public_id} | Open |
| POST | Create place | /api/v1/places | Open |
| PATCH | Update place | /api/v1/places/{public_id} | Open |
| DELETE | Delete place | /api/v1/places/{public_id} | Open |
| POST | Create name alias | /api/v1/name_aliases | Open |
| PATCH | Update name alias | /api/v1/name_aliases/{public_id} | Open |
| DELETE | Delete name alias | /api/v1/name_aliases/{public_id} | Open |
| POST | Create source reference | /api/v1/source_references | Open |
| PATCH | Update source reference | /api/v1/source_references/{public_id} | Open |
| DELETE | Delete source reference | /api/v1/source_references/{public_id} | Open |
| PATCH | Update (mark complete or reopen) | /api/v1/zero_result_searches/{id} | Open |
Reference
- Swagger UI — browse every path, parameter, and schema; execute requests with “Authorize”.
- OpenAPI 3 specification (YAML) — machine-readable contract for codegen and CI.
- Interactive API playground — same-origin fetch from your browser (paste a key or sign in). Or jump straight into a scoped form: Unified search · People · Organizations · Memberships · Places · Name aliases · Source references
Writes & provenance
Creating or updating most records requires a source reference (citation):
source_category,
a valid http(s) URL, and optional metadata.
Mutating methods need an API key with can_edit.
The full rules and request shapes are in the OpenAPI document.
Frequently asked questions
- What is the base URL for the Little Outreach JSON API?
-
All endpoints live under
/api/v1on the same host as the web app (unless your deployment documents a different base). - How do I authenticate API requests?
-
Send your per-user API key on every request as
Authorization: Bearer <key>or duplicate the same value inX-Api-Key. Sign in, then use the API key link on your Account page to copy a key. Missing or invalid keys receive401 Unauthorized. - Where is the machine-readable API specification?
- The OpenAPI 3 document is at /api-docs/v1/swagger.yaml. Browse and try operations in Swagger UI or the API playground.
- Which requests require an editor (write) API key?
-
POST,PATCH,PUT, andDELETEthat change data require an API key withcan_edit. Read-only keys still work forGETwhere the API allows it.
MCP & tools
For Claude Desktop, OpenClaw, or other MCP clients, see MCP server setup.
Endpoint reference
Each HTTP method and path has its own page with a stable URL, unique title, meta description, and structured data—so search engines and assistants can point to a specific operation.
Lookups
Memberships
Name aliases
Organizations
People
Places
Source references
- GET List source references /api/v1/source_references
- POST Create source reference /api/v1/source_references
- DELETE Delete source reference /api/v1/source_references/{public_id}
- GET Show source reference /api/v1/source_references/{public_id}
- PATCH Update source reference /api/v1/source_references/{public_id}