Mask.ID Protect your identity. Prove your reputation.

The Mask.ID Attestation API

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.

The privacy model, in three rules

  1. Pairwise identity. You receive a subject_id minted for your site alone. Two sites can’t correlate their users; nothing about the member is recoverable from it.
  2. Ranges, not records. Sensitive quantities arrive as buckets — "1k–10k PIV", "active within 30 days", "25+" — never exact amounts, dates, or ranks that could single a member out.
  3. Member-granted, member-revoked. Every data point beyond the Trust Index requires the member’s explicit consent, and any grant can be revoked at any time — your access ends that moment.

Scope packs

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 What the member is asked to share
profile Profile basics 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 Aggregate referral strength: counts as ranges, your referrers' average Trust Index and verification rate. Never who they are.
reputation Trust Scores 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 How verified your social footprint is: coverage score, verified platform count, crypto-key linkage. Not which accounts.
commitment Commitment Economic commitment as ranges: Trust Capital score, holdings and coin-age buckets, tip and username-market activity. Never exact amounts or addresses.
mno Masternode owner Opt-in Reveal that you run a PIVX masternode.
location Location context Opt-in Your region (continent only), language, and UTC offset — never your country or city.
platforms Verified platforms 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.

Data points

Each row names the scope that carries it. Live ships today. Live · Opt-in is never pre-checked — the member must deliberately turn it on. Never available is a design guarantee, not a default: those rows can’t be requested, bought, or opted into.

Profile

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

Referrals

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

Trust Scores

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, Longevity reputation Live "identity_score": 84
“Real person” confidence (referrer average) reputation Live "real_person": 92
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
Would recommend / would work with again (share) reputation Live "recommend_pct": 95
Professional reputation (referrer average) reputation Live "professional_rep": 88
Any individual referrer's answers Never available

Online Presence

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

Trust Capital

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
Total commitment (own + backing) commitment Live "commitment": "1k–10k PIV"
Coin Age — all time commitment Live "coin_age_all": "10k–100k PIV-days"
Coin Age — prior 6 months commitment Live "coin_age_6mo": "1k–10k PIV-days"
Coin Age — prior 3 months commitment Live "coin_age_3mo": "1k–10k PIV-days"
Coin Age — prior 30 days commitment Live "coin_age_30d": "100–1k PIV-days"
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

Cross-site

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+"
Which sites those are Never available

The full picture — every live field at once

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", "mno", "location", "platforms"],
  "trust_index": 87,
  "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,
  "avg_years_known": "4 years",
  "met_in_person_pct": 40,
  "recommend_pct": 95,
  "professional_rep": 88,
  "presence_score": 75,
  "verified_platforms": 3,
  "crypto_linkage": true,
  "platforms": ["github", "x"],
  "oldest_identity": "5+ years",
  "capital_score": 61,
  "commitment": "1k–10k PIV",
  "coin_age_all": "10k–100k PIV-days",
  "coin_age_6mo": "1k–10k PIV-days",
  "coin_age_3mo": "1k–10k PIV-days",
  "coin_age_30d": "100–1k PIV-days",
  "backed": true,
  "tipped_by": "5+ members",
  "tipped": "10+ members",
  "parked_held": "3+",
  "names_bought": "1+",
  "names_sold": "1+",
  "attested_sites": "3+",
  "issued_at": "2026-08-14T15:02:09Z",
  "api": "…/api/attest/v1/subject/msub_…"
}

Edge cases your integration must expect

  • Absent fields are normal, not errors. A field is omitted when the member declined its scope, the value is unset, or a privacy floor withholds it. Code for presence, never for position or completeness.
  • "trust_scores": "gated" replaces the whole reputation pack while the member has fewer than ten referrers — informative in itself.
  • The subject read answers 404 identically for unknown, revoked, and malformed subjects — treat any 404 as “no longer verified,” and expect it the moment a member revokes.
  • Bucket values are display text ("1k–10k PIV", "25+") subject to refinement — compare for presence or equality, never parse them.
  • Webhook delivery retries a few times; any 2xx from you stops it. Verify-then-store must be idempotent per nonce.

How verification works

  1. Your site shows a verification request (QR + copyable string) to a user who clicked “Verify with Mask.ID”:
    {
      "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"]
    }
  2. The user reviews exactly what you’ll receive and approves it with a wallet signature on their Mask.ID.
  3. Mask.ID POSTs a signed response to your webhook (and/or returns the user to your 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_score": 78, "real_person": 92, "recommend_pct": 95,
      "commitment": "1k–10k PIV", "coin_age_all": "10k–100k PIV-days",
      "issued_at": "2026-08-13T14:02:09Z"
    }
  4. You verify one Ed25519 signature against the published platform key, store the subject_id, and may re-read the granted data while the member’s permission stands.

Endpoints

GET /.well-known/maskid-attest-key The Ed25519 verification key to pin. Currently key_id cdde5c8d68dbb162, public key 5REJlRin5SL5voivThSqUAqup7StIEpqauTQ38iOWgc.
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.

API keys & pricing

During the pilot, verification and the subject read are free and keyless. API keys, volume tiers, and self-serve signup will land on this page. Building something against this? We’d like to hear from you — use the Contact form in the footer.

Are you a Mask.ID member? The other half of this flow is yours: Verify Trust Index.