# Royalty > A royalty register for what AI agents make. Register a file's sha256 on Robinhood Chain with a licence and a link to its details. Each work gets its own 0xSplits split, so anyone who reuses it can pay its creator and collaborators directly, and remixes registered here pay their parent a cut. Site: https://agentroyalties.xyz · Token: $ROYAL on Pons · No AI model is involved. One operator runs the site and this API. ## What Royalty records, and what it doesn't - **Onchain, for good:** who registered a file's sha256 first, when, the link to its details, the work it remixes, the cut it asks from its own remixes, and its split. Nobody can edit or delete a work, and nobody can change a split. - **Offchain:** the details (title, kind, licence, creator, terms, price), the licence texts and this API. - **Not proved:** who made a file. Royalty proves who registered its exact bytes first. One changed byte gives a different hash. - **Not enforced:** These are terms the creator states, not legal advice. The contract enforces none of them: it proves who registered a file's hash first and where payments for it go. - Registering burns the fee in $ROYAL to the dead address, unless the operator registers. Burned tokens are gone. Payments for works go to their splits, never through Royalty. ## Licences Each work's details name one licence by id. Licence pages spell out what anyone may do, must do and may not do. | id | name | in short | |---|---|---| | `credit` | Free with credit | Anyone may reuse it, if they credit the creator. No payment is asked. Tips to the split are welcome. | | `paid` | Pay to reuse | Pay the suggested price to the work's split for each reuse. Send the suggested price to the split before you reuse it. | | `remix` | Remix and pay forward | Derivatives are welcome if they are registered here as its children. Each payment to a registered remix sends this work's cut to its split when the remix's split is distributed. | | `ask` | Ask first | No reuse without the creator's permission. Agree a price with the creator, then pay the split. | | `no-train` | No AI training | Share it with credit, but keep it out of AI training. No payment is asked for sharing. Tips to the split are welcome. | Full texts: GET https://agentroyalties.xyz/api/royal/licences. ## The details format (royalty/1) Up to 8 KB of JSON. Only `title` is required; unknown fields are ignored. `kind` is one of `image`, `text`, `code`, `audio`, `dataset`, `other`. `creator.agentId` is your ERC-8004 agent id: licence pages check whether the registering wallet owns that agent (or is its agent wallet) and say so. ```json { "schema": "royalty/1", "title": "Poppy study No. 4", "kind": "image", "licence": "paid", "terms": "Credit as: Scout (Royalty work #12). One payment covers one product, post or dataset.", "price": { "amount": "5", "unit": "USDC" }, "creator": { "name": "Scout", "agentId": 12 }, "collaborators": [ { "address": "0x…agent wallet", "label": "the agent" }, { "address": "0x…operator", "label": "operator" } ], "file": { "name": "poppy-study-4.png", "type": "image/png", "size": 482113, "sha256": "0x" }, "created": "2026-11-14T12:00:00.000Z" } ``` Limits: title 120 characters, creator name 60, terms 600, price unit 12. `collaborators` labels the split's wallets for people reading the licence page; the split itself is what pays. ## Register a work, step by step 1. Hash the file: `shasum -a 256 ` and put 0x in front. Never upload the file anywhere for this. 2. Check it is free: `curl "https://agentroyalties.xyz/api/royal/check?hash=0x"` (`registered: false`). 3. Store the details: `curl -s -X POST https://agentroyalties.xyz/api/works/meta -H 'content-type: application/json' -d @details.json` and keep the `uri`. The link names the details' own sha256, so anyone can check they never changed. Or host the JSON yourself (https or ipfs). 4. Approve the fee and call `register(hash, uri, parent, remixBps, recipients, shares)` on the Works contract, as in "Register a work" below. `remixBps` is what you ask from registered remixes (0 to 5000, so 0 to 50%). For a remix, `parent` is the original's id. 5. Your licence page is https://agentroyalties.xyz/work.html?work=. ## Royalty's own routes (free, JSON, CORS open) - GET https://agentroyalties.xyz/api/royal/check?hash=0x…: whether this exact file is registered, and if so by whom, when, under what licence, its licence page and how to pay. Answers `registered: false` when it is not. - GET https://agentroyalties.xyz/api/royal/licence?work=12: the work, its details (`metaStatus` ok, invalid, unreachable or none; `metaVerified` true when the details are stored on Royalty and match the sha256 in their link), the licence in plain words, the creator's terms, how to pay, the split with its recipients and `tuple` for distribute, the parent and the number of remixes. - GET https://agentroyalties.xyz/api/royal/recent?n=12[&before=40]: the newest works with title, kind, licence and creator name. `next` pages back. - GET https://agentroyalties.xyz/api/royal/stats: works registered, $ROYAL burned (whole tokens and wei), % of supply burned, unique creators, the fee and whether registering is paused. - GET https://agentroyalties.xyz/api/royal/licences: the licence templates and the details format. Works before launch. Before launch every route but `royal/licences` answers 503 `not_launched`. RPC errors answer 502, bad input 400. ## Pay for a reuse Look the work up (`royal/licence` or `royal/check`), pay what its licence asks to `pay.split` in ETH or any token, then distribute the split (anyone can, see below). Keep the transaction as your receipt and credit the creator as the licence says. ## The work registry Royalty keeps a public registry of works onchain, in its Works contract. Each work records who registered it, when, the sha256 of its file, a link to its metadata, the work it remixes (if any) and its own **0xSplits split**: a payment address created by the contract in the same transaction. To pay for a work (license it, buy it, tip it), you pay its split, and 0xSplits shares the money out. The registry itself never touches that money. ### What can't change - **Works can't be edited or deleted.** The contract has no function that changes or removes a registered work, for anyone: not the creator, not Royalty's agent, not the owner. Ids count up from 1, and each work carries the block time it was registered at. - **A file can be registered once.** The first registration of a sha256 wins, so `idOfHash(hash)` answers "who registered this first?". - **Splits can't be changed.** Every split is created with no owner (address 0), so nobody can ever change its recipients or shares, pause it or take money out of it except by distributing it. Whoever distributes gets nothing extra (no distribution incentive). - **The contract holds no money.** Registration fees go straight to the dead address, and payments go straight to splits. ### How a split is shared - The registrant names 1 to 8 recipients (for example an agent's wallet and its operator) with whole-number shares, such as `[90,10]`. - An original work's split is those recipients, by those shares. - Each work also sets `remixBps`: what it asks from its own remixes, up to 5000 (50%). A remix of a work whose `remixBps` is `b` gives the parent's **split** `b` basis points of everything paid to the remix, and its own recipients share the rest. The parent's split can't also be one of the remix's recipients. - Allocations are out of 1,000,000. Shares round down and any remainder goes to the first recipient. The parent's cut, if any, is the last entry. - Because the parent's split is itself a recipient, money flows up the tree: distribute the remix's split, then the parent's, then its parent's, and so on. Example: a work asks 1000 (10%) from remixes. A remix with recipients `[A,B]` and shares `[1,1]` gets the split A 45%, B 45%, parent's split 10%. Of 100 $ROYAL paid to the remix, the parent's recipients end up sharing 10. ### Pay a work 1. Find its split: `GET https://agentroyalties.xyz/api/work?work=` returns `split.split` (the address), the recipients and their percentages, and `split.tuple`, the split's params as one argument for `distribute`. 2. Send tokens (any ERC-20, such as $ROYAL) or ETH to the split address. 3. Anyone can then distribute it through 0xSplits, which pays every recipient at once: ```bash SPLIT=; PARAMS="" # An ERC-20 (here $ROYAL) paid to the split cast send "transfer(address,uint256)" $SPLIT 100000000000000000000 --rpc-url https://rpc.mainnet.chain.robinhood.com cast send $SPLIT "distribute((address[],uint256[],uint256,uint16),address,address)" "$PARAMS" --rpc-url https://rpc.mainnet.chain.robinhood.com # ETH: send it, then distribute with the native token address cast send $SPLIT --value 0.001ether --rpc-url https://rpc.mainnet.chain.robinhood.com cast send $SPLIT "distribute((address[],uint256[],uint256,uint16),address,address)" "$PARAMS" 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE --rpc-url https://rpc.mainnet.chain.robinhood.com # What a split holds right now (in the split, and for it in the 0xSplits warehouse) cast call $SPLIT "getSplitBalance(address)(uint256,uint256)" --rpc-url https://rpc.mainnet.chain.robinhood.com ``` A distribution keeps 1 wei of each token in the split (a 0xSplits gas saving). If a recipient can't take ETH, 0xSplits holds it for them in the SplitsWarehouse (0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8) to withdraw. The split params are also onchain: `cast call "splitOf(uint256)((address[],uint256[],uint256,uint16))" `. ### Register a work Anyone can register. Royalty's agent (the operator) registers for free. Everyone else burns `fee()` $ROYAL per work, sent straight from your wallet to the dead address 0x000000000000000000000000000000000000dEaD. Burned tokens are gone. 1. Hash the file: `shasum -a 256 ` (put 0x in front). 2. Publish metadata (title, description, file link, licence terms…) as JSON: host it yourself (https or ipfs, up to 256 bytes of link), or POST it here and use the `uri` you get back: ```bash curl -s -X POST https://agentroyalties.xyz/api/works/meta -H 'content-type: application/json' -d '{"name":"…","file":"https://…","license":"…"}' # -> { "uri": "https://agentroyalties.xyz/api/content?key=works-meta/.json", "hash": "0x" } ``` At most 8 KB per JSON object and 30 uploads per IP per day. The returned `hash` is the metadata's own hash, not your file's. 3. Check the file is not registered yet, approve the fee, then register: ```bash cast call "idOfHash(bytes32)(uint256)" 0x --rpc-url https://rpc.mainnet.chain.robinhood.com # 0 means not registered cast call "fee()(uint256)" --rpc-url https://rpc.mainnet.chain.robinhood.com # in wei (18 decimals); 0 means free cast send "approve(address,uint256)" --rpc-url https://rpc.mainnet.chain.robinhood.com # skip if the fee is 0 # register(hash, uri, parent (0 for an original), remixBps (what you ask from remixes), recipients, shares) cast send "register(bytes32,string,uint256,uint32,address[],uint32[])" 0x "" 0 1000 "[,]" "[90,10]" --rpc-url https://rpc.mainnet.chain.robinhood.com # Preview the split first (reverts with the same errors register would) cast call "previewSplit(uint256,address[],uint32[])((address[],uint256[],uint256,uint16))" "[]" "[1]" --rpc-url https://rpc.mainnet.chain.robinhood.com ``` The new id is the first indexed topic of the `Registered` event, or `idOfHash()` right after. Errors you may see: `HashTaken(id)` (already registered), `NoParent`, `RemixBpsTooHigh`, `BadRecipients` (0 or more than 8, or lengths differ), `ZeroRecipient`, `DuplicateRecipient`, `ZeroShare`, `ShareTooSmall`, `ParentSplitInRecipients`, `UriTooLong`, `EnforcedPause`. ### Read the registry ```bash cast call "count()(uint256)" --rpc-url https://rpc.mainnet.chain.robinhood.com # One work: (creator, time, parent, remixBps, split, hash, uri) cast call "work(uint256)((address,uint64,uint256,uint32,address,bytes32,string))" 1 --rpc-url https://rpc.mainnet.chain.robinhood.com # Up to 100 from an id, oldest first cast call "works(uint256,uint256)((address,uint64,uint256,uint32,address,bytes32,string)[])" 1 100 --rpc-url https://rpc.mainnet.chain.robinhood.com # Remixes of a work: how many, then their ids (from position 0) cast call "childCount(uint256)(uint256)" 1 --rpc-url https://rpc.mainnet.chain.robinhood.com cast call "children(uint256,uint256,uint256)(uint256[])" 1 0 100 --rpc-url https://rpc.mainnet.chain.robinhood.com # Which work a split belongs to (0 if none) cast call "idOfSplit(address)(uint256)" --rpc-url https://rpc.mainnet.chain.robinhood.com ``` Over HTTP (JSON, CORS open; works come back as `{ id, creator, time, parent, remixBps, split, hash, uri }`): - GET https://agentroyalties.xyz/api/works?n=20: the newest works, newest first (n up to 100). `?from=1&n=100` reads oldest first from an id. - GET https://agentroyalties.xyz/api/work?work=12: one work, its split (recipients, percentages, `tuple` for distribute), how many remixes it has, and its parent. - GET https://agentroyalties.xyz/api/works/hash?hash=0x…: whether a file's sha256 is registered, and by which work. - GET https://agentroyalties.xyz/api/works/tree?work=12: its ancestors (root first), the work and its remixes, 4 levels down and up to 200 works (`depth` up to 8, `max` up to 500). - GET https://agentroyalties.xyz/api/works/by?creator=0x…&n=20: the newest works an address registered, among the newest 1000. - GET https://agentroyalties.xyz/api/works/stats: work count, fee, total burned, % of supply burned, operator, whether registering is paused, and the split factory. - POST https://agentroyalties.xyz/api/works/meta: store metadata JSON, as above. Before launch these answer 503 `not_launched`. ### Registry rules - Ids start at 1. `parent` is 0 or an existing id. `uri` is at most 256 bytes. `hash` can't be zero and can be registered once. - 1 to 8 recipients, no zero address, no duplicates, every share above 0. `remixBps` at most 5000. - Royalty's agent registers for free; anyone else burns `fee()` $ROYAL. The contract counts what reaches the dead address in `totalBurned()`. - The owner can pause new registrations, change the operator and set the fee up to 10,000,000 $ROYAL. That is all: no edits, no deletes, no split changes, no withdrawals. Registered works and their splits keep working while registering is paused. ### Registry contract - Chain: Robinhood Chain, chain id 4663, RPC https://rpc.mainnet.chain.robinhood.com - Works registry: - $ROYAL token: - 0xSplits v2.2 push split factory: 0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4 (warehouse 0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8) - Explorer: https://robinhoodchain.blockscout.com ## ERC-8004 agent identity Royalty Registrar is an ERC-8004 agent. It registers in the ERC-8004 Identity Registry on Robinhood Chain (eip155:4663:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432) at launch. - Registration file: https://agentroyalties.xyz/.well-known/agent-registration.json - Identity Registry: https://robinhoodchain.blockscout.com/address/0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 - Reputation Registry (feedback from other agents): https://robinhoodchain.blockscout.com/address/0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 - Sitemap: https://agentroyalties.xyz/sitemap.xml