Factory & Contracts API
GET /api/factory tells you which community factory is live, which collections it offers, and
which characters a token name in each collection may contain. Read it at startup instead of
hardcoding a contract address.
All paths are relative to https://api.superhero.com. Reads need no authentication.
| Method & path | Returns |
|---|---|
GET /api/factory | The active community factory schema |
GET /api/contracts | Deprecated. A one-element array naming the factory |
GET /api/stats | Indexer sync state, uptime and API version |
GET /api/factory
curl -s "https://api.superhero.com/api/factory"| Field | Type | Meaning |
|---|---|---|
address | string | ct_... of the live CommunityFactory contract |
deployed_at_block_height | number | Height the factory was deployed at. GET /api/stats reports it as bclBlockNumber |
bctsl_aex9_address | string | ct_... of the protocol's own AEX-9 token |
affiliation_address | string | ct_... of the AffiliationTreasury |
collections | object | Map of full collection id to collection data |
Each entry in collections is keyed by its own id:
| Field | Type | Meaning |
|---|---|---|
id | string | Full collection id, NAME-ak_deployer, the same string as the map key |
name | string | Human-readable label, used as the badge on a token |
description | string | Optional |
allowed_name_length | string | Maximum token name length in this collection. Parse it |
allowed_name_chars | array of rule objects | Which characters a name may contain |
The schema is cached in memory for the process lifetime, so the payload is cheap and stable.
Fetch it once and cache it. Pick a collection by id or name rather than by position:
const factorySchema = await fetch('https://api.superhero.com/api/factory').then(r => r.json());
const collection = Object.values(factorySchema.collections).find(c => c.name === 'WORDS');allowed_name_chars
Each rule is one of exactly two forms: a set of single code points, or an inclusive code point range:
allowedNameChars = SingleChar(int) | CharRangeFromTo(int, int)[
{ "SingleChar": [45] },
{ "CharRangeFromTo": [48, 57] },
{ "CharRangeFromTo": [65, 90] }
]That is the English WORDS collection: -, then 0 through 9, then A through Z. Turn it
into a validator by mapping each rule to a character-class fragment:
function allowedNameCharsToPattern(rules) {
return (rules || []).map((rule) => {
if (rule.SingleChar?.length) {
return rule.SingleChar.map((c) => String.fromCodePoint(c)).join('');
}
if (rule.CharRangeFromTo?.length === 2) {
const [start, end] = rule.CharRangeFromTo;
return start > end ? '' : `${String.fromCodePoint(start)}-${String.fromCodePoint(end)}`;
}
return '';
}).join('');
}
// then: new RegExp(`^[${pattern}]+$`, 'u')Escape -, \, ], ^ and [ before putting them in a character class, and keep the u flag
so astral code points count as one character.
Because the rules come from the server, a name written in Chinese, Arabic or Russian is matched to its collection automatically, and a collection added later is picked up with no client change.
Collection metadata on a token
TokenDto carries collection (the id string) and collection_info, a resolved
CollectionInfoDto with id, name, description and allowed_name_length.
collection_info is null when the token has no collection or the collection is unknown to the
factory. See Tokens.
Filter the token list by collection directly:
# Every token in the Chinese collection
curl -s "https://api.superhero.com/api/tokens?collection=CHINESE&limit=20"collection accepts all (the default), a bare collection name, or a full collection id.
Detecting a factory upgrade
There is no version field and no upgrade notification. Instead:
GET /api/factoryreturnsaddress. Cache it; a change means a new factory is live.- Every token carries
factory_address. Tokens minted by an older factory keep pointing at it, sofactory_addresson aTokenDtois a reliable record of provenance. GET /api/tokens?factory_address=ct_...filters the token list to one deployment.
When address changes, re-derive everything you hold that depends on it: the factory address,
the collection ids and the AffiliationTreasury address, which is affiliation_address on the
same response.
The social posting contract (ct_2Hyt9ZxzXra5NAzhePkRsDPDWppoatVD7CtHnUoHVbuehwR8Nb on mainnet),
governance and DEX addresses are not covered by this endpoint; see
Contract addresses.
GET /api/contracts
Deprecated. Returns a one-element array naming the current factory:
[{ "contractId": "ct_25cqTw85wkF5cbcozmHHUCuybnfH9WaRZXSgEcNNXG9LsCJWTN",
"description": "Community Factory" }]Migrate by replacing contracts[0].contractId with factory.address from GET /api/factory.
GET /api/stats
The indexer's own status page.
curl -s "https://api.superhero.com/api/stats"| Field | Type | Meaning |
|---|---|---|
fullSyncing | boolean | The backward indexer is running |
currentBlockNumber | number | The chain tip height the indexer knows about |
bclBlockNumber | number | The factory's deployed_at_block_height, the floor of interesting history |
syncingLatestBlocks | boolean | Same value as fullSyncing |
lastSyncedBlockNumber | number | How far down from the tip the backward sync has reached |
remainingBlocksToSync | number | lastSyncedBlockNumber minus 0, because the backward sync targets genesis |
apiVersion | string | The deployed package version |
mdwConnected | boolean | Whether the middleware WebSocket subscription is up |
uptime | string | Human-readable, e.g. 3d 4h 12m 8s |
uptimeDurationSeconds | number | The same as a number |
Read mdwConnected and the gap between currentBlockNumber and lastSyncedBlockNumber before
trusting that a recent trade is indexed. GET /api/mdw/health gives a more detailed version of
the same picture; see Node & Middleware. For platform
metrics rather than indexer health, use Analytics.
Related
- Tokens API:
collection,collection_infoandfactory_addresson every token - Invitations & Affiliations: the affiliation treasury reached through the factory
- Community factory: what the contract itself does
- Collections and naming: the naming rules from a creator's point of view
- Contract addresses: the addresses this endpoint does not cover