Introduction
One API key and one balance of credits for pay-per-call data APIs. The four ideas the rest of these docs build on.
Last updated
On this page
PrimaryAPI puts one HTTP interface in front of many pay-per-call data providers: social profiles and posts, search results, company and people enrichment, e-commerce listings, public records, validation and more. You hold one API key and one balance of credits. Every call is routed to a healthy upstream at the best price, and if an attempt fails it is retried automatically inside the same request. You are charged only for the answer you get.
The catalog currently lists 200 APIs across 31 platforms in 10 categories. All of them are called the same way, return the same envelope and fail with the same error shape, so code written for one API works for the next.
How a call works
- You send
POST /v1/run/{sku}with your API key and a JSON body that matches the API's input schema. - We validate the input. Unknown or malformed fields are rejected with
400 invalid_inputbefore anything runs or is charged. - We hold the most the call could cost from your credits, so a call can never overdraw them.
- We route the call to the best healthy upstream for your input. If it times out, errors or is rate limited, the call is retried automatically.
- The first answer wins. You pay its price in credits and the rest of the hold comes back at once.
- You get one envelope back with the data and what the call cost.
If every attempt fails, the whole hold comes back and you get 502 all_sources_failed. You pay nothing.
The mental model
SKU
Each API is a SKU named <platform>.<action>, for example instagram.profile, reddit.search or email.verify. A SKU has an input schema (the JSON you send), an output schema (the data you get back), a price and measured reliability. Browse them in the API reference, or programmatically with GET /v1/apis and GET /v1/apis/{sku}, which need no key.
Routing and reliability
Behind each SKU we run and monitor the upstream integrations, route every call to a healthy one and retry automatically when an attempt fails. Which upstream answered a call is an internal detail; what you see is whether the API is working: its status (operational, degraded, outage or unknown), success rate, uptime and latency measured from real traffic over 30 days.
You never pick an upstream. When you want to, the routing controls let you cap what a call may cost or prefer fast answers.
Envelope
Every successful call returns the same JSON shape:
{
"output": {
"found": true,
"data": {
"email": "[email protected]",
"domain": "example.com",
"status": "good",
"reason": "accepted_email",
"score": 0.97,
"disposable": false,
"role": false,
"free": false,
"catchAll": false,
"mxRecords": []
}
},
"provider": "PrimaryAPI",
"credits": 1,
"items": 1,
"requestId": "req_01JBXK6Y2N9V8T4R3Q2P1M0A7Z"
}output.data follows the SKU's output schema. List APIs also return nextCursor for the next page, and some calls carry a short hint. Making requests describes every field.
When the thing you asked about does not exist, is private, or a search matches nothing, the call still succeeds with HTTP 200: output.found is false, output.data is null and output.reason says why (not_found, private, no_results, …). It usually costs nothing. The 404 not_found error is reserved for URLs that do not exist, such as an unknown SKU.
credits
credits is exactly what this call took from your balance, in whole credits. It is 0 when nothing was charged. Every API has a price in credits, per call or, for some list and search APIs, per result returned; most calls cost 1 or 2 credits. A credit costs $0.005 on Pay as you go and less on a plan, and every API costs the same credits on every plan.
You pay only for answers: invalid input, authentication and balance errors, calls where every attempt failed, quotes, polling and re-reading stored results are all free. Pricing and billing has the full rules.
Base URL and conventions
| Convention | Value |
|---|---|
| Base URL | https://api.primaryapi.com |
| Versioning | Customer endpoints live under /v1. Additive changes (new fields, new SKUs, new error details) can ship at any time; breaking changes would get a new version prefix. |
| Format | JSON in and out, UTF-8. Request bodies are limited to 2 MB. |
| Authentication | Authorization: Bearer pa_live_… or X-API-Key: pa_live_… (Authentication) |
| Identifiers | Prefixed, sortable ids: req_… for requests, key_… for API keys |
| Times | ISO 8601 in UTC, for example 2026-10-30T14:05:09.120Z |
| Credits | Whole credits as JSON integers (credits, maxCredits). Prices per result can be fractional (creditsPerResult); a call is always charged whole credits. |
Write your client to ignore fields it does not know: new optional fields are not considered breaking.
Built for people and agents
People create keys in the dashboard, set spend limits per key in credits and buy credits by card. AI agents get the same API plus a few doors of their own:
- an agent without a key can mint its own trial key and hand a claim link to its human when it needs more,
- the MCP server at
https://api.primaryapi.com/mcpexposes search, quote and run as tools, - SKILL.md teaches coding agents the whole workflow in one file, and every docs page is available as Markdown (
/llms.txt,/llms-full.txt, and the "Copy page" button above).