REST API reference
Every MCP tool is a thin wrapper around a REST endpoint on api.blockchainacademics.com. If you’d rather call HTTP directly — a non-MCP integration, a server-side pipeline, an internal job runner — the same API key and the same canonical envelope apply.
Live interactive Swagger: api.blockchainacademics.com/docs. Raw OpenAPI JSON: api.blockchainacademics.com/openapi.json.
Base URL
https://api.blockchainacademics.comOverride with BCA_API_BASE env var (MCP server) or a direct baseURL config flag (custom HTTP client) when hitting staging.
Authentication
Every request carries the API key in a header:
X-API-Key: bca_live_xxxxxxxxxxxxxxxxOr, equivalently, using the Authorization convention:
Authorization: Bearer bca_live_xxxxxxxxxxxxxxxxThe server accepts either. Get a key at brain.blockchainacademics.com/pricing.
Never commit your key. The MCP-adjacent env pattern (BCA_API_KEY in a shell profile or Claude Desktop config) applies here too.
Response envelope
Every 2xx response returns the canonical three-key envelope:
{
"data": { "...": "endpoint-specific payload" },
"attribution": {
"citations": [
{
"cite_url": "https://blockchainacademics.com/...",
"as_of": "2026-04-22T10:12:00Z",
"source_hash": "sha256:abc123..."
}
]
},
"meta": {
"status": "complete",
"request_id": "req_01HABCDEF0123456789ABCDEFG",
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"startCursor": null,
"endCursor": null
}
}
}Full field-by-field breakdown: Response envelope. Citation semantics: Citations.
Response headers
Every response carries:
X-Request-ID: req_01HABCDEF0123456789ABCDEFG
X-RateLimit-Limit: 1200
X-RateLimit-Remaining: 1187
X-RateLimit-Reset: 1713787200X-Request-ID mirrors meta.request_id. Log it with every call. X-RateLimit-Reset is Unix epoch seconds.
Core endpoint map
| Endpoint group | Path | Who uses it |
|---|---|---|
| Articles / corpus | /v1/articles/... | search_news, get_article, get_as_of_snapshot |
| Entities | /v1/entities/... | get_entity, list_entity_mentions |
| Topics | /v1/topics | list_topics |
| Academy | /v1/academy/... | get_explainer |
| Market | /v1/market/... | get_price, get_ohlc, get_market_overview, get_pair_data |
| On-chain | /v1/onchain/... | get_wallet_profile, get_tx, get_token_holders |
| Sentiment | /v1/sentiment/... | get_sentiment, get_social_pulse, get_fear_greed |
| Proprietary indicators | /v1/indicators/... | get_coverage_index, get_narrative_strength, … |
| Agent jobs | /v1/agents/... | generate_due_diligence, translate_contract, get_agent_job |
| Directories | /v1/directories/... | list_stablecoins, list_yields, list_vcs, list_jobs, … |
| Fundamentals | /v1/fundamentals/... | get_tokenomics, get_audit_reports, compare_protocols |
| Chain-specific | /v1/chains/... | get_solana_ecosystem, get_l2_comparison |
| Regulatory | /v1/regulatory/... | get_regulatory_status, track_sec_filings, get_mica_status |
| Security | /v1/security/... | scan_contract, check_phishing_domain, get_bug_bounty_programs |
| History time-series | /v1/history/... | get_history_prices, get_history_sentiment, … |
| Services (revenue, POST) | /v1/services/... | book_kol_campaign, request_custom_research, submit_listing |
| Studio (BCA leads) | /v1/studio/... | Internal — powers studio.blockchainacademics.com contact form |
For exact parameters, request bodies, and response shapes of every endpoint, see the live Swagger. This page intentionally does not duplicate it — the OpenAPI JSON is the source of truth, and an auto-generated mirror drifts.
Example: search_news over HTTP
curl -s "https://api.blockchainacademics.com/v1/articles/search?q=circle+mica&limit=5" \
-H "X-API-Key: $BCA_API_KEY"Response:
{
"data": {
"items": [
{
"slug": "circle-mica-license",
"title": "Circle secures full MiCA license",
"published_at": "2026-04-18T14:02:17Z",
"summary": "Circle became the first USD stablecoin issuer…",
"entities": ["circle", "mica", "european-union"]
}
],
"total": 1
},
"attribution": {
"citations": [
{
"cite_url": "https://blockchainacademics.com/article/circle-mica-license?src=custom&utm_medium=http&utm_campaign=search_news",
"as_of": "2026-04-21T09:31:22Z",
"source_hash": "sha256:a9f1b7de2c4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1"
}
]
},
"meta": {
"status": "complete",
"request_id": "req_01HABCDEF0123456789ABCDEFG",
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"startCursor": null,
"endCursor": null
}
}
}Example: list with pagination
Collection endpoints paginate via meta.pageInfo — Linear / GraphQL cursor style.
curl -s "https://api.blockchainacademics.com/v1/articles/search?q=ethereum&limit=2" \
-H "X-API-Key: $BCA_API_KEY"{
"data": {
"items": [
{ "slug": "eth-pectra-mainnet", "title": "Pectra goes live on Ethereum mainnet", "published_at": "2026-04-20T12:00:00Z" },
{ "slug": "eth-staking-rate", "title": "ETH staking yield falls below 3%", "published_at": "2026-04-19T08:31:00Z" }
],
"total": 147
},
"attribution": {
"citations": [
{
"cite_url": "https://blockchainacademics.com/search?q=ethereum&src=custom&utm_medium=http&utm_campaign=search_news",
"as_of": "2026-04-22T10:12:00Z",
"source_hash": "sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3"
}
]
},
"meta": {
"status": "complete",
"request_id": "req_01HABCDEF0123456789ABCDEFK",
"pageInfo": {
"hasNextPage": true,
"hasPreviousPage": false,
"startCursor": "c_01HABCDEF000000000000AAAA",
"endCursor": "c_01HABCDEF000000000000BBBB"
}
}
}To fetch the next page, pass the endCursor as after:
curl -s "https://api.blockchainacademics.com/v1/articles/search?q=ethereum&limit=2&after=c_01HABCDEF000000000000BBBB" \
-H "X-API-Key: $BCA_API_KEY"Cursor format is server-internal — never parse or construct it client-side.
Example: degraded response (partial)
{
"data": {
"candles": [
{ "t": "2026-04-22T09:00:00Z", "o": 67200.5, "h": 67450.0, "l": 67100.0, "c": 67380.2 },
{ "t": "2026-04-22T10:00:00Z", "o": 67380.2, "h": null, "l": null, "c": null }
]
},
"attribution": {
"citations": [
{
"cite_url": "https://blockchainacademics.com/market/btc?src=custom&utm_medium=http&utm_campaign=get_ohlc",
"as_of": "2026-04-22T10:12:00Z",
"source_hash": "sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3"
}
]
},
"meta": {
"status": "partial",
"request_id": "req_01HABCDEF0123456789ABCDEFI",
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"startCursor": null,
"endCursor": null
},
"diagnostic": {
"reason": "Upstream returned 502 on 1 of 2 candles.",
"vendor": "coingecko",
"upstream_status": 502
}
}
}Errors
Errors return HTTP 4xx/5xx and an error body — they do not reuse the envelope shape.
{
"error": {
"code": "BCA_BAD_REQUEST",
"message": "`limit` must be between 1 and 200.",
"request_id": "req_01HABCDEF0123456789ABCDEFG"
}
}| HTTP | error.code | Meaning |
|---|---|---|
| 400 | BCA_BAD_REQUEST | Validation failure. |
| 401 | BCA_AUTH | Missing / invalid key. |
| 403 | BCA_TIER_LOCKED | Caller below required tier for the tool. |
| 404 | BCA_NOT_FOUND | Entity / article / slug not in corpus. |
| 429 | BCA_RATE_LIMIT | Rate-limited. Honor Retry-After header. |
| 5xx | BCA_UPSTREAM | Backend failure. Retry with backoff. |
Every error body carries request_id. It matches the X-Request-ID response header. Include it in any support ticket.
Integration-state responses are not errors. If a tool’s upstream isn’t wired in yet, the response is HTTP 200 with meta.status: "unseeded" and a meta.diagnostic block — see Envelope → Status decision tree.
Pagination
List endpoints accept:
| Param | Default | Max | Notes |
|---|---|---|---|
limit | 10–50 | 200 | Per-endpoint max documented in Swagger. |
after | — | — | Opaque cursor from the previous page’s endCursor. |
before | — | — | Opaque cursor for backward pagination (where enabled). |
Inspect meta.pageInfo on every response to decide whether to keep walking. Do not assume data.items.length < limit means you’re done — some endpoints return up to limit per page even when more exist.
Rate limits
Rate limits are per-key, not per-IP. Live state lives in headers, not the body:
X-RateLimit-Limit: 1200
X-RateLimit-Remaining: 1187
X-RateLimit-Reset: 1713787200| Tier | Requests / minute | Monthly quota |
|---|---|---|
| Free | 60 | 2,000 calls |
| Starter | 300 | 20,000 calls |
| Pro | 1,200 | 200,000 calls |
| Team | 3,000 | 1,000,000 calls |
| Enterprise | custom | custom |
See Tiers & quotas for the full breakdown.
Webhooks (v0.4)
Webhook delivery for monitor_keyword and agent-job completion lands in v0.4. Webhook payloads will use the same canonical envelope shape (including meta.request_id for idempotency). Spec will live here when it ships.
Next
- Live Swagger — interactive, click-to-try.
- OpenAPI JSON — for codegen.
- Response envelope — field-by-field breakdown.
- Citations — why
citations[]is an array. - Tool reference — MCP-flavored view of the same surface.