Raw endpoints
Provider + endpoint addressing for the long tail: the provider's own request and payload, settled on the provider's measured cost after the run.
Two tiers share one front door. Capabilities are the routed product: one name, normalized input and output, a quote before the run, several providers behind it, waterfall failover. Raw endpoints are the long tail: one provider's own endpoint, called with the provider's own request shape, answered with the provider's own payload. No routing, no normalization, no fixed price.
Use a capability when one exists (discover tells you which capability wraps an endpoint). Use a raw endpoint when you need a provider field the capability does not expose, or a job the catalog has not wrapped yet.
Where they come from
Endpoints are imported from the providers' own catalogs, not hand-written: DataForSEO's OpenAPI specification (every live endpoint plus the free reference data), the Apify store (public actors that allow agentic use and bill per event or per compute, filtered to actors people actually run), and the OpenAPI specifications of TikHub, Exa and Firecrawl. A few providers without a machine-readable catalog have hand-maintained manifests (LeadMagic, Hunter, Tomba, MillionVerifier, PredictLeads, ScrapeCreators, Apollo, Findymail, USAspending, USAJOBS, Grants.gov, Federal Register). USAspending, USAJOBS, Grants.gov and the Federal Register are public federal APIs with no charge: their endpoints hold nothing and settle at $0, so an agent can pull award records, incumbents and contract end dates by agency and office, the open and closed federal job postings by agency code, title and date, grant opportunities with the agency contact on each, and the requests for information, notices and rules an agency publishes before it buys, at no cost.
Some providers are never exposed raw, and inspect says why: fal (its terms prohibit it; use creative.*), AgentMail and Name.com (inboxes and domains live in the platform account and are owned per workspace; use email.* and domain.*).
Each provider page shows how many endpoints it serves. GET /v1/catalog/providers/{provider} carries endpoints.count and endpoints.status: live (runs now), ready (listed, platform account pending), excluded.
Addressing
provider + endpoint
dataforseo + /v3/serp/google/organic/live/advanced. apify + /apidojo/tweet-scraper. tikhub + /api/v1/tiktok/app/v3/fetch_video_comments. The endpoint is the provider's own path; discover and the provider listing return it verbatim.
Discover
POST /v1/discover searches capabilities and endpoints together. Every item has kind (capability or endpoint), a relevance score and a health verdict; capabilities outrank endpoints on equal relevance, and a live capability that wraps an endpoint always ranks above it. Restrict with "kind": "endpoint" or "provider": "dataforseo". Read the response's hints.
routergrowth discover -q "tiktok video comments" --kind endpoint
routergrowth endpoints -p dataforseo -q backlinks # one provider's list, substring filter
Inspect
{"provider": "dataforseo", "endpoint": "/v3/serp/google/organic/live/advanced"}
Returns the provider's contract: input with pathParams, queryParams, body (properties, required) and bodyType, an example, the cost model, health, wrapped_by (capabilities that call this endpoint), a ready-to-run run.cli, and hints. Apify actors load their input schema from the actor's build on first inspect.
input.bodyType |
Meaning |
|---|---|
task |
DataForSEO: input is one task object (or an array of up to 10); the request body is the array |
actor_input |
Apify: input is the actor's input object |
json |
the JSON body; on GET endpoints input becomes query parameters |
Run
{
"provider": "dataforseo",
"endpoint": "/v3/serp/google/organic/live/advanced",
"input": {"keyword": "best crm", "location_code": 2840, "language_code": "en"},
"routing": {"max_cost": "0.05"}
}
path fills {placeholders} in the endpoint ({"domain": "example.com"}), query adds query parameters. The response has the run's usual shape with kind: "endpoint", capability: null, endpoint set, and result.data holding the provider's payload untouched (result.raw: true).
How a raw run bills
There is no quote. Instead:
- Hold. Before the call, the wallet holds the rate-card estimate with headroom when the provider publishes rates, or $1.00 when it does not.
routing.max_costlowers the hold; set it on every raw call. - Settle. After the call, the charge is the provider's measured cost, at the platform rate, when the provider reports its cost (DataForSEO reports every task's cost; Apify reports
usageTotalUsd), the rate-card estimate otherwise. The charge never exceeds the hold, and never exceedsmax_cost. - Release. Provider errors, timeouts and HTTP 4xx/5xx release the hold in full. A measured cost of zero charges nothing.
Apify books a run's per-event charges a few seconds after the run ends, so an Apify run settles in two steps. When the call returns, it charges the larger of what Apify has reported so far and the rate card for the items delivered. A few minutes later, RouterGrowth reads Apify's final bill for that run and adjusts the charge to it: one more usage_charge entry on the run, either the rest of the charge or the overcharge returned, still within the hold and max_cost. GET /v1/runs/{id} shows the final charge once it is in.
An Apify actor that stops at its timeout or at your cap after collecting items is not a failure: the run succeeds with the items it collected and settles on what Apify measured, never above max_cost. result.data.run.status shows where it stopped (TIMED-OUT, ABORTED), and the attempt's detail starts with partial:. With no items, the hold is released.
Apify actors that bill per event receive your cap directly: your cap becomes the run's maxTotalChargeUsd, enforced by Apify.
Raw runs never fall back to another provider: there is nothing equivalent to fall back to.
Controls
The daily spend guard applies to raw runs like any other. A per-run ceiling exists for exactly this tier: POST /v1/spend-guard {"per_run_limit": "1"} blocks any single run whose hold would exceed $1 (status blocked, error cost_limit_exceeded, a controls list naming the control). It is off unless you enable it; null disables it again.
Health
Every endpoint and every capability offer carries health: healthy (confirmed within the last hour), stable (strong 30-day record), degraded, outage, or unknown (not enough data, common for low-traffic endpoints, not a warning), with latency_ms_p50, the typical latency in milliseconds. For Apify actors with no measurements of our own, the actor's published 30-day run stats set the verdict. Use health to break ties between two endpoints that both fit, never to skip one that is unknown.
Promotion
Raw calls that recur are the roadmap: an endpoint many workspaces call gets wrapped into a routed capability with a fixed price and a second provider behind it. python -m app.ops.endpoints usage is the report.
Reading this as an agent? This page as markdown: /docs/api/endpoints.md · every page: /docs/llms.txt