MUCHALPHAIntel for Robinhood Chain
Tape Trac Record Get a Pass Agents Log in
—
records on the ledger
—
—
calls on the ledger
—

Choose how your agents access the feed.

1Free APIno key, no account · try it before you pay

The public endpoints take no key and open to anyone. You can integrate against them, and against the Trac Record, before paying a cent — this is the free tier the access model serves.

authnone · public GET endpoints what you getlocked stubs, a random handful of full samples, and call commitments · a stub opens after its delay window, or now with a pass orderrows come sorted by arrivedAt, newest first — the payload says so in sortKey. ts is when the thing happened, which for news is often days earlier, so sorting on it scrambles the tape pagingsend the answer's nextBefore back as ?before= · the last page carries nextBefore: null, so a walk never needs a trailing empty request · a before we cannot read is 400 bad_cursor, and omitting it starts at the newest row countersrows = lockedIntel + openCalls + openRows · locked is the first two together and freeSamples is inside openRows, so summing all five double-counts · the payload repeats this in countsIdentity
shell
$ curl -s /api/public/tape?limit=3
$ curl -s /api/public/record
$ curl -s /api/public/status
$ curl -s '/api/public/proof?id=record-id'
/api/public/tapesignals by arrival, newest first · ?limit= ?before= · before takes nextBefore from the previous answer and pages backwards /api/public/recordresolved calls, hit rate, running score · ?limit= ?after= pages the resolved rows only, newest resolution first · after takes page.next_cursor from the previous answer · sending neither returns the whole listing, and the hit rate, the totals and the reconciliation are whole-record on every page /api/public/record/<id>one record by id · not window-scoped, so a from_records citation always resolves /api/public/statusfeed health, chain head, ledger queue /api/public/calibrationwhat the confidence words are worth, per bucket /api/public/proofthe commit window a record was SEALED into · ?id=<record> is the exact lookup, ?ts=<unix> resolves to the windows carrying records from that event bucket · a member still locked comes back as {sealed, leaf, unlockAtMs}, so the root rebuilds without its bytes /api/public/p2pthe identifiers a peer needs to attach
What the free tier actually returns
news & chain intela stub in realtime — when it happened, its coarse class, when it opens · the full record after the delay window callsthe commitment in realtime — asset, commit time, deadline, commit root, and claim, the law it is scored under (two_sided scores whether the price breaks out of a volatility window twice the committed threshold wide and not which side it breaks, directional scores the side) · direction, threshold and rationale open at the deadline, to everyone free samplesa deterministic fraction of explicitly approved record kinds opens immediately, marked freeSample · new record kinds default to paid · the same eligible record always draws the same way with a passevery record, in full, in realtime, on /api/live/* · nothing is stubbed
how it is withheldserver-side, by construction · a locked row is built from the fields it may carry, so what is withheld is never in the response — there is nothing to un-blur, and locked:true tells you which rows those are when it opensunlockAtMs on every locked row
two chain idsstatus.chainId is 4663, Robinhood Chain mainnet — the chain every record, block and reference on the tape comes from  wallet.chainId is 4663 as well — the pass payment rails run on Robinhood Chain mainnet, so that is the network your wallet connects to. Two fields because they answer different questions: one names where the data comes from, the other where your wallet has to be
2Direct APIHTTP and a bearer token · no install
Your key here

There is no signup. A human logs in with the wallet bound to a live pass and the main tape opens in full; an agent uses the one key shown after payment. That same key works on every paid route below — Direct API, MCP, P2P and the SDK. The free tier needs no key.

1 · buy/pass · pick a rail and how many days · — 2 · paysend the exact amount shown · the site watches for it 3 · collectthe key is shown once per issue · on the status read where your payment lands, and again on each recovery the key looks likemapt_… headerAuthorization: Bearer mapt_… store it thenonly its hash is kept here · nobody can show it to you again if you lose ityou keep the pass. Prove you paid and a new key is issued at /pass · the old one stops working, the remaining time is untouched how you prove itsign a challenge with the wallet that paid · on TAP (Bitcoin) send a small exact amount from the paying address instead, because that wallet's message signatures cannot be checked against it — you pay the Bitcoin network fees for that stolen keysame route · recovering evicts everything holding the old key, including your own other sessions
shell · poll for the key after paying
# poll every few seconds; stop when status leaves "pending"
$ curl -s /api/pass/status/p_REPLACE_WITH_PURCHASE_ID
# the first read after activation carries it, and only that read:
#   "claim": { "issued": true, "token": "mapt_…", "shownOnce": true }
# every later read returns no token at all.
Live endpoints — undelayed, one bearer token

Same response shapes as the public endpoints, so one parser reads either tier. since takes the cursor from the previous answer and returns only what is newer.

a passevery record in full and in realtime · get a pass price— how it is priced— network today—
shell
$ PASS=mapt_replace_with_your_token
$ curl -s -H "Authorization: Bearer $PASS" /api/live/tape?limit=20
$ curl -s -H "Authorization: Bearer $PASS" '/api/live/tape?since=0'
$ curl -s -H "Authorization: Bearer $PASS" /api/live/status
GET /api/live/tapeundelayed rows · ?limit= ?since= GET /api/live/recordresolved calls and hit rate · ?limit= ?after=, the same page rules as the public route GET /api/live/statusfeed health · delayed:false no pass401 auth_required wrong or lapsed403 no_active_pass · one answer for all of them rate limit60 requests/minute per pass · 429 rate_limited reader cap—
Binding a key

The token is a bearer credential: whoever holds it has the access. Bind a key and the pass follows the key instead. Two calls, and the text you sign is shown to you first.

shell · evm key (EIP-191 personal_sign)
$ curl -s -X POST /api/pass/claim/challenge \
    -H 'content-type: application/json' \
    -d '{"purchaseId":"p_0000000000000000000000000000dead","keyKind":"evm","address":"0x0000000000000000000000000000000000000000"}'
# sign the returned .challenge string verbatim, then:
$ curl -s -X POST /api/pass/claim/verify \
    -H 'content-type: application/json' \
    -d '{"keyKind":"evm","nonce":"REPLACE_WITH_NONCE","signature":"0xREPLACE_WITH_SIGNATURE"}'
shell · trac key (raw-bytes ed25519)
$ curl -s -X POST /api/pass/claim/challenge \
    -H 'content-type: application/json' \
    -d '{"purchaseId":"p_0000000000000000000000000000dead","keyKind":"trac","address":"testtrac1replace_with_your_address"}'
# sign .challenge verbatim: ed25519 over the raw bytes, no envelope, no pre-hash
$ curl -s -X POST /api/pass/claim/verify \
    -H 'content-type: application/json' \
    -d '{"keyKind":"trac","nonce":"REPLACE_WITH_NONCE","signature":"REPLACE_WITH_HEX","publicKey":"REPLACE_WITH_64_HEX"}'
noncesingle use · a replay is 403 bad_or_expired_nonce signing the payer keyrevokes the bearer token · any link you shared stops working key-bound over RESTnot accepted · an address is public, so it is not a credential
Streams and the reader cap

REST polling is stateless and holds no reader slot. A stream does: the SDK's WebSocket and the MCP feed tools open a reader session, and a pass has a fixed number of them.

who opens onethe SDK's WebSocket and the MCP feed tools, with your bearer token · you do not call the gate yourself the leasea reader slot is held until the stream closes or its 5-minute lease goes stale · the tools heartbeat for you applies tostreams · WS and MCP feed tools does not apply toREST polling · /api/live/* holds no slot over the cap429 concurrent_reader_cap

The pass gate and its session lease live on the pass service and are reached with your bearer token, not through this site — the browser has no route to them, on purpose: a gate that resolved a pass from a public address alone would be an open door.

Check the record yourself
what it doesrecomputes a record's id from the bytes that were hashed reads/api/public/tape and /api/public/proof · two GETs on this site walletnot used keysnot used writesnone installsnothing · node built-ins only file/verify.mjs · the bytes below, served as a file
Verify a record yourself · read it, then run it
verify.mjs
loading /verify.mjs…
shell
$ curl -O /verify.mjs
$ node verify.mjs 
canonical form—
3MCP servertools for an MCP client · stdio
Your key here
two free toolsno key · the Trac Record and sample signals answer without one the live feed toolyour pass key stdiothe key goes in the server's own environment · ALPHA_PASS_TOKEN streamable httpthe same key as the request's bearer token
mcp config · http transport · json
{
  "mcpServers": {
    "much-alpha": {
      "type": "streamable-http",
      "url": "http://127.0.0.1:8791/mcp",
      "headers": { "Authorization": "Bearer mapt_replace_with_your_token" }
    }
  }
}
1 · install
shell
$ npm install /sdk/much-alpha-sdk.tgz
2 · configure
transportstdio entrynode_modules/much-alpha-sdk/bin/much-alpha-mcp.mjs
mcp config · json
loading…
get_track_recordfree · limit after get_sample_signalsfree · limit type get_latest_signalspass · type beat since_ms limit get_creator_relationshipspass · creator cursor limit
ALPHA_PASS_TOKENyour pass token · the free tools run without it
Smoke-test the server without an MCP client
shell
$ printf '%s\n' \
    '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
    '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  | node ./node_modules/much-alpha-sdk/bin/much-alpha-mcp.mjs
4Plain P2Pthe sidechannel directly · no SDK

The SDK is a convenience over a public transport. If you would rather not run our package, run your own Trac Intercom peer and read the frames yourself: the identifiers below are served by this site so a copied snippet cannot go stale.

Your key here
the open channelno key · attach and read the announcement · discovery only the gated channelyour pass key, exchanged with the gatekeeper for an invite what you sendthe key, and your own peer's public key for the invite to be addressed to what you get backan invite for that peer, and the epoch key that opens frames or, key-boundsign a challenge with the key your pass is bound to — same answer, no bearer token in flight
shell · pass key in, invite out
# your own peer, over its local bridge, told you its public key
$ read -rsp 'Pass token: ' PASS_TOKEN; echo
$ curl -s -X POST http://127.0.0.1:8787/auth/agent/verify \
    -H 'content-type: application/json' \
    -H "Authorization: Bearer ${PASS_TOKEN}" \
    -d '{"peerPubkey":"REPLACE_WITH_64_HEX"}'
# -> { "authorized": true, "channel": "…", "invite": "…",
#      "epoch": { "id": …, "key": "…" }, "inviteExpiresAtMs": … }
no passauthorized:false with a reason · no invite is minted invite lifetimeshort, and renewed · access lapses rather than being withdrawn
1 · where the feed lives
subnetloading…

2 · the open channel

One channel is open to anyone: it carries a periodic cleartext announcement of what this service is and how to get into the gated one. It is an ephemeral frame, not a record — nothing on it is committed, hashed or scored.

announcement on the open channel · json
loading…
3 · the gated channel

The signal channel is invite-required and owner-write. The gatekeeper issues the invite, and only against an active pass: you sign a challenge with the key your pass is bound to, and send your own peer's public key so the invite can be addressed to it.

who issues itthe gatekeeper · never the peer what it checksa single-use nonce, your signature, and an active pass what you getan invite for your peer key, and the epoch key that opens frames revocationby expiry · invites are short-lived and renewed, so access lapses rather than being withdrawn
4 · joining is deferred, and that is not a failure

A join is answered only once the topic is genuinely announced on the swarm, which during peer bootstrap can take seconds. Announced means discoverable, not merely registered — so a reply that says registered, and a reply that never comes, are both retries. Neither is a joined channel, and neither is an error.

replywhat it meanswhat to do
joined · announced:trueon the swarmjoined
joined · announced:falseregistered, not announcedretry
no reply before your timeoutstill bootstrappingretry
error · …already…this peer is already injoined
error · anything elsethe invite did not carryget a fresh invite

Treating a timeout as success is the one failure mode worth naming: it leaves a client believing it is subscribed to a channel it was never announced on, and the feed simply looks empty for ever.

5 · a minimal join
join · js (node 22+, no dependencies)
loading…
6 · the frames

Every message on the signal channel carries one sealed record. Read it from the event's message field and pass that whole object to your decrypt step — the envelope around it has an id and a ts of its own, and they are not the record's.

envelope ida transport de-duplication id frame idthe record's content id envelope tswhen it was sent · milliseconds frame tsthe record's own time · seconds why it mattersthe frame's own values authenticate the ciphertext; taking them from the envelope makes every open fail
one event on the signal channel · json
loading…
plaintext—

What comes out is the canonical record — the same bytes the commit leaf was built from, so a frame you received live and a record you read off the ledger a week later hash to the same thing.

5SDKthe peer, the epoch key and a local socket, handled
Your key here
the keythe same pass key · the SDK does the gatekeeper exchange for you where it goesthe feed process's environment · ALPHA_PASS_TOKEN without onethe delayed public endpoints still answer · the live feed does not
The package
packagemuch-alpha-sdk source/sdk/much-alpha-sdk.tgz · served from this host requiresnode >= 22 registrynot published · install from the URL above
shell
# one process holds the epoch key, everything else reads its socket
$ node ./node_modules/much-alpha-sdk/bin/much-alpha-feed.mjs
$ node ./node_modules/much-alpha-sdk/quickstarts/ws.mjs
in-process · js
import { openFeed } from 'much-alpha-sdk';

const feed = await openFeed({ mode: 'auto' });
feed.on('record', (r) => r.type === 'call' && console.log(r.instrument, r.direction, r.threshold, r.deadline_utc));
feed.serve();                        // ws://127.0.0.1:8790
feed.latest({ type: 'call', limit: 10 });