Developer docs
Proof of a real human, in one request.
Patina turns the history in accounts a person already owns into a score out of 100, high only when there are real years of history behind it. You can read that score, signed and verifiable, for anyone with a public Patina profile. No API key, no OAuth, one GET.
What it is good for
Sybil resistance without KYC or biometrics: airdrops, quadratic funding, DAO votes, gated betas, one-human-one-vote. A fresh wallet is free; a decade of ordinary digital life is not, and the score is exactly how much of that history it can prove. Use it as a signal or a gate, say, only wallets whose owner scores above 40.
The endpoint
Public and CORS-open, so you can call it straight from a browser or a backend.
GET https://patinadata.xyz/api/verify/{username}Returns 404 if nobody holds that name. Otherwise:
{
"username": "alice",
"score": 83,
"verdict": "Deeply worn in",
"oldestYear": 2013,
"sourcesConnected": ["youtube", "github", "linkedin", "spotify"],
"components": [
{ "key": "age", "label": "Age", "points": 38.4, "max": 40, "detail": "..." },
{ "key": "corroboration", "label": "Corroboration", "points": 17, "max": 20, "detail": "..." }
],
"issuedAt": "2026-08-01T12:00:00.000Z",
"attestation": {
"app": "0x620dDbEceaD28Bbf1b979bfaB8e3a7B893aa54A1",
"message": "Patina score attestation\n\nusername: alice\nscore: 83/100\n...",
"signature": "0x…",
"howToVerify": "Recover the EIP-191 signer of `message` from `signature`; it equals `app`."
}
}Verify the signature
This is the part that matters: don't trust our JSON, check the signature. Every response carries an attestation signed by Patina's app key. Recover the signer from the message and signature and confirm it equals Patina's public address. If it does, the score is genuinely ours and has not been altered, and you never had to trust this server.
Patina's app address
0x620dDbEceaD28Bbf1b979bfaB8e3a7B893aa54A1viem
import { recoverMessageAddress } from "viem";
const res = await fetch("https://patinadata.xyz/api/verify/alice");
const { score, attestation } = await res.json();
const signer = await recoverMessageAddress({
message: attestation.message,
signature: attestation.signature,
});
// True only if Patina really signed this exact score.
const genuine = signer.toLowerCase() === attestation.app.toLowerCase();ethers
import { verifyMessage } from "ethers";
const signer = verifyMessage(attestation.message, attestation.signature);
const genuine = signer.toLowerCase() === attestation.app.toLowerCase();Prefer to see it work before you write any code? The standalone checker runs the same recovery in your browser, with no call back to Patina.
Embed a verified badge
A live SVG badge for any public profile, drop it on a site, a README, or a bio. It reads current and links back to the proof.
HTML
<a href="https://patinadata.xyz/verify?u=alice">
<img src="https://patinadata.xyz/api/badge/alice" alt="Patina verified" height="30" />
</a>Markdown
[](https://patinadata.xyz/verify?u=alice)The fields
- score
- 0–100. Age and corroboration (whether independent sources agree on how far back you go) are 60 of it; depth, standing and breadth make up the rest and only count when real history backs them. The full model is on the home page.
- components
- The breakdown, each with its points, max, and a plain-English reason. Show it, or reduce it to a single number, it is your call.
- oldestYear
- The earliest year Patina can prove across every connected source, or null.
- issuedAt
- When this attestation was signed. Scores rise as people connect more, so an attestation is a snapshot, re-fetch for a fresh one.
Good to know
- Only people who have chosen a public username are verifiable, the same data as their public card.
- No key and no rate limit today, but be reasonable; the score changes slowly, so cache it.
- The signature is a plain EIP-191 message, so any Ethereum library verifies it, on-chain or off.
From an AI agent
Patina runs an MCP server, so Claude, ChatGPT and anything else that speaks the protocol can read a score mid-conversation. Same data as the endpoint above, same lack of an API key, with tools for the two questions an agent actually asks: what is this person's score, and do they clear a bar.
https://patinadata.xyz/api/mcpSetup for each client, and what the tools do and deliberately do not return, is on the MCP page.
Pricing
Patina is free for individuals and free to start building on. Businesses that verify humans at volume pay for it, and that is how Patina makes money. No card to try it.
Your own score, card and story. No wallet, no card, free for good.
Read any public score. No key, CORS-open, generous limits while you build.
Volume reads, uptime commitments and support. Talk to us when you scale.
Try it live at /verify, or ask in the Vana Discord.