ReferenceREST API

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.

Base URL

https://api.blockchainacademics.com

Override 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_xxxxxxxxxxxxxxxx

Or, equivalently, using the Authorization convention:

Authorization: Bearer bca_live_xxxxxxxxxxxxxxxx

The 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: 1713787200

X-Request-ID mirrors meta.request_id. Log it with every call. X-RateLimit-Reset is Unix epoch seconds.

Core endpoint map

Endpoint groupPathWho uses it
Articles / corpus/v1/articles/...search_news, get_article, get_as_of_snapshot
Entities/v1/entities/...get_entity, list_entity_mentions
Topics/v1/topicslist_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"
  }
}
HTTPerror.codeMeaning
400BCA_BAD_REQUESTValidation failure.
401BCA_AUTHMissing / invalid key.
403BCA_TIER_LOCKEDCaller below required tier for the tool.
404BCA_NOT_FOUNDEntity / article / slug not in corpus.
429BCA_RATE_LIMITRate-limited. Honor Retry-After header.
5xxBCA_UPSTREAMBackend 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:

ParamDefaultMaxNotes
limit10–50200Per-endpoint max documented in Swagger.
afterOpaque cursor from the previous page’s endCursor.
beforeOpaque 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
TierRequests / minuteMonthly quota
Free602,000 calls
Starter30020,000 calls
Pro1,200200,000 calls
Team3,0001,000,000 calls
Enterprisecustomcustom

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