Skip to main content
Nexus serves a Blockfrost-compatible surface at https://nexus.gerowallet.io/api/v0. Point an unmodified Blockfrost SDK at that base URL and pass your Nexus nxs_ key as the project_id, and your existing calls keep working against Blockfrost’s request and response shapes.
This page is for developers arriving from Blockfrost. If you already call the native Nexus API at /api/... with an X-Api-Key header, nothing here changes for you and there is nothing to do. The compatible surface is an additional entry point, not a replacement.

The one-line change

Two changed lines in @blockfrost/blockfrost-js: your project ID becomes your Nexus key, and customBackend points at /api/v0.
That is the whole migration. Same SDK, same method calls, same response shapes.
project_id is accepted only on /api/v0, and it carries the same nxs_ key you would use natively. X-Api-Key also works on this surface, and an explicit X-Api-Key wins if a request sends both. See Authentication.

What works

Most of the Blockfrost read surface is served today:
  • Blocks and transactions
  • Addresses
  • Accounts, through the stake-address sub-resources
  • Assets, by asset ID and by policy ID
  • Epochs
  • Scripts
  • Transaction metadata
  • Stake pools: the pool list, /pools/retired, /pools/retiring, and the per-pool sub-resources metadata, relays, updates, blocks, votes and delegators
The exceptions inside those areas are listed below, in full.
/pools/{pool_id}/delegators is answered from Nexus’s own data rather than forwarded, so it behaves slightly differently from hosted Blockfrost. On preview and preprod it lists the pool’s current delegators, read when you ask: in Blockfrost’s own order (oldest delegation first, with order=desc for newest first), with each account’s current stake, UTxO plus unwithdrawn rewards, and no paging depth limit. Two kinds of account are treated differently from hosted Blockfrost’s list. In both, Nexus agrees with hosted Blockfrost’s own /accounts/{stake_address}:
  • An account that deregistered after delegating and later registered again without delegating again is not listed. Hosted Blockfrost lists it, although its own /accounts/{stake_address} gives it pool_id: null.
  • An account that deregistered and re-registered in one transaction, then delegated to the pool, is listed. Hosted Blockfrost omits it, although its own /accounts/{stake_address} names the pool.
On preprod, rewards come from Nexus’s indexer’s own reward calculation, which for some accounts runs up to a few tens of lovelace per epoch above the ledger’s. Such an account’s live_stake can read slightly higher than on hosted Blockfrost; the list and its order are unaffected.Mainnet has live per-delegator data too, in the same order, but /api/v0 does not serve mainnet keys yet; the native GET /api/pools/{poolId}/delegators serves live mainnet figures now. If that live data is stale, or the current read is unavailable, this endpoint falls back to the stake snapshot. There, rows are ordered by stake address, not by the blockchain’s own order, so page 1 holds a different set of delegators than hosted Blockfrost returns. order=desc reverses that address ordering, which is the opposite of the key that exists there, not of Blockfrost’s chain order. Paging reaches offset 2000, which is page 21 at count=100, and deeper pages answer 400. For the full list without a depth limit, use the native GET /api/pools/{poolId}/delegators and follow its nextCursor.
/addresses/{address}/transactions and /addresses/{address}/total are answered from Nexus’s own index of the chain rather than forwarded, including for the busiest addresses, which page in milliseconds. Both accept the payment-credential forms Blockfrost does (addr_vkh…, script…) and return the transactions or totals of every address under that credential. from and to follow hosted Blockfrost’s rules, including which malformed values it refuses. /total sums an address’s entire history, so for the largest addresses it can take up to about 20 seconds: if it cannot finish in that time the answer is 503 with a Retry-After header, and a retry usually succeeds because the first attempt warmed the index. On preview, for an address with more than 3,000,000 outputs, /total answers 400, “Address is too large to compute totals for.”, the refusal Blockfrost’s own server software defines for this case; hosted Blockfrost has no such limit configured. No preview address is that large today: the largest, about 1.9 million outputs, is answered in about 8 seconds once its index is warm, with the same totals hosted Blockfrost returns. The limit is set per network, and it is 1,000,000 outputs on the networks /api/v0 does not serve yet.

What is not available yet

Guarded endpoints

These paths return a Blockfrost-shaped 503 with a Retry-After header. The cause is unbounded per-request aggregation in the upstream indexer, so each path is guarded individually and is released on its own as the matching upstream fix lands. A pool or epoch that does not exist still gets Blockfrost’s 404 on /pools/{pool_id}, /pools/{pool_id}/history and /epochs/{number}/previous, so only an id that exists gets the 503. In the rare moment the existence check cannot answer, such as while the chain index it reads catches up to the newest block or is unavailable or busy, the response is the 503 instead. The same goes for a request whose query Nexus does not check itself, such as one that repeats from or to (a 500 on Blockfrost). Tracked upstream in bloxbean/yaci-store: #1078, #1080, #1083, #1089.

Not supported by design

  • Mempool endpoints.
  • Blockfrost’s account-usage metrics endpoints.
These are Blockfrost product surface rather than chain data, and Nexus does not serve them.
/accounts/{stake_address}, the account root, is also not served yet. That one is an upstream gap rather than a Nexus decision, tracked in bloxbean/yaci-store#1077. The sub-resources under a stake address are served.

Error responses

On /api/v0, Nexus returns Blockfrost’s error envelopes rather than the native Nexus error body, so an unmodified SDK parses them without changes. Every envelope is UTF-8. A key that is present but refused returns 403:
A request with no key at all returns 403 with a different message, because a missing header and a wrong key need different fixes:
The rest:
Ids are validated the way hosted Blockfrost validates them, with its messages: a stake address or address for another network, a bad bech32 checksum, an asset that is not 56 to 120 hex characters, a malformed block hash or number, an out-of-range metadata label or epoch, and bad paging on a paged route are all 400. Like Blockfrost, lookups are case-sensitive while the format check is not, so an all-uppercase id is a 404 even when its lowercase form exists. Credentials are the exception, again as on Blockfrost: an addr_vkh or script payment credential, a hex pool id, and any id on /accounts/{stake_address}/transactions are read in either case. A hex pool id is read two ways, again as on Blockfrost: on /pools/{pool_id} and /pools/{pool_id}/history an odd-length one is a 400, while every other pool path drops a trailing odd hex digit, so a 57-character id names the pool of its first 56. The node’s wording for a rejected transaction differs from hosted Blockfrost’s, because the two run different submission software, but both put the reason in message.
A well-formed id that has never appeared on chain is a 404, as on Blockfrost, not an empty list. That covers a stake address, an address or payment credential, a policy, a pool or a script. In the rare moment the existence check cannot answer, such as while the chain index it reads catches up to the newest block, the response is the empty list instead. An id that exists but has nothing to list, such as a stake address with no withdrawals or an address whose outputs are all spent, is 200 with []. /accounts/{stake_address}/transactions accepts the same credential forms Blockfrost does (stake_vk, stake_vkh, script, or a stake address in either case), and each returns the transactions of the stake address it names.
These shapes apply to /api/v0 only. The native /api/... surface returns the Nexus error envelope, with timestamp, status, error, message, path and requestId. See Error Handling.

Rate limits and quota

One key, one tier, one set of limits. Your nxs_ key carries the same plan tier on both surfaces, and traffic through /api/v0 counts against the same monthly quota and the same per-second rate limit as native traffic. There is no separate compatibility allowance and no second key to manage. The per-tier numbers are on Rate Limits. A 429 on /api/v0 uses the Blockfrost envelope described above and still sends Retry-After, so an SDK’s built-in backoff behaves the way it does against hosted Blockfrost.
Guarded 503 responses currently consume quota. That is the behaviour today, and it is under review.

Moving individual calls to the native API

Optional, and only where it pays. Once you are running on Nexus, individual calls can move to the native API, which has endpoints that answer in one request what the Blockfrost surface needs many requests to assemble. A wallet page is the clearest case. Built through the Blockfrost SDK it takes 42 calls; the native GET /api/addresses/{address}/transactions/history answers the same page in 1. This is a quota and code-structure argument, not a latency one. What changes is that the page spends 1 request of your monthly quota instead of 42, and you maintain a single call instead of a fan-out.
Nothing forces this. A working Blockfrost integration on /api/v0 can stay exactly as it is.

Stability

The base URL and your key are the contract. https://nexus.gerowallet.io/api/v0 plus your nxs_ key is what you integrate against, and that pair does not change. What answers behind that URL is ours to improve. Backend changes never require action on your side: no new URL, no key rotation, no forced SDK upgrade.

Next steps

Authentication

project_id, X-Api-Key, and how keys are scoped

Rate Limits

Per-tier quotas and per-second limits

Error Handling

The native error envelope and how to branch on it

API Reference

The native Nexus surface, endpoint by endpoint