API reference
Public read-only endpoints at https://api.zebra.pub. All responses are JSON; amounts are wei strings (1 BNB = 10¹⁸ wei) and times are Unix seconds.
Rate limits and caching
| Item | Rule |
|---|---|
| Most endpoints | 120 requests per minute per IP |
/api/flap*, /api/meta, /api/tx*, /api/bind/* | 30 per minute per IP (reads the chain, simulates a call or calls Flap) |
| Over the limit | 429 with retry_after_s in the body |
| Caching | Responses carry cache-control and x-cache: HIT/MISS; the same URL returns the same data within its cache window |
| Endpoint | Cache |
|---|---|
/api/launches, /api/launch/*, /api/recent | 3 s |
/api/me/*, /api/airdrops* | 5 s |
/api/stats, /api/profile/* | 10 s |
/api/dao, /api/hot | 15 s |
/api/name/*, /api/address/*, /api/search | 30 s |
/api/flap, /api/flap/estimate, /api/vanity, /api/timeline | 60 s |
/api/binding/* | 3 seconds |
/api/decode | 5 minutes |
/api/health, /api/meta, /api/admin/*, /api/tx*, /api/bind/* | not cached |
For anything more frequent, read the on-chain events directly (see Contracts).
Rounds
GET /api/launches
List rounds. By default open rounds come first, then full, then launched; each group is ordered by the sort.
| Param | Notes |
|---|---|
sort | progress (default, fill progress) · people · amount |
stage | Open · Full · Launched · Done · Refunding; all if omitted |
limit | default 50, max 200 |
Each item has: address, creator (the address that sent the transaction), creator_id (the Agent ID the issuer acts for: itself, or the ID it is bound to; null if none), creator_name, template_id (game template, 0 = Classic), binding (binding contract this round locked in), kind (TaxV6/TaxV6Vault/PlainV7), name, symbol, meta, pool, quote_token, slip_bps, fee_bps, buy_tax_bps, sell_tax_bps, min_per_id, max_per_id, target, raised, left_bnb, progress (0–1, fill progress), subscribers, stage, created_time, filled_at, launched_at, graduated_at (when it graduated on Flap and liquidity moved to the DEX), token, spent, tokens_bought, fee_charged.
GET /api/launch/:addr
All fields for one round, plus its current subscribers (subscribers: who is the address that paid and receives, id the Agent ID it counts for, name that ID's name; with a bound wallet who ≠ id), exits and settlements, and stats:
| Field | Notes |
|---|---|
first_sub_time, exits, exited_people | first subscription time; number of exits and of people who exited |
distributed, distributed_at | people paid out at distribution, and when it finished |
graduated_at, dex_pool | graduation time and DEX pool |
holders | addresses holding the token after launch (replayed from its on-chain transfers) |
real_holders, real_share | how many of them hold an Agent ID, and their share of the supply (0–1) |
top10_share | share of the 10 largest holders, leaving out contracts (bonding curve, DEX pool, the round) unless the contract itself holds an Agent ID |
GET /api/launch/:addr/wall
Name wall: subscription events (subscribe, top up, exit). limit defaults to 100, max 500.
GET /api/me/:addr
addr may also be a name (with or without .ai); looking needs no wallet. An address's Agent ID, rounds it joined or created, its amounts, and the DAO airdrops it received (airdrops: one row per batch and token, with amount, delivered or not, transaction hash). Joined rounds also carry my_balance (current holding), my_since (when this holding began), my_received, my_refunded and my_exit_back; my_payee is the address that actually paid and receives in that round (the bound wallet when the ID joined through it). For an Agent ID, rounds its bound wallet joined for it are listed too. binding is the first three fields of /api/binding below. profile is as below.
GET /api/profile/:id
Name-card data; id is a name (with or without .ai) or an address. profile has joined (rounds joined), at_launch (rounds still in at launch), created, holding (launch tokens still held), hold_days (days the longest current holding has lasted), airdrops (airdrop batches received), early (among the first 50,000 claims) and pending_airdrops (airdrops being sent but not yet delivered, summed per token).
GET /api/hot?limit=10
Real-person leaderboard: open rounds by current subscribers, launched ones by holders with an Agent ID (real_people), most first, up to 50.
Wallet binding
GET /api/binding/:who
who is an address or a name. Returns:
| Field | Meaning |
|---|---|
contract | binding contract new rounds use |
wallet | when who is an Agent ID: its bound wallet (address, bound_at, tx), or null |
id | when who is a wallet: the Agent ID it acts for (address, name, bound_at, tx), or null |
next_bind_at, nonce | Agent ID: earliest time it may bind again (0 = now), current signature nonce |
wallet_free_at | wallet: earliest time it may be bound (0 = now) |
history | last 50 binding events: kind (bound / unbound / revoked), id_addr, wallet, detail (how it was unbound: wallet / id / id_signature / replaced), block_time, tx_hash |
Agent hand-off (order codes)
The Agentic Wallet only works through chat. These endpoints prepare and check a transaction or an authorization to sign, store it under a 6-character code (valid 30 minutes, fetched once) for the Agent to run with the Zebra skill. They only ever produce calls to Zebra round contracts or the binding contract, never token approvals or transfers.
POST /api/tx
{ "action": "subscribe", "launch": "0x…", "from": "0x…", "amount": "0.05" }| Field | Meaning |
|---|---|
action | subscribe (subscribe or top up) · exit · claim · refund · withdraw · withdraw_tokens |
launch | round contract |
from | the address that will send it (Agentic Wallet or bound wallet) |
amount | BNB to subscribe (or amount_wei); subscribe only |
lang | optional; en gives an English summary (default Chinese); /api/bind/request takes it too |
Checks, in order: the round exists and is at the right stage; which Agent ID from acts for; whether that ID already joined this round from another address; the amount against the per-person limits and the room left; finally a simulation from from. On failure: 400 with {"error": "reason (Chinese)", "code": "ErrorCode"}. On success:
{ "kind": "tx", "code": "NHJQU3", "expires_at": 1793008991, "chain_id": 56, "action": "subscribe",
"launch": "0x…", "from": "0x…", "to": "0x…", "value": "50000000000000000", "value_bnb": "0.05",
"data": "0x8f449a05", "function": "subscribe()", "summary": "…" }POST /api/bind/request
{ "name": "alice", "wallet": "0x…" } // bind
{ "action": "unbind", "name": "alice" } // unbind the current walletChecks the name, cooldowns and whether the wallet is taken, and returns the EIP-712 authorization to sign: kind: "sign", code, signer (the Agent ID address), wallet, binding, deadline, digest (the contract's own hash, to check the signature against), summary, and typed_data (domain Zebra Binding / 1 / 56 / binding contract, primaryType Bind or Unbind; ready for eth_signTypedData_v4).
GET /api/tx/:code
The Agent fetches either of the above with the code (verbatim, typed_data keys in field order). Once only: again returns 410 (CodeUsed); expired returns 410 (CodeExpired); unknown returns 404.
Error codes
Contracts revert with error codes, which an Agent's preview may show only as hex.
| Endpoint | Meaning |
|---|---|
GET /api/decode?data=0x… | turns revert data (or a whole error message containing it) into words: code, selector, text (Chinese) |
GET /api/errors | every error code with its 4-byte selector and text |
Zebra DAO
GET /api/dao
Total income (launch_fees, exit_fees, swept), recent flows, and the multisig safe: address, live BNB balance (bnb_wei), signers (owners) and threshold.
totals: tax commission (commission_bnb), donations (donations_bnb, donations count including token gifts), spending (spent_bnb, split into token buys spent_buy_bnb and other spent_other_bnb), airdrop_batches, airdrop_people.
ledger: the multisig's inflows and outflows, newest first. Each entry has dir (in / out), kind, time, tx, n (transfers) and amounts:
kind | Meaning |
|---|---|
launch_fee · exit_fee · sweep | launch fees, exit fees (merged per round and day), swept dust |
tax_commission | Flap's tax commission from a tax token (symbol = the source token; paid in a pool token it carries token_symbol and decimals) |
donation | BNB sent straight to the multisig |
token_in | tokens sent to the multisig (token_symbol, decimals) |
buy · spend | BNB sent by the multisig: to Flap or PancakeSwap counts as a token buy, anything else as spending (each MultiSend entry counted) |
airdrop · token_out | tokens sent by the multisig, one entry per transaction (tokens lists each token); entries matched to an airdrop batch carry batch_id and batch_name |
GET /api/airdrops
Published airdrop batches (sending, done, cancelled), newest first. Each has id, name, note, rule (all_ids / launches / custom), tokens (per token: token, symbol, decimals, total_wei, sent_wei), recipients, sent (people fully paid), transfers, transfers_sent, status (active / done / cancelled), created_at, published_at, done_at, snapshot_block.
GET /api/airdrops/:id
One batch and its recipients, paged. Params: page, size (max 500), q (address or name prefix), status (pending still owed something / sent fully paid). Each recipient has address, handle, status (pending / partial / sent) and items (one per token: pos, amount_wei, status, tx_hash, sent_at).
GET /api/airdrops/:id/csv
The full list as CSV, one row per recipient and token, with delivery status.
Flap parameters
GET /api/flap
The zebra field holds the factory's current settings for new rounds: factory, binding, fee_bps, min_target / max_target (raise range, wei), min_per_id_floor, official_vaults_only, twap_window, paused, and templates (each with id, name, impl, status, ready_at; active ones carry creation_cost, what creating a round costs).
The rest are Flap's current parameters read from chain: Portal version, trading fee (bps), BNB curve (r, h, k, graduation reserve), and enabled pools with their average-price routes. A pool is enabled when Flap allows BNB swaps into it and every pool on its route keeps a full 1,800 observations of price history (oracle_ready); otherwise the factory refuses new rounds on it.
GET /api/flap/estimate?progress=58&pool=BNB
Estimate the raise needed to reach a curve progress after launch, on the BNB curve. progress is in (0, 100]; non-BNB pools include 20% headroom at 100%.
Logo upload
POST /api/meta
Used when creating a launch: uploads the token logo and its details to Flap, pinned on IPFS, and returns a cid. That cid is the token's meta field, which Flap and zebra.pub both read the logo and links from. Browsers can't call Flap's upload endpoint directly because of cross-origin rules, so our backend forwards it.
The request is multipart/form-data:
| Field | Required | Notes |
|---|---|---|
image | yes | Logo: PNG, JPEG, WebP, SVG or GIF, up to 3 MB (same as Flap); square, 512×512 or more, is best |
description | no | Token description, up to 256 characters (same as Flap) |
website | no | Website link |
twitter | no | X link |
telegram | no | Telegram link |
Success returns 200:
{ "cid": "bafkreictuhft3yl5icnswbh52nhth3sjjcgrk7d4qnxglhuqehwgfznw3q" }The cid points to a JSON document (description, website, twitter, telegram, image, …) whose image is the picture's own CID. You can view it through Flap's gateway, e.g. https://flap.mypinata.cloud/ipfs/<cid>.
| Status | Meaning |
|---|---|
400 | No image, image over 3 MB or not a supported format, description over 256 characters, or a malformed form |
429 | Rate limited (30 per minute per IP, shared with /api/flap*) |
502 | Flap's upload failed or returned no cid (the body's detail carries Flap's error) |
Example:
curl -X POST https://api.zebra.pub/api/meta \
-F "image=@logo.png;type=image/png" \
-F "description=One-line pitch" \
-F "website=https://example.com" \
-F "twitter=https://x.com/example"Uploads are public and permanent on IPFS and can't be deleted, so only upload the material meant for the token.
Other
The admin endpoints under /api/admin/* are for DAO multisig signers only (wallet sign-in) and aren't listed here.
Agent ID
| Endpoint | Notes |
|---|---|
GET /api/stats | Total Agent IDs and growth |
GET /api/name/:handle | Look up by name (without .ai) |
GET /api/address/:addr | Look up by address |
GET /api/search?q= | Name prefix search, up to 20 |
GET /api/recent?limit= | Latest registrations, default 50, max 200 |
GET /api/timeline?bucket=3600&hours=72 | Registrations over time |
GET /api/vanity | Three-character names, lucky-number names, earliest names |
GET /api/health | Service status and cache stats |