Let your users prove they are established, reputation-backed people — no email, no phone number, no bots. Your site receives the member’s Trust Index and, with their permission, the reputation evidence behind it. You never learn who they are on Mask.ID.
Quick start:
download the single-file example relying party —
maskid-example-rp.js
(Node 18+, zero dependencies). Run node maskid-example-rp.js,
open localhost:8080, and receive your first verified attestation
in redirect mode with nothing publicly hosted. It implements the entire
verify procedure documented below.
subject_id
minted for your site alone. Two sites
can’t correlate their users; nothing about the member is recoverable
from it.
"1k–10k PIV", "active within 30 days",
"25+"
— never exact
amounts, dates, or ranks that could single a member out.
Your request's scopes list names the packs below by id; the
member approves or unchecks each one at verification time. The Trust Index
itself rides every grant — no scope needed.
| Scope id | Name | Availability | What the member is asked to share |
|---|---|---|---|
profile |
Profile basics | Live | Broad account facts: profile type, that you cleared the real-person hurdle, account age and activity as ranges, Founding Member yes/no, invited yes/no. |
referrals |
Referrals | Live | Aggregate referral strength: counts as ranges, your referrers' average Trust Index and verification rate. Never who they are. |
reputation |
Trust Scores | Live | What your referrers said, averaged across all of them: real-person confidence, how well they know you, whether they'd recommend you. No individual answers. |
presence |
Online Presence | Live | How verified your social footprint is: coverage score, verified platform count, crypto-key linkage. Not which accounts. |
commitment |
Commitment | Live | Economic commitment as ranges: Trust Capital score, holdings and coin-age buckets, tip and username-market activity. Never exact amounts or addresses. |
humanity |
Humanity | Live | Two "is this a person?" confidences and a roll-up: what your referrers witnessed (real-person and one-operator confidence, weighted up by video, audio or in-person contact) and how costly your profile would be to fake (real-person hurdle, oldest verified identity, key linkage, backing). Never who vouched or what any one of them said. |
mno |
Masternode owner | Live · Opt-in | Reveal that you run a PIVX masternode. |
location |
Location context | Live · Opt-in | Your region (continent only), language, and UTC offset — never your country or city. |
platforms |
Verified platforms | Live · Opt-in | WHICH platforms you've verified (e.g. GitHub, X) — not your usernames on them. The combination is more identifying than the count alone. |
competence |
Confirmed fields | Live · Opt-in | The fields of work you listed on your profile that at least 3 of your referrers confirmed, with the share who vouched. Never who vouched. |
track_record |
Track record | Live · Opt-in | Counts of dealings that settled as agreed on other sites you've verified with — how many sites, how many people, and whether any were disputed. Never amounts, never which sites, never who. |
pay_link |
Payment link | Live · Opt-in | Creates a private payment page for this site — a fresh shielded address just for them, behind a random link. People there can pay you directly; the site and its visitors never see your username, balance, or other addresses. |
Each row names the scope that carries it. Live ships today. Live · Opt-in starts unchecked — the member must deliberately turn it on (the payment link is the one exception: it starts on, and the member may turn it off). Never available is a design guarantee, not a default: those rows can’t be requested, bought, or opted into.
The identity surface. Names, images, and free text never cross the API; dates and ranks travel only as ranges.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Trust Index (0–100) | always | Live |
"trust_index": 87
|
| Trust Index tier — unproven · low · building · trusted (the platform's own bands) | always | Live |
"trust_index_tier": "trusted"
|
| Profile type |
profile
|
Live |
"profile_type": "individual"
|
| Real-person hurdle cleared (anti-sybil gate) |
profile
|
Live |
"earned_username": true
|
| Account age |
profile
|
Live |
"account_age": "1–2 years"
|
| Recently active |
profile
|
Live |
"active_within": "30 days"
|
| Founding Member |
profile
|
Live |
"founding_member": true
|
| Invited by an existing member |
profile
|
Live |
"invited": true
|
| Masternode owner |
mno
|
Live · Opt-in |
"mno_verified": true
|
| Region / language / timezone |
location
|
Live · Opt-in |
"region": "North America"
|
| Username, Mask ID, display name, bio, avatar | — | Never available | — |
| Member number, exact join date, exact last-seen time | — | Never available | — |
Aggregates over the member's referral graph. The graph itself — who vouched for whom — is never exposed, in any direction.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Referrals pillar score (0–100) |
referrals
|
Live |
"referrals_score": 72
|
| Accepted referrals received |
referrals
|
Live |
"referrals_received": "25+"
|
| Accepted referrals given |
referrals
|
Live |
"referrals_given": "10+"
|
| Average Trust Index of referrers |
referrals
|
Live |
"referrer_avg_ti": 64
|
| Share of referrers with verified platforms |
referrals
|
Live |
"referrers_verified_pct": 80
|
| New referral accepted in the last 90 days |
referrals
|
Live |
"referral_recent": true
|
| Who referred whom — names, dates, notes, answers, connection paths | — | Never available | — |
Averages of what referrers actually answered — computed only once ten or more referrers exist, so no individual answer is ever recoverable.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Overall Trust Score + tier |
reputation
|
Live |
"trust_score": 78, "trust_tier": "Established"
|
| Section scores — Confidence, Relationship, Identity, Reputation, Trust-with, Longevity |
reputation
|
Live |
"identity_score": 84
|
| “Real person” confidence (referrer average) |
reputation
|
Live |
"real_person": 92
|
| “Identity has stayed consistent” (referrer average) |
reputation
|
Live |
"identity_consistent": 90
|
| “The Mask ID belongs to them” confidence (referrer average) |
reputation
|
Live |
"owns_user_id": 85
|
| How well referrers know them (referrer average) |
reputation
|
Live |
"familiarity": 80
|
| In what capacity referrers know them (share per bucket; all-that-apply) |
reputation
|
Live |
"capacity_mix": {"colleague": 40, "client": 60, "community": 30}
|
| Still in contact this year (share of referrers) |
reputation
|
Live |
"active_relationship_pct": 80
|
| Known 5+ years and still in contact (share of referrers) |
reputation
|
Live |
"long_standing_current_pct": 30
|
| Would trust them with money (share of referrers who answered) |
reputation
|
Live |
"trust_money_pct": 80
|
| Would trust them with their home, vehicle or belongings (share) |
reputation
|
Live |
"trust_property_pct": 70
|
| Would trust them with the care of a person or animal (share) |
reputation
|
Live |
"trust_care_pct": 60
|
| Would trust their advice in their field (share) |
reputation
|
Live |
"trust_advice_pct": 90
|
| Would meet them alone in person (share) |
reputation
|
Live |
"trust_meet_pct": 90
|
| In contact weekly or more (share of referrers) |
reputation
|
Live |
"frequent_contact_pct": 50
|
| Have exchanged money or goods with them (share) |
reputation
|
Live |
"transacted_pct": 60
|
| Transactions went as agreed (share of those who transacted) |
reputation
|
Live |
"settled_as_agreed_pct": 90
|
| “One person controls this account” confidence (referrer average) |
reputation
|
Live |
"sole_operator": 90
|
| Respectful and civil (referrer average) |
reputation
|
Live |
"conduct": 95
|
| Responds and communicates clearly (referrer average) |
reputation
|
Live |
"responsiveness": 85
|
| Average familiarity / years known |
reputation
|
Live |
"avg_years_known": "4 years"
|
| Met in person / communicated directly (share of referrers) |
reputation
|
Live |
"met_in_person_pct": 40
|
| Video calls (share of referrers) |
reputation
|
Live |
"video_calls_pct": 60
|
| Audio calls (share of referrers) |
reputation
|
Live |
"audio_calls_pct": 40
|
| Completed a project together (share of referrers) |
reputation
|
Live |
"project_together_pct": 50
|
| Would recommend / would work with again (share) |
reputation
|
Live |
"recommend_pct": 95
|
| Professional reputation (referrer average) |
reputation
|
Live |
"professional_rep": 88
|
| Reliability as a person — shows up, keeps their word (referrer average) |
reputation
|
Live |
"personal_reliability": 85
|
| Commitment reliability — do they do what they say (referrer average) |
reputation
|
Live |
"commitment_reliability": 85
|
| Confirmed fields of work (≥3 referrers vouched; share who vouched) |
competence
|
Live · Opt-in |
"competence": [{"code": "software.web", "domain": "Software & IT", "subdomain": "Web development", "endorsed_pct": 60}]
|
| Any individual referrer's answers | — | Never available | — |
How much of the member's social footprint is cryptographically verified — never which accounts.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Coverage score (0–100) |
presence
|
Live |
"presence_score": 75
|
| Verified platform count |
presence
|
Live |
"verified_platforms": 3
|
| Cryptographic key linkage (Nostr / Vector) |
presence
|
Live |
"crypto_linkage": true
|
| Which platforms are verified |
platforms
|
Live · Opt-in |
"platforms": ["github", "x"]
|
| Oldest verified identity |
presence
|
Live |
"oldest_identity": "5+ years"
|
| Platform usernames, account names, profile URLs | — | Never available | — |
Economic commitment behind the identity. Always ranges: an exact balance would identify the wallet on-chain, which is why exactness is never offered.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Trust Capital pillar score (0–100) |
commitment
|
Live |
"capital_score": 61
|
| Per-coin holdings + Coin Age, keyed by chain — native units, never FX |
commitment
|
Live |
"capital": {
"pivx": {"unit": "PIV", "commitment": "1k–10k", "coin_age_all": "10k–100k",
"coin_age_6mo": "10k–100k", "coin_age_3mo": "1k–10k", "coin_age_30d": "100–1k"}
}
|
| Backing exists (referrers stake PIV behind them) |
commitment
|
Live |
"backed": true
|
| Tips received (distinct members) |
commitment
|
Live |
"tipped_by": "5+ members"
|
| Tips given (distinct members) |
commitment
|
Live |
"tipped": "10+ members"
|
| Parked Usernames held |
commitment
|
Live |
"parked_held": "3+"
|
| Usernames bought (lifetime) |
commitment
|
Live |
"names_bought": "1+"
|
| Usernames sold (lifetime) |
commitment
|
Live |
"names_sold": "1+"
|
| Which usernames — held, bought, or sold | — | Never available | — |
| Exact balances, amounts, addresses, transactions | — | Never available | — |
Is this a person? Two variables and a roll-up. Witnessed = people vouched. Costly = a bot could do this, but it wouldn't be cheap. Use human_confidence if you only want one number.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Witnessed (0–100): referrers' real-person and one-operator confidence, weighted up by video, audio or in-person contact. Absent below the 10-referrer threshold. |
humanity
|
Live |
"human_witnessed": 90
|
| Costly to fake (0–100): real-person hurdle, age of the oldest verified outside identity, cryptographic key linkage, PIV backing, and cross-site history (sites active in 90 days). Cost, not proof; available day one. |
humanity
|
Live |
"human_costly": 55
|
| Combined (0–100): Witnessed where it exists, else Costly capped at 60 so an unwitnessed profile never reads as confirmed. The one field to use if you want one. |
humanity
|
Live |
"human_confidence": 90
|
| A human/bot verdict — these are confidences, never a label | — | Never available | — |
| Which referrers vouched, or what any one of them answered | — | Never available | — |
Reputation earned through this API itself — a network signal no single site can see alone.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Verified on other sites via this API |
commitment
|
Live |
"attested_sites": "3+"
|
| Other sites that re-read this member in the last 30 days (a re-read is a "session": the site checked them, typically at login). Never which sites. |
commitment
|
Live |
"active_sites_30d": "1+"
|
| Same, over 90 days — cross-site history is the best bot signal we hold. |
commitment
|
Live |
"active_sites_90d": "3+"
|
| Which sites those are | — | Never available | — |
Conduct reported by other sites the member verified with — dealings that settled as agreed, as counts of sites and people. Only sites with standing count, so a member's own fork moves nothing. Opt-in, and never an amount.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Sites with standing where dealings settled as agreed (a site earns standing by age and real members, so a member's own fork counts for nothing). |
track_record
|
Live · Opt-in |
"settled_sites": "1+"
|
| Distinct people dealt with, across those sites (a pair counts once per site). |
track_record
|
Live · Opt-in |
"settled_counterparties": "5+"
|
| Present (true) once at least five dealings settled and none were disputed; absent otherwise — never false. A negative only ever removes a positive. |
track_record
|
Live · Opt-in |
"dispute_free": true
|
| Amounts, prices, currencies, or totals | — | Never available | — |
| Which sites, which counterparties, or when | — | Never available | — |
| Disputes or flags as a number — a negative only removes a positive | — | Never available | — |
A verified payment endpoint, not payment processing. The pay link resolves to a fresh shielded address derived for your site alone; payments are peer-to-peer on-chain, and Mask.ID is never in the flow of funds.
| Data point | Scope | Availability | Example |
|---|---|---|---|
| Verified payment page (pairwise pay link) |
pay_link
|
Live · Opt-in |
"pay_link": "https://app.mask.id/pay/hTgkxGkYyBWJow0KrTppBQ"
|
| The member's wallet addresses or balances | — | Never available | — |
| Any payment, amount, or transaction history | — | Never available | — |
| The same pay address on any other site — links are pairwise, like subject IDs | — | Never available | — |
A response with every pack and opt-in granted (generated from the same catalog the server builds payloads from; multi-value rows show a representative key). Real responses carry only the granted, statable fields.
{
"v": 1,
"type": "maskid.attestation",
"key_id": "…", "subject_id": "msub_…",
"rp_host": "your-site.example", "rp_user_id": "u_8347", "nonce": "…",
"scopes": ["trust_index", "profile", "referrals", "reputation",
"presence", "commitment", "humanity", "mno", "location",
"platforms", "pay_link"],
"trust_index": 87, "trust_index_tier": "trusted",
"profile_type": "individual",
"earned_username": true,
"account_age": "1–2 years",
"active_within": "30 days",
"founding_member": true,
"invited": true,
"mno_verified": true,
"region": "North America",
"referrals_score": 72,
"referrals_received": "25+",
"referrals_given": "10+",
"referrer_avg_ti": 64,
"referrers_verified_pct": 80,
"referral_recent": true,
"trust_score": 78, "trust_tier": "Established",
"identity_score": 84,
"real_person": 92,
"identity_consistent": 90,
"owns_user_id": 85,
"familiarity": 80,
"capacity_mix": {"colleague": 40, "client": 60, "community": 30},
"active_relationship_pct": 80,
"long_standing_current_pct": 30,
"trust_money_pct": 80,
"trust_property_pct": 70,
"trust_care_pct": 60,
"trust_advice_pct": 90,
"trust_meet_pct": 90,
"frequent_contact_pct": 50,
"transacted_pct": 60,
"settled_as_agreed_pct": 90,
"sole_operator": 90,
"conduct": 95,
"responsiveness": 85,
"avg_years_known": "4 years",
"met_in_person_pct": 40,
"video_calls_pct": 60,
"audio_calls_pct": 40,
"project_together_pct": 50,
"recommend_pct": 95,
"professional_rep": 88,
"personal_reliability": 85,
"commitment_reliability": 85,
"presence_score": 75,
"verified_platforms": 3,
"crypto_linkage": true,
"platforms": ["github", "x"],
"oldest_identity": "5+ years",
"capital_score": 61,
"capital": {
"pivx": {"unit": "PIV", "commitment": "1k–10k", "coin_age_all": "10k–100k",
"coin_age_6mo": "10k–100k", "coin_age_3mo": "1k–10k", "coin_age_30d": "100–1k"}
},
"backed": true,
"tipped_by": "5+ members",
"tipped": "10+ members",
"parked_held": "3+",
"names_bought": "1+",
"names_sold": "1+",
"attested_sites": "3+",
"active_sites_30d": "1+",
"active_sites_90d": "3+",
"settled_sites": "1+",
"settled_counterparties": "5+",
"dispute_free": true,
"human_witnessed": 90,
"human_costly": 55,
"human_confidence": 90,
"competence": [{"code": "software.web", "domain": "Software & IT", "subdomain": "Web development", "endorsed_pct": 60}],
"pay_link": "https://app.mask.id/pay/hTgkxGkYyBWJow0KrTppBQ",
"issued_at": "2026-08-14T15:02:09Z",
"api": "…/api/attest/v1/subject/msub_…"
}
"trust_scores": "gated"
replaces the whole reputation pack while the member has fewer than ten
referrers — informative in itself.
subject_id, not the account.
It is stable for a member on your site: a member who revokes and later
re-verifies receives the same subject_id, so a ban
you keyed on it holds across revoke-and-rejoin. Getting a fresh one takes
a whole new Mask.ID identity — the cost your tier gate sets.
"1k–10k PIV", "25+") subject to
refinement — compare for presence or equality, never parse them.
{
"v": 1,
"rp_user_id": "u_8347",
"nonce": "d41d8cd98f00b204e9800998",
"webhook": "https://your-site.example/maskid/callback",
"redirect": "https://your-site.example/settings/verified",
"scopes": ["trust_index", "reputation", "commitment"]
}
redirect
URL carrying the same response): {
"v": 1,
"type": "maskid.attestation",
"subject_id": "msub_k5r2…",
"rp_user_id": "u_8347",
"nonce": "d41d8cd98f00b204e9800998",
"scopes": ["trust_index", "reputation", "commitment"],
"trust_index": 87, "trust_index_tier": "trusted",
"trust_score": 78, "real_person": 92, "recommend_pct": 95,
"capital": {"pivx": {"unit": "PIV", "commitment": "1k–10k", "coin_age_all": "10k–100k"}},
"issued_at": "2026-08-13T14:02:09Z"
}
subject_id, and may re-read the granted data while the
member’s permission stands.
GET /.well-known/maskid-attest-key |
The Ed25519 verification key to pin. Currently key_id cdde5c8d68dbb162, public key 5REJlRin5SL5voivThSqUAqup7StIEpqauTQ38iOWgc.
|
Nostr (no endpoint) |
For members who opt in, Mask.ID’s Nostr key npub1uhq0ye3a9pjgml864ml38lenthgeuq2z0l3rh2pspl6wqrv8qrjq2mcrhf
(NIP-05 _@mask.id) publishes their Trust Index tier
as a
NIP-85 kind 30382
assertion (d
= the member’s
pubkey; tags tier, username, NIP-32 label mask.id) plus NIP-58 badges for Building and Trusted. Read it from
any relay; verify the signature against that key. Tier only — no number,
no addresses.
|
GET /api/attest/v1/subject/:subject_id |
Re-read a verified member’s granted data. Answers 404 once the member revokes. Rate-limited; cache and poll gently. |
Today, during the pilot, everything on this page is free and keyless — verification, webhooks, and the subject read. When API keys ship, pricing will meter monthly active verified members. The tier schedule, discounts, founding-site terms, and the free community tier live on the pricing page. Building against the API? We’d like to hear from you (Contact form in the footer) — early integrators get the founding-site terms.
Are you a Mask.ID member? The other half of this flow is yours: Verify Trust Index.