{"schema_version":"2026-15","provider":"XRPL-Utilities™","service":"XR-Trust","domain":"XRPL Permissioned Domains (XLS-80)","interpretation":"Descriptive directory of PermissionedDomain ledger objects. NOT a compliance, certification, or risk assessment of any domain, owner, credential issuer, or member.","endpoints":{"list_domains":"GET /domains?limit=&offset=","domain_drilldown":"GET /domain/{domain_id}","credential_issuers":"GET /credentials/issuers","scan":"POST /scan {domain_id?, owner_address?}","events":"GET /events?since=<event_id>&limit=<n>&tx_type=<comma_separated_subset>"},"freshness_pipeline":{"persistent_snapshot":"On startup, the materialized /domains snapshot is hydrated from /data/trust.db (aiosqlite) so the first request after a redeploy serves immediately.","streaming_subscribe":"A long-lived WebSocket subscription to the global transactions stream filters client-side for XLS-70/80 lifecycle tx types (PermissionedDomainSet, PermissionedDomainDelete, CredentialCreate, CredentialAccept, CredentialDelete) and XLS-81 permissioned-DEX txs (when the body or affected meta carries DomainID), and persists each event within seconds of validation.","inline_seed":"When a PermissionedDomainSet from a brand-new owner arrives via subscribe, account_objects is fetched once for that owner (O(1)) and the domain is upserted into the snapshot inline. Closes the new-owner gap without any whole-ledger walk.","incremental_refresh":"Every 300s the incremental loop re-polls account_objects for every known owner and updates only the domains that changed (O(known_owners) calls per pass; ~500 QuickNode credits/day at current size).","manual_seed":"POST /admin/seed?owner=<addr> backfills a specific owner if subscribe missed them (e.g. a deploy gap). Read-only on-chain + idempotent in DB; no auth required.","event_consumers":"Pulse polls GET /events for the permissioned_domain_lifecycle event source; other downstream consumers can do the same."},"indexing_note":"Discovery is event-driven, not walk-based. There is no periodic `ledger_data type=permissioned_domain` enumeration - that path was retired in 2026-13 because the Clio type filter still scans the full ~250M-entry ledger server-side and burned roughly 10M QuickNode credits per day. Per-domain drill-down (/domain/{id}) uses ledger_entry index=<id> and is O(1).","fields":{"domain_id":"64-hex LedgerIndex of the PermissionedDomain object (XLS-80)","owner_address":"XRPL classic address of the domain owner (the Owner field)","owner_label":"XRPScan label for owner_address when available; null otherwise. Shape: {name, desc, domain, verified, twitter}","accepted_credentials":"Array of {issuer, credential_type, credential_type_decoded, issuer_label} the domain accepts. credential_type is the raw hex per XLS-80; credential_type_decoded is best-effort hex->ASCII (e.g. '4B5943' -> 'KYC'), null when bytes are not printable ASCII; issuer_label is XRPScan's accountName for the issuer when available.","institutional_issuer_count":"Count of distinct, non-self, XRPScan-labeled credential issuers accepted by this domain. 'Labeled' means XRPScan's accountName.name is populated for the issuer address - a cheap proxy for 'recognized stablecoin issuer / custodian / exchange / infrastructure operator'. Self-issued credentials (where issuer == owner_address) are intentionally excluded. Available in both /domains list view and drill-down.","institutional_issuers":"Sorted unique XRPScan display names of the issuers counted above (e.g. ['Quantoz', 'RLUSD', 'USDC']). Available in both list view and drill-down.","sequence":"On-chain sequence number used to derive the domain_id alongside the owner address","owner_node":"OwnerDirectory page index (XRPL bookkeeping)","previous_txn_id":"Tx hash that last modified this object","previous_txn_lgr_seq":"Ledger sequence of previous_txn_id","flags":"PermissionedDomain flags bitmap","lifecycle":"Drill-down only (null in /domains list view). Shape: {created_at_unix, created_at_iso, created_ledger, created_tx_id, last_modified_at_unix, last_modified_at_iso, last_modified_ledger, last_modified_tx_id, modification_count, lifecycle_status}. Derived by walking the meta chain backwards from PreviousTxnID to the CreatedNode (typically 1-4 tx lookups, capped at 12 hops). lifecycle_status is one of: complete, partial_history_truncated, partial_history_error, partial_history_chain_broken, no_last_txn_id. When status != complete, created_* fields may be null.","permissioned_market":"XLS-81 Permissioned DEX state. Drill-down only (null in /domains list view). Shape: {offer_count, amm_count, offers: [{sequence, taker_gets, taker_pays, flags, ledger_index}], amms: [{account, asset, asset2, ledger_index}], scope_note}. v1 enumerates owner-side offers/AMMs whose DomainID matches this domain. Permissioned offers/AMMs created by other accounts that reference this domain are not enumerated in v1 (would require a full-ledger walk). taker_gets / taker_pays follow XRPL conventions: drop string for XRP, {currency, issuer, value} object for IOUs.","identity":"Off-chain identity bridge for the domain owner. Drill-down only. Shape: {uri, did_document, data, ledger_index, toml_source_url, toml_org_name, toml_org_url, toml_description, toml_principals: [{name, email, twitter, ...}], toml_accounts_count}. Derived from the owner's DID ledger object (XLS-40); when the URI is a https .well-known/xrp-ledger.toml, the canonical XRPL identity manifest is fetched and parsed (6h cached). When the owner has not published a DID record, this field is null. uri / did_document / data are hex-decoded to strings."},"reserved_fields":{"member_count_estimate":"RESERVED for v2 (member-count methodology). Currently null on every record.","member_count_methodology":"RESERVED for v2.","member_count_confidence":"RESERVED for v2.","verified_attestation":"RESERVED for v2 (T.7 self-attested domain ownership). Currently null on every record.","health_score":"RESERVED. v1 ships descriptive only; no scoring. Field name reserved so it isn't reused for something else later."},"not_provided":["compliance_certification","domain_legitimacy_verdict","member_kyc_verification","credential_issuer_endorsement","regulatory_advice"],"payment":{"spec":"x402","x402_version":2,"scheme":"exact","network":"xrpl:0","facilitator_url":"https://xrpl-facilitator-mainnet.t54.ai","amount_usd":"0.1","currencies_accepted":["XRP"],"free_via_preview_token":"Browser-based callers from xrpl-utilities.com obtain a short-TTL JWT via the marketing site's Cloudflare Pages Function (Turnstile-gated) and attach it as Authorization: Bearer <jwt>; verified responses carry served_via: preview-token. No free path exists for non-browser clients - they pay via x402."},"pricing_policy":{"default":"$0.10 USD per call via x402, free for the browser-based marketing site via preview-token","data_availability_gate":"/domains, /credentials/issuers, and /scan-by-owner_address skip the x402 challenge while the materialized directory is empty (no owners have been seeded yet, or mainnet genuinely has 0 PermissionedDomain objects). Charging for an empty enumeration is bad incentive design; those endpoints flip to paid the moment the directory has at least one entry. /domain/{id} and /scan-by-domain_id stay paid because they hit ledger_entry directly and return useful results independent of snapshot state.","pricing_status_field":"Every response carries a `pricing_status` field with value `paid` or `free_until_data_available` so agents can detect the regime and decide whether to attach a PAYMENT-SIGNATURE."},"legal_notice":"ON-CHAIN PERMISSIONED DOMAIN DESCRIPTION ONLY. Not a compliance verdict, certification, or endorsement of any domain, owner, credential issuer, or member. Domain inclusion in this directory does not imply legitimacy; absence does not imply illegitimacy. Always do your own research and independently verify any domain or its credential issuers before transacting or extending credit.","cache_ttls_seconds":{"domains_list":300,"domain_record":60,"issuers":300,"labels":86400}}