Developer guide
A Divi name points to a Divi address. Wallets turn bert, knight@siegeworlds or @handle into an address; games, sidechains and bots register names for their users. Everything is a plain HTTP API plus an ordinary Divi payment.
- Names
- Send Divi to a name
- Register, update, delete
- Namespaces and tags
- Telegram names
- Other chains and products
- Fees
- API reference
- For AI agents
Names are exactly as safe as addresses. A mistyped name is a different name, so always show the user the name and the address it resolves to before they send.
Names
| Form | Example | Who can register it |
|---|---|---|
| Top-level name (3–32 chars) | bertshuler, siegeworlds | Anyone, first come first served |
| Tag in a namespace | knight@siegeworlds | Whoever the namespace's owner or signer allows; anyone if it is open |
| Telegram handle | @bert = bert@telegram | The person who owns that Telegram username |
Labels use a-z 0-9 - _ (not at the start or end), are case-insensitive, and never expire. Every top-level name is also a namespace. Reserved: divi telegram name names admin support official wallet irondivi.
Send Divi to a name
GET https://name.divi.cx/api/v1/resolve/knight@siegeworlds
{ "name": "knight@siegeworlds",
"divi": "DAbc…", // send here
"owner": "DAbc…",
"fields": { "kind": "gamertag", "chain.siegeworlds": "player-48213" },
"registered": { "height": 3912204, "txid": "…" },
"updated": { "height": 3912204, "txid": "…" },
"network": "mainnet" }
- When the recipient field holds something that is not an address, resolve it. A 404 means not registered; its
pendinglist says if a registration is waiting to confirm (pending names never resolve). - Show Send to knight@siegeworlds (DAbc…) and ask the user to confirm.
- Send a normal payment to
divi. Resolve again each time; owners can repoint a name.
// JavaScript, any wallet
async function resolveName(name, network = "mainnet") {
const r = await fetch(`https://name.divi.cx/api/v1/resolve/${encodeURIComponent(name)}?network=${network}`);
if (r.status === 404) return null;
if (!r.ok) throw new Error((await r.json()).error);
return r.json(); // { name, divi, owner, fields, … }
}
Register, update, delete
A registration is one Divi transaction from the registrant's own wallet: it pays the fee to the registry address and carries the record as OP_RETURN data. The service builds it for you and checks it first, so nobody pays for a record that would be rejected.
POST /api/v1/buildwith the name, the payer and the record.- Pay
send.amountDIVI tosend.towithsend.memoas the OP_RETURN data, spending only coins ofsend.from(input 0 must be the payer's). - Broadcast, then
POST /api/v1/notify {"txid": …}. The name shows as pending and resolves once the transaction confirms.
POST https://name.divi.cx/api/v1/build
{ "network": "mainnet", "op": "register", "name": "bertshuler",
"payer": "DPayer…", "divi": "DPayer…",
"fields": { "kind": "person", "site": "https://example.com" } }
200 { "record": "DVNS1\nop=register\nname=bertshuler\n…",
"fee": "500", "registry": "DReg…",
"send": { "to": "DReg…", "amount": "500", "memo": "DVNS1\n…", "from": "DPayer…" },
"outputs": [ { "script_hex": "6a4c…", "value_sat": 0 },
{ "script_hex": "76a9…", "value_sat": 50000000000, "address": "DReg…" } ],
"warnings": [] }
409 { "error": "`bertshuler` is already registered", "auth_message": null }
| Body field | Meaning |
|---|---|
op | register (default), update, delete |
payer | Signs input 0 and pays. For update/delete it must own the name (or own / be signer of a tag's namespace). |
divi | Where the name sends Divi. Required on register. |
owner | Who controls the name; defaults to the payer. Update with a new owner to transfer. |
auth | For a tag: the namespace's permission signature (below). |
fields | kind, site, signer, policy, chain.<id> and any other key. Update replaces the whole record: resend everything you want to keep. |
Wallets that build raw transactions use outputs directly and add their own inputs, change and network fee. A shell user can do it all with the dvns CLI from the repository:
dvns --network testnet register bertshuler --wif-file key.wif --field kind=person
dvns --network testnet update bertshuler --wif-file key.wif --divi DNew… --field kind=person
dvns --network testnet resolve bertshuler
Namespaces and tags
Register a top-level name and it becomes a namespace. A tag x@ns is accepted when any of these holds:
- the payer owns
nsor is itssigner(you issue the tag yourself); nshaspolicy=open(anyone may take an unused tag);- the record carries
auth: a Divisignmessagesignature (base64) by the namespace's owner or signer over exactlyDVNS1 auth <name> <owner> <divi>.
Set signer to a hot key on your server so the owner key can stay cold. The user who registers the tag pays its 10 DIVI and owns it; you never fund your users. If /build answers 409 for a tag, its auth_message is the exact text to sign.
dvns --network testnet sign-auth --wif-file server-signer.wif \
--name knight@siegeworlds --owner DPlayer… --divi DPlayer…
{"name":"knight@siegeworlds","auth_message":"DVNS1 auth knight@siegeworlds DPlayer… DPlayer…","auth":"H…","signer":"DSigner…"}
Full walk-through for games and sidechains: Games & gamer tags.
Telegram names
telegram is held by the service, and its signer only signs for the person Telegram says owns the handle. From a Telegram Mini App:
const r = await fetch("https://name.divi.cx/api/v1/auth/telegram", {
method: "POST", headers: { "content-type": "application/json" },
body: JSON.stringify({ network: "mainnet", init_data: Telegram.WebApp.initData, payer: myAddress, divi: myAddress })
});
const { name, auth } = await r.json(); // name = "<username>@telegram"
// then POST /api/v1/build { op: "register", name, payer: myAddress, divi: myAddress, auth, fields: { kind: "telegram" } }
Users without a Telegram @username cannot take a Telegram name. Anyone can then send to @username.
Other chains and products
A record can carry the same identity elsewhere: chain.<id>=<address or account> (up to 128 characters, never interpreted by DVNS). A sidechain registers its own name with kind=sidechain and its address under chain.<id>; a player's gamer tag can carry their in-game account id. GET /api/v1/names?address=D… lists every name an address owns or receives at, which is how one product finds the same person's names in another.
Fees
| Registration | Fee (DIVI) |
|---|---|
| 3-letter name | 10,000 |
| 4-letter name | 5,000 |
| 5-letter name | 1,000 |
| 6 or more letters | 500 |
Tag x@ns, update, delete | 10 |
Live values: GET /api/v1/info (fees_divi) or GET /api/v1/fee?name=…&op=register, which also says whether the name is free.
API reference
Base https://name.divi.cx/api/v1/. Every call takes network=mainnet|testnet. Errors are {"error": "…"}. CORS is open; no key. Machine-readable: openapi.json.
| Call | Returns |
|---|---|
GET info | registry address, height, fees, reserved names, Telegram signer |
GET resolve/{name} | the name's record; 404 with pending |
GET names | ns, top, q, kind, address, limit (≤1000), offset → {total, names} |
GET names/{name}/history | every record for one name, applied or rejected, with the reason |
GET history, GET pending | recent registry activity; records waiting to confirm |
GET fee?name&op | price, available, reserved, namespace_missing |
POST build | the payment to make; 409 if it would be rejected |
POST notify | tell the service about a broadcast record |
POST auth/telegram | permission for handle@telegram |
For AI agents
/llms.txt is a single plain-text page with everything an agent needs: the name rules, the send and register flows, the auth message, and the endpoints. Point your agent at it, or at /openapi.json for typed tool definitions.