For builders

The protocol

Everything a moeba is lives on the ledger in a form anyone can read: one URI, a handful of token Remarks, and thirty-two bytes of genome. This page lays the bytes out so a wallet, an explorer or a marketplace can read them without asking us — and gives the API for those who would rather ask.

Written for a reader who writes code. The same material for a keeper is in the whitepaper and How it works. Where this page and the ledger disagree, the ledger is right.

A rehearsal. This species runs on Xahau testnet before its release: the population may be wiped, the issuing account replaced and the rules changed without notice, and nothing born here carries over. Why → Found a fault? Tell us on X.

Where a moeba is

A moeba is a URIToken on Xahau issued by one account, the species: rMmx5nHzoVJAoMTFWkgCCMrZryTaD682tr on Xahau testnet. A URIToken from any other issuer is not a moeba, whatever its URI says; that check comes before any other. Three places hold everything:

One genetic model has ever been minted on chain: v0.1-32-deep, model byte 1. The URI reserves a byte for the model so a wider genome can be added later without touching a creature that exists; a reader that meets a model byte it does not know should say so rather than guess. Everything below describes v0.1-32-deep.

Numbers are big-endian throughout. Hex is upper-case where the ledger shows it; base64url is the RFC 4648 §5 alphabet, no padding, and a decoder must reject a string that does not re-encode to itself.

The identity URI

urn:creature:birth:2: followed by 52 bytes as base64url: 91 characters in all. A URIToken's URI is stored as hex on the ledger; decode the hex to ASCII first.

BytesFieldMeaning
0version02. Version 1 tokens (44-byte payload, prefix urn:creature:birth:1:) exist only on earlier testnet populations and carry no deadline or serial.
1model1-based index into the model table: 1 = v0.1-32-deep, 2 = v0.1-64 (reserved, never minted). 0 or above the table is invalid.
2kind0 founder, 1 born of two parents.
3generation0 for a founder; otherwise 1 + the greater parent's generation, saturating at 255.
4–7birthLedgeru32. The ledger in which the birth's randomness was fixed and its genome settled: the ledger of the draw, which c.audit/1 names too. For source 2 it is a moment after the source ledger.
8–9fertilityu16. Births this creature may parent in total. The count used so far is in c.use/1.
10–11rulesu16. The rules version; the profile's hash is in c.rules/1.
12–15maturityAtu32, ledger close time (seconds since the Ripple epoch, 2000-01-01). Mature when the current ledger's close time is at or past it. A founder's is in the past.
16–19serialu32. The admission number; monotonic, never reused, so a burned creature cannot be re-minted.
20–51commitment32 bytes. The hash of the validated request that committed this birth; never all zero. One birth per commitment.

The token id is Xahau's URIToken keylet — a SHA-512-half over the ledger-space prefix, the issuer's AccountID and the URI bytes — so the id is fixed the moment the URI is, and the species can retry a failed mint without producing a second token.

The records

Six Remarks by name. Each value begins with a version byte; a reader that meets a version it does not know reports it as unknown rather than parsing on assumption. Values are at most 256 bytes. The three immutable records and the URI are covered by the token's Digest.

RemarkWrittenLayout
c.birth/1at mint, immutable[0] version 02 · [1–2] development u16 · [3] parent count, 0 or 2 · [4–23] breeder AccountID, 20 zero bytes for a founder · [24–55], [56–87] the parents' token ids when count is 2 (P then Q; P supplies the child's first copy, Q its second) · then the genome, 32 bytes. 56 bytes for a founder, 120 for a birth. A version-1 record without the breeder exists only on earlier testnet populations.
c.audit/1at mint, immutable[0] version 01 · [1] source: 0 laboratory (never on a species deployment), 1 retired and never to be reused, 2 ledger-beacon, 3 consensus-rng · [2–5] the source ledger, u32: for consensus-rng the ledger of the capture fire, for ledger-beacon the ledger named at admission · [6–37] the entropy, 32 bytes. 38 bytes. For consensus-rng the entropy is the draw bound to the birth: SHA-512-half( "KIN/entropy/2\0" ‖ network id u32 ‖ issuer AccountID ‖ rules u16 ‖ commitment ‖ draw ledger u32 ‖ draw ), the same 108-byte layout, where the draw is the 32 bytes util_random returned to the clock (position 1) on the capture fire. That fire's metadata carries the ledger's random state (RandomData); with the fire's transaction id, the species' account and the clock's hook hash it gives the draw. Fetch the fire, recompute and compare. The draw ledger is always after the ledger of the request. For ledger-beacon the entropy is not that ledger's hash itself but the seed made from it: SHA-512-half( "KIN/entropy/1\0" ‖ network id u32 ‖ issuer AccountID ‖ rules u16 ‖ commitment ‖ source ledger u32 ‖ source ledger hash ), 108 bytes in, the rules and commitment as in the URI. Fetch the ledger, recompute and compare.
c.rules/1at mint, immutable[0] version 01 · [1–32] the profile hash. 33 bytes. The profile is the text that describes the rules of birth; the hash is in the Hook's own state too.
c.use/1by the species, after each birth it parents[0] version 01 · [1–2] births used, u16. Absent means zero on a token whose three immutable records are present; on an incomplete token it means unknown, and unknown is not fertile.
c.breed/1by the species at the keeper's request (F=05); removed at F=04[0] version 01 · [1–20] the owner who published, AccountID · [21–24] price per birth in drops, u32 · [25–28] expiry ledger, u32, 0 for none. 29 bytes. The terms bind only while the account named is the token's owner: a transfer closes the creature with no further write.
c.name/1by the species at the keeper's request (F=06), once[0] version 01 · [1–24] UTF-8, NUL-padded to 24 bytes. Trim trailing NULs. Not in the Digest: it says nothing about what the creature is.

The Digest. SHA-512-half( "KIN/digest/1\0" ‖ len(uri) ‖ uri ‖ len(birth) ‖ birth ‖ len(audit) ‖ audit ‖ len(rules) ‖ rules ), each length a u32, the URI as ASCII. It is fixed before the mint, so it cannot name the mint transaction; what it commits to is the identity and the three immutable records in one fixed order.

The genome

Thirty-two bytes: two haplotypes of 16 bytes, the first from parent P, the second from parent Q. Within a haplotype the 36 loci are packed at the bit offsets below, MSB-first — bit 0 of the haplotype is the top bit of its first byte — using 128 of 128 bits. A locus's value on haplotype h is the bits-wide unsigned integer at h × 128 + offset.14 loci are discrete and choose an allele from a table; the rest are quantitative and add up into 22 traits.

#OffsetBitsLocusKindAlleles (index: name, dominance, founder weight /256) or trait
Body (LG1)
003BODY_PLAN
Body plan
discrete0 elongate d3 w1121 compact d2 w802 discoid d1 w483 serpentine d0 w164 bifid (forked) d5 mutation-only5 colonial (lobed) d6 mutation-only6 polyp d7 mutation-only7 reserved
133SYMMETRY
Symmetry
discrete0 bilateral d2 w1601 radial3 (threefold radial) d1 w402 radial4 (fourfold radial) d3 w403 asymmetric d0 w164 radial5 (fivefold radial) d4 mutation-only5 spiral d5 mutation-only6 radial6 (sixfold radial) d6 mutation-only7 reserved
263REG_SEGMENT
Segment rule
discrete0 linear d1 w1281 doubled d2 w642 paired d3 w483 suppressed d0 w164 hyper d4 mutation-only5 fused d5 mutation-only6 reserved7 reserved
394SEGMENT_COUNT
Segment count
quantitativetrait SEGMENT_COUNT (Segment count)
4134ELONGATION
Elongation
quantitativetrait ELONGATION (Elongation)
5174TAPER
Taper
quantitativetrait TAPER (Taper)
6214BODY_SIZE
Body size
quantitativetrait BODY_SIZE (Body size)
7253HEAD_FORM
Head
discrete0 rounded d2 w1201 pointed d3 w722 flat d1 w483 crested d0 w164 horned d4 mutation-only5 double d5 mutation-only6 reserved7 reserved
8284HEAD_SIZE
Head size
quantitativetrait HEAD_SIZE (Head size)
Limbs and senses (LG2)
9323APPENDAGE_FAMILY
Limbs
discrete0 fins d2 w961 legs d3 w802 tentacles d1 w483 none d0 w324 spines d4 mutation-only5 wings d5 mutation-only6 frills d6 mutation-only7 reserved
10353REG_APPENDAGE
Limb placement
discrete0 per_segment (one per segment) d2 w1121 fixed (fixed count) d1 w962 terminal (at the ends) d3 w323 alternating d0 w164 radial_all (all around) d4 mutation-only5 none_reg (none) d5 mutation-only6 reserved7 reserved
11384APPENDAGE_COUNT
Limb count
quantitativetrait APPENDAGE_COUNT (Limb count)
12424APPENDAGE_LENGTH
Limb length
quantitativetrait APPENDAGE_LENGTH (Limb length)
13464APPENDAGE_SPREAD
Limb spread
quantitativetrait APPENDAGE_SPREAD (Limb spread)
14504BRANCHING
Branching
quantitativetrait BRANCHING (Branching)
15543TAIL_FORM
Tail
discrete0 tapered d2 w1281 forked d3 w642 blunt d1 w483 none d0 w164 fan d4 mutation-only5 split3 (three-way split) d5 mutation-only6 reserved7 reserved
16574TAIL_LENGTH
Tail length
quantitativetrait TAIL_LENGTH (Tail length)
17613EYE_FORM
Eyes
discrete0 paired d2 w1441 single d1 w482 multiple d3 w483 none d0 w164 stalked d4 mutation-only5 ring d5 mutation-only6 reserved7 reserved
Colour and pattern (LG3)
18644PIGMENT_A
Base hue
quantitativetrait PIGMENT_A (Base hue)
19684PIGMENT_B
Accent hue
quantitativetrait PIGMENT_B (Accent hue)
20724SATURATION
Saturation
quantitativetrait SATURATION (Saturation)
21763BRIGHTNESS
Brightness
quantitativetrait BRIGHTNESS (Brightness)
22793PIGMENT_CLASS
Colour
discrete0 cool d3 w961 warm d2 w802 deep d1 w483 pale d0 w324 iridescent d4 mutation-only5 albino d5 mutation-only6 melanic d6 mutation-only7 magenta d7 mutation-only
23823PATTERN_FAMILY
Pattern
discrete0 plain d0 w961 stripes d2 w642 spots d3 w643 gradient d1 w324 rings d4 mutation-only5 mottled d5 mutation-only6 labyrinth d6 mutation-only7 eyespots d7 mutation-only
24853REG_PATTERN
Pattern rule
discrete0 global (whole body) d1 w1281 segmental (per segment) d2 w802 appendage_only (limbs only) d3 w323 sparse d0 w164 fractal d4 mutation-only5 masked d5 mutation-only6 reserved7 reserved
25884PATTERN_DENSITY
Pattern density
quantitativetrait PATTERN_DENSITY (Pattern density)
26924PATTERN_CONTRAST
Pattern contrast
quantitativetrait PATTERN_CONTRAST (Pattern contrast)
Movement and surface (LG4)
27963MOVEMENT_FAMILY
Movement
discrete0 undulate (undulating) d2 w1121 pulse (pulsing) d1 w642 crawl (crawling) d3 w483 drift (drifting) d0 w324 jitter (jittering) d4 mutation-only5 spiral_swim (corkscrew swimming) d5 mutation-only6 glide (gliding) d6 mutation-only7 reserved
28993ACCENT_PLACEMENT
Accent placement
discrete0 none d1 w1121 appendages (on the limbs) d2 w802 head_tail (head and tail) d3 w483 alternate (alternating) d0 w164 inverted d4 mutation-only5 gradient d5 mutation-only6 reserved7 reserved
291024MOVE_AMPLITUDE
Movement amplitude
quantitativetrait MOVE_AMPLITUDE (Movement amplitude)
301064MOVE_FREQUENCY
Movement speed
quantitativetrait MOVE_FREQUENCY (Movement speed)
311104MOVE_STIFFNESS
Stiffness
quantitativetrait MOVE_STIFFNESS (Stiffness)
321143MOVE_PHASE
Movement phase
quantitativetrait MOVE_PHASE (Movement phase)
331173SURFACE_TEXTURE
Texture
discrete0 smooth d1 w1281 scaled d2 w642 ridged d3 w483 velvet (velvety) d0 w164 plated d4 mutation-only5 translucent d5 mutation-only6 crystalline d6 mutation-only7 bristled d7 mutation-only
341204SURFACE_RELIEF
Surface relief
quantitativetrait SURFACE_RELIEF (Surface relief)
351244CURVATURE
Curvature
quantitativetrait CURVATURE (Curvature)

A reserved allele index is invalid: a genome that carries one is malformed, and no birth produces one. Mutation-only alleles have founder weight 0 and appear only through the mutation pathways at birth.

Expression

What the two copies come to, per locus. This is all a reader needs to name a moeba and list its traits; the body that is drawn from the traits is presentation and may change, the traits do not.

Asking the species

Every request except the poke is an XAH Payment to the species account with hook parameters: one-letter names (as hex: F is 46, P is 50) and values as below. The species' Hooks read them and nothing else; memos and destination tags mean nothing to it. No partial payments, no SendMax, no paths: the amount must be the amount delivered.

FAsks forOther parametersAmountWho
01A founder—founder price + budgetanyone
02A birthP, Q: the parents' token ids, 32 bytes eachbirth fee + budget + Q's or P's price if it is another keeper'sthe keeper of at least one parent; the other must be theirs too or open under valid terms
04Withdraw termsP: the token idenough for one SetRemarks (the site sends 0.1 XAH)its keeper
05Publish termsP: token id; A: price per birth, u32 drops; X: expiry ledger, u32, optionalas aboveits keeper
06Give a nameP: token id; N: UTF-8, 1–24 bytes, printable, no leading or trailing spacename fee + record writeits keeper, once
—Poke: sweep a stuck birth, restart a stopped clockan Invoke with Destination the species account; no parameters, no amountthe transaction fee onlyanyone

The amounts are quoted from the ledger at the moment of the request and refused below the quote; an overpayment is kept as budget. The protocol fee for a birth, the founder curve, the issuer's share of partner prices and the name fee are Hook parameters on the species account and are read for you at /v1/issuer (birthFeeDrops, founderCurve, partnerCutBps, nameFeeDrops, tickDrops). The share comes out of the partner's payout: the requester pays the published price, and the slot records what the partner will receive. The budget a birth carries is 20 × tickDrops for the clock plus 124 emitted transactions at the network's emission price; what a birth does not spend stays with the species. The founder price is FFEE × (FMUL/100)^⌊n/FTRN⌋ with n the founders admitted so far, all from founderCurve. The site's own arithmetic for this is in its request pages; a wallet can copy it or over-quote slightly.

A request is accepted when the Payment succeeds and the species' Hooks return accept; a refusal is a tecHOOK_REJECTED with the reason in the Hook execution's return string, in plain words. After admission nothing more is signed: the species' own clock fixes the randomness, breeds, mints and delivers by Remit. A receiving account with lsfDisallowIncomingRemit set is refused at admission, since the child could never land.

LIFE

A moeba brought to life has its life on a second account, the LIFE account rGXvnPHRDktpq8BQYkKVz8AiByy3Q4BTDy on Xahau testnet. Its hooks keep one entry per living moeba and change it only by the transactions below. Everything this site shows about a living moeba is read from those entries; how it moves is worked out on each device from them.

Five positions

Two unnamed positions, the gate and the guard, and three named ones (NamedHooks): a transaction names the position it is for with HookName. The hashes are what this site recognises; any other installation reads as no LIFE.

PositionHookNameHookHashDoes
gatenone2311CBF2B8D2BF799669C8D1C8F91CFB2C6FD380F12707C8701E17FAA92EA10CRuns first on every transaction to the account. Refuses a LIFE transaction without a HookName, or with one no position answers (UNNAMED, WRONG_HOOK).
awakenawaken3BCD358AF596037991BF84F26324F625B3AA6F67E6688E933DF85655EEF14E24The activation Payment: exactly the price, from the token’s keeper, for a token of the species. Writes the first LifeState.
lifelifeABB97981549B83BDF1C30FAD4E6D576941CB41AF8724F12A5869AB6312664CC9Every Invoke but Start Visit: Feed, Care, Play, Rest, Wake, Open, Close, and Reap of a burned token.
visitvisitE1C5EC625018E8F357CF6FE52323D6863D77E8180612ACE8A2A6B90F87877BECStart Visit: the guest’s state, the host’s and its roster, in one transaction.
guardnone3ADC427DBC7FB9583A1FCCD1C8C0C8F62C30C24046BA3A651A8B12C318394567Lets the operator withdraw only what the reserves for the entries do not need.

The transactions

Bring to Life is a Payment of exactly the price (the hook parameter LP), named awaken, with the parameter T, the token id. Every other action is an Invoke named life (or visit), with A, one byte, and T; Start Visit adds H, the host’s token id; Play may add S, a spot the hook ignores; Rest may add U, when it ends (ledger time, u32).

ActionA
FEED01
CARE02
PLAY03
REST04
WAKE05
OPEN06
CLOSE07
START_VISIT08
REAP09

The state, and how to read it yourself

The entries are in the LIFE account’s HookState under the namespace 0F40B4738BB475C506966169F8060ACE20CDBCD48B2A97E7E8E67FD025F212F0 (sha256 of kin:life). A moeba’s LifeState is keyed by its token id: ask a node { "method": "ledger_entry", "params": [{ "hook_state": { "account": "rGXvnPHRDktpq8BQYkKVz8AiByy3Q4BTDy", "key": "<token id>", "namespace_id": "0F40B473…" } }] }. While it hosts, its roster is keyed 52 followed by the first 31 bytes of its token id (for example 52ABABABABAB…), and the count of living moebas is under 4C4946453A434F554E54…. Every entry at once: account_namespace. Times are ledger time, seconds since 2000-01-01.

The LifeState is 256 bytes, big-endian, fixed width: its length never changes, its first byte says which layout it is in, and what the fields do not use is kept empty at the end. What it holds is the state as of its last write: needs drift, rests end and long sleeps come by time alone, so a reader brings it to now with the rules in the hooks’ parameters (@kin/life’s effective() does exactly what the hooks do).

BytesField
0schemaVersion
1flags
2profileVersion
3paramsVersion
4–10temperament
11–14physiology
15–17affinity
18–21lastUpdate
22–31needs
32–33bond
34mode
35–66hostTokenId
67–70visitUntil
71othersOnArrival
72hostElement
73–108recentHosts
109–128caretaker
129–132caretakerSince
133–134caretakerCount
135–138lastKeeperAction
139–142awakenedAt
143–146activeSince
147–150periodActive
151–154totalActiveLife
155–158longestContinuousLife
159–160dormancyCount
161–164dormantSince
165–166hungryTicks
167–170careCount
171–174visitsHosted
175–176visitsMade
177–180milestones
181–184firstVisitMadeAt
185–188firstVisitHostedAt
189–192returnedFromDormancyAt
193–196restSince
197–200restUntil
201–227windows
228–231revision
232–255reserved

The roster is 217 bytes: version 1, then six slots of a visitor’s token id and when its visit ends. The count is 5 bytes: version 1, then the number living, u32.

Fees

Each action is one transaction with its network fee, which depends on the hooks it runs. Bring to Life also pays the price, once. Touching, calling and pointing are free: nothing is signed.

ActionNetwork fee, as measured on the hooks
Bring to Life (the Payment, beside the price)about 0.01 XAH (9,091 drops)
Feed, Care, Rest until woken, Wake, Open, Close, Reapabout 0.01 XAH (8,164 drops)
Play (one byte more: its spot)about 0.01 XAH (8,166 drops)
Rest until a chosen endabout 0.01 XAH (8,169 drops)
Start Visitabout 0.01 XAH (14,379 drops)

Refusals

A refused action rolls back with its reason’s code (HookReturnCode) and its words; the network fee is spent and nothing else changes. Every reason, by code, in the reference’s own words:

CodeReasonMeaning
1NOT_OWNEROnly the Moeba's current owner can do that.
2UNKNOWN_TOKENThere is no such token.
3NOT_SPECIESThat token was not issued by the Xahmoeba species.
4BURNEDThat Moeba's token has been burned; its LIFE is inert.
5NOT_ALIVEThat Moeba has not been brought to life.
6ALREADY_ALIVEThat Moeba is already alive.
10WRONG_AMOUNTThe payment must be exactly the activation price.
11ACTIVATIONS_CLOSEDNew activations are closed right now.
12NO_TOKENA payment to LIFE must name a token.
13INSUFFICIENT_RESERVEThe LIFE account cannot cover the reserve for a new state entry.
14WITHDRAWAL_GUARDThat withdrawal would leave too little for the reserves LIFE must keep.
15NO_GENOMEThat token's birth record has no genome LIFE can read.
16NOT_PLAIN_PAYMENTBring to Life must be a plain XAH payment of the price.
20RESTINGIt is resting.
21DORMANTIt is dormant; wake it first.
22VISITINGIt is visiting and returns at its visit's end.
23HAS_GUESTSIt has guests; it can do that once they have left.
24NOT_RESTINGIt is neither resting nor dormant.
25REST_MINIMUMIt has not rested for the rest minimum yet.
26COOLDOWNToo soon after the last one.
27REST_UNTILA rest's chosen end must be at least the rest minimum away.
30HOST_IS_SELFA Moeba cannot visit itself.
31HOST_UNKNOWNThere is no such host.
32HOST_NOT_ALIVEThe host has not been brought to life.
33HOST_BURNEDThe host's token has been burned.
34HOST_CLOSEDThe host is not open to visits.
35HOST_FULLThe host has no free slot.
36HOST_VISITINGThe host is away visiting.
37HOST_RESTINGThe host is resting.
38HOST_DORMANTThe host is dormant.
39VISITOR_COOLDOWNIt visited too recently.
40REPEAT_VISITIt visited this host too recently.
41HOST_SCHEMAThe host's state is in a layout this LIFE does not read.
50NOT_BURNEDOnly a burned Moeba's state can be reaped.
51VISIT_RUNNINGA visit involving it is still running.
60UNKNOWN_ACTIONThat is not a LIFE action.
61BAD_PARAMSThe hook parameters are invalid.
62WRONG_HOOKThat action belongs to another LIFE position (HookName).
63UNNAMEDA LIFE transaction must carry its position's HookName.
64OVERFLOWThat would take a count or a time in its state past what the state can hold.
65SCHEMAThat Moeba's state is in a layout this LIFE does not read.

The API

Everything above is what the ledger says; the API says the same in words and pictures, from an index that re-reads the ledger every few seconds. It is read-only, allows any origin, and every JSON answer carries headLedger so you know what ledger you are looking at. This deployment's is at https://api.xahmoeba.com.

RouteAnswer
GET /v1/moebas/{id}The record — id, model, genome, kind, generation, parents, breeder, owner, fertility and use, maturity, entropy, rules hash, digest, terms, offer — with name (taxon, variant, fingerprint, given, display) and traits (every expressed locus with its label, group, allele and value) already worked out.
GET /v1/moebas/{id}/metadata.jsonToken metadata in the shape NFT readers expect: name, description, image, external_url, attributes as { trait_type, value }. The protocol's facts sit under xahmoeba.
GET /v1/moebas/{id}.png?size=Its picture: the specimen view as a still, in its habitat, drawn from the genome. Square; size is the side, 64–800. Drawn once per genome and kept; the metadata's image points here.
GET /v1/moebas/{id}.svg?size=Its structure diagram, drawn from the genome; a still, on paper, with nothing interactive. size is the height, 64–2048. Immutable for a day.
GET /v1/moebas/{id}/plateWhere its plate stands: state is painted, painting or none, with the plate's width and height and the webp and jpg addresses below. Asking paints nothing.
GET /v1/moebas/{id}/plate.webp?width=, .jpgIts plate: a 4:5 sheet in the manner of a natural-history atlas, the moeba painted in watercolour from its genome as the renderer builds it, its parents beside it. Painted on the first request, which answers 202 with Retry-After until it is done (under a minute), or 503 while the painter is busy; then kept. width is 320 up to the plate's own, 1600 here; download=1 names the file.
GET /v1/moebas/{id}/model.glbIts body as a portable 3D model, a glTF 2.0 binary: the mesh with vertex colours, a skeleton of named bones, its skin, the face and shape morphs, and six baked clips (idle, travel and four moods), compressed with EXT_meshopt_compression and KHR_mesh_quantization (in three.js, give the loader a meshopt decoder). The organism's rules ride along under XAHMOEBA_organism. Made on the first request, which answers 202 with Retry-After until it is (a minute or so), then kept; the record's glb points here.
GET /v1/moebas?owner=&kind=&living=&forSale=&open=&limit=&cursor=A page of records in mint order; ?ids=A,B,C for several.
GET /v1/moebas/{id}/history, /ownersEvery transaction that touched it and what each did; who has held it, with prices.
GET /v1/populationThe whole population in one document, gzipped, with an ETag.
GET /v1/issuer, /v1/queue, /v1/serverThe species' parameters and prices; the birth queue as it stands; the network's reserves and base fee.
GET /v1/ledgersServer-sent events, one per ledger close.

Each client has a budget — a few hundred requests a minute, a fresh picture costing several and a fresh plate or model a few dozen — and gets 429 with Retry-After over it. Pictures and the population are cacheable; please cache them. A marketplace that shows moebas needs only metadata.json and the picture, and can verify either against the ledger with this page.

Try it on a real one

Choose a moeba, or paste a token id. Its URI is decoded byte by byte on this device by the rules above, the genome is unpacked locus by locus, and each API link opens what the index says about it.

If this page and the ledger disagree, the ledger is right and this page has a fault. Tell us.