Authentication
One credential covers both surfaces: an API key, sent as a header. The hosted MCP endpoint and the REST API check it the same way, in middleware, before a request reaches any tool.
Where keys come from
Create, rotate, and revoke keys in the dashboard. A key is shown in full exactly once, at creation; after that the dashboard only ever shows its prefix. Rotation mints a replacement under the same prefix and revokes the old secret in one step, so a compromised key is a two-minute fix rather than a re-onboarding.
Keys minted in the dashboard belong to the signed-in account and run on the public surface. That matters for more than billing: the public surface is where the redistribution gate applies, so a public key can only ever receive data that is licensed for redistribution. Provider-licensed data is absent from the public surface entirely — not thinned, not masked, absent — which is why the tool catalog and the REST reference are generated from what a public key can actually see.
Sending the key
Both surfaces read the same header:
X-API-KEY: adk_...For MCP clients the header goes in the server config — the Quickstart has the block for each client. A request with no key, an unknown key, or a revoked key is rejected by the middleware before dispatch:
{ "error": { "code": "unauthorized", "message": "missing or invalid API key" } }Over REST the header goes on every request. A complete authenticated call, taken from the published specification:
curl --fail --silent --show-error \
--header "X-API-KEY: adk_..." \
"https://api.agentdatasets.com/v1/banks/financials?cert=1"Limits a key carries
Two limits apply, and they are different things:
- A per-key request rate, measured in a short sliding window. The dashboard shows each key's limit and its current-window usage side by side, so you can see a client approaching it before it trips. Exceeding it returns
rate_limited. - A per-account monthly quota across every key the account owns. Exceeding it returns
quota_exceeded, and the error carries the instant the window resets.
Both codes are in the error reference with their HTTP statuses and their MCP rendering. Neither is the same as upstream_rate_limited, which means a data provider throttled one of our connectors rather than us throttling you.
| Code | HTTP | How it reaches an MCP client |
|---|---|---|
| rate_limited | 429 | emitted by auth middleware before tool dispatch (+ Retry-After) |
| quota_exceeded | 429 | emitted by auth middleware before tool dispatch (+ Retry-After, reset_at) |
OAuth discovery
The hosted MCP endpoint advertises OAuth 2.1 protected-resource metadata at /.well-known/oauth-protected-resource, and an unauthenticated request comes back with a WWW-Authenticate challenge pointing at it — so a client that speaks OAuth discovery will find the authorization server. Self-serve OAuth onboarding is not open yet, though. Until it is, use an API key from the dashboard; that is the supported path for both surfaces.
Keeping keys out of trouble
- A key is a bearer credential: anything holding it can spend your quota. Keep it out of source control, out of client-side bundles, and out of anything a browser can read.
- Give each client its own key. Per-key usage is visible in the dashboard, so a noisy or leaked integration can be identified and revoked without disturbing the others.
- Revoke rather than delete-and-forget. A revoked key fails closed immediately on both surfaces.