d Divi Name Service

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 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

FormExampleWho can register it
Top-level name (3–32 chars)bertshuler, siegeworldsAnyone, first come first served
Tag in a namespaceknight@siegeworldsWhoever the namespace's owner or signer allows; anyone if it is open
Telegram handle@bert = bert@telegramThe 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" }
  1. When the recipient field holds something that is not an address, resolve it. A 404 means not registered; its pending list says if a registration is waiting to confirm (pending names never resolve).
  2. Show Send to knight@siegeworlds (DAbc…) and ask the user to confirm.
  3. 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.

  1. POST /api/v1/build with the name, the payer and the record.
  2. Pay send.amount DIVI to send.to with send.memo as the OP_RETURN data, spending only coins of send.from (input 0 must be the payer's).
  3. 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 fieldMeaning
opregister (default), update, delete
payerSigns input 0 and pays. For update/delete it must own the name (or own / be signer of a tag's namespace).
diviWhere the name sends Divi. Required on register.
ownerWho controls the name; defaults to the payer. Update with a new owner to transfer.
authFor a tag: the namespace's permission signature (below).
fieldskind, 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:

  1. the payer owns ns or is its signer (you issue the tag yourself);
  2. ns has policy=open (anyone may take an unused tag);
  3. the record carries auth: a Divi signmessage signature (base64) by the namespace's owner or signer over exactly DVNS1 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

RegistrationFee (DIVI)
3-letter name10,000
4-letter name5,000
5-letter name1,000
6 or more letters500
Tag x@ns, update, delete10

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.

CallReturns
GET inforegistry address, height, fees, reserved names, Telegram signer
GET resolve/{name}the name's record; 404 with pending
GET namesns, top, q, kind, address, limit (≤1000), offset → {total, names}
GET names/{name}/historyevery record for one name, applied or rejected, with the reason
GET history, GET pendingrecent registry activity; records waiting to confirm
GET fee?name&opprice, available, reserved, namespace_missing
POST buildthe payment to make; 409 if it would be rejected
POST notifytell the service about a broadcast record
POST auth/telegrampermission 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.