{"schema_version":"2026-40","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","list_operators_index":"GET /permissioned-domains/operators/index?limit=&offset=&status=all|in_use|active  (free, lightweight rollup)","list_operators":"GET /permissioned-domains/operators?limit=&offset=&status=all|in_use|active  (paid full rollup)","operator_drilldown":"GET /permissioned-domains/operators/{operator_address}","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, the owner's on-chain objects are fetched once (O(1)) and the domain is upserted into the snapshot inline. Closes the new-owner gap without any whole-ledger walk.","incremental_refresh":"The incremental loop re-polls on-chain owner state on a recurring cadence and updates only the domains that changed (O(known_owners) calls per pass).","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. Operator-only: requires X-Admin-Key header matching the admin secret (per-call upstream RPC cost makes anonymous access an abuse vector).","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 full-ledger enumeration path; that was retired in 2026-13 because the server-side type filter still scans the full ledger and burned significant upstream credits per day. Per-domain drill-down (/domain/{id}) uses a single ledger-entry lookup 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, has_toml, ipfs_did_uri, did_method, verification_method_count, service_endpoint_count}. Two resolution paths: (1) any of uri/did_document/data points at a https .well-known/xrp-ledger.toml, which is fetched and parsed (6h cached); (2) any field is an ipfs://<cid> reference to a W3C DID Document JSON, which is fetched via the public gateway and summarized into did_method + verification_method_count. If the IPFS DID Document carries a service block pointing at a TOML, that TOML is fetched too. has_toml is True only when TOML metadata is actually populated. When the owner has not published a DID record at all, this field is null. uri / did_document / data are hex-decoded to strings.","identity_tier":"Six-tier classification of the domain owner's identity (added credential_attributed in 2026-40). Present on every list row and drill-down. Values: 'institutional' (TOML resolved + org_name + principals_count > 0 + org_url present — the highest tier, used for named-entity-with-principals operators like xrp-liquid); 'named_entity' (TOML resolved + org_name, but thinner — missing principals or org_url); 'funder_attributed' (no DID/TOML on chain, but the auto-walker has an XRPScan-verified well-known label on the parent funder and likely_retail is false — used for CEX-onboarded institutional operators like Bitso/EURØP and Kraken/EUROP_Approved that haven't published a TOML yet, added 2026-39); 'credential_attributed' (no funder well-known either, but the operator explicitly nominates a verified XRPScan well-known issuer in their accepted_credentials — catches venues like XSpenceKYC that attribute via the credential-issuer mechanism instead of the funder chain, added 2026-40; subject-side trustline path was tried and rolled back because it false-fired on real multi-asset KYC venues); 'did_only' (DID record exists on chain but no TOML or walker attribution); 'anonymous' (no DID AND no walker attribution path clears the bar).","jurisdiction":"ISO-3166-1 alpha-2 country code (string, 2 chars) attributed to the entity operating this address, or null when no reliable signal is available. Present on every /domains row, /domain/{id} drill-down, and /credentials/issuers row. Inferred in priority order from (1) the operator-curated KNOWN_JURISDICTIONS map (covers named XRPL entities like Ripple/Ondo/Braza/Schuman/Archax/xrp-liquid where corporate jurisdiction is established but the TOML lives on a gTLD), (2) issuer self-attestation via a `country = \"XX\"` field in the TOML METADATA block — lets a new entity auto-resolve with no operator action, (3) the ccTLD of the entity's TOML source_url or org_url when published, (4) the ccTLD of XRPScan's resolved domain field. gTLDs (.com, .org, .io, .net, .dev, .xyz, .app, .finance, .digital) and ambiguous country-as-vanity TLDs (.io, .ai sold commercially) are explicitly NOT inferred from — null is honest when no ccTLD signal exists. Cross-portfolio rollup at GET /jurisdictions, including a per-address unattributed list for operator review.","operator_address":"Per-operator rollup field. Classic XRPL address that has either issued at least one credential (CredentialCreate.account) or owns at least one PermissionedDomain ledger object. The two sets typically overlap.","credentials_issued_total":"Per-operator: count of CredentialCreate events emitted by this account, lifetime within Trust's events table.","credentials_accepted_by_subjects":"Per-operator: count of CredentialAccept events from subjects activating credentials this operator issued. Resolved via payload.issuer (post-2026-17 events) with fallback to (subject, credential_type) -> Create.account index for older events.","credentials_revoked":"Per-operator: count of CredentialDelete events attributable to this operator (issuer-side or subject-side; either party can call CredentialDelete per XLS-70).","credentials_outstanding":"Per-operator: max(0, credentials_issued_total - credentials_revoked). Best-effort estimate of the size of this operator's active allowlist.","unique_subjects_count":"Per-operator: distinct subject addresses appearing in CredentialCreate events emitted by this operator.","credential_types":"Per-operator: sorted list of distinct credential_type hex values this operator has minted.","first_seen_unix":"Per-operator: Unix timestamp of the operator's earliest captured lifecycle event. Lower-bound — predates Trust's events table only when /admin/seed was used.","last_active_unix":"Per-operator: Unix timestamp of the operator's most recent captured lifecycle event. Used as the default sort key on the /permissioned-domains/operators rollup.","subject_breakdown":"Per-operator drill-down only. Array of {credential_type, credential_type_decoded, subject_count, subjects: [...]} grouped by credential_type and built from the operator's CredentialCreate events.","recent_events":"Per-operator drill-down only. Last 200 lifecycle events attributable to this operator (event.account match OR payload.issuer match), newest first."},"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, /permissioned-domains/operators, 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}, /permissioned-domains/operators/{address}, and /scan-by-domain_id stay paid because they hit ledger_entry / event drill-down 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,"operators":300,"labels":86400}}