veil

Look up a card

Find the card that holds one exact account, key or fingerprint.

GET/v1/lookup
Access
Public; API key optional
Client
Browser fetch supported

Parameters#

NameLocationMeaning
discordQueryStable numeric Discord user ID, 17 to 20 digits.
githubQueryNumeric GitHub account ID, not its login name.
emailQueryThe complete email address.
domainQueryExact domain, without a final dot. International domains use their ASCII A-label.
fediverseQueryThe complete @user@server account.
keyQueryAn Ed25519 public key in hex or the full composite public key in base64. Also a public key from elsewhere as you would paste it: an OpenSSH line with or without comment, an armoured OpenPGP public key, a minisign public key, an ML-DSA key in base64. URL-encode the value.
fingerprintQueryThe 12 words in English or Italian, or the 60 digits. Also the fingerprint of a public key from elsewhere: SHA256:… as ssh-keygen -l prints it, a minisign key ID in 16 hex digits, or the 40 hex digits of an OpenPGP fingerprint, in either case, with or without spaces or 0x. An OpenPGP key ID is not enough.

Request examples#

cURL
curl -fsS 'https://veil.rip/v1/lookup?key=73ad6159583a43f8ad230a215b758db680efcd3ce32ab8e83c622eeca883e68a'
javascript
const response = await fetch("https://veil.rip/v1/lookup?key=73ad6159583a43f8ad230a215b758db680efcd3ce32ab8e83c622eeca883e68a");
const result = await response.json();

Try the request#

Response#

HTTP 200application/json

identity is the short card. match gives the normalised query. takeover describes a pending account transfer when present. Fetch the full card for its proof.

FieldTypeMeaning
identityCardLiteMatching short card, without an inclusion proof.
matchobjectby names the lookup parameter; value is its normalised value. For a public key from elsewhere, value is its fingerprint and external gives type, fp, label and addedIn.
takeoverobject | nullPending transfer with toIdentity, openedAt and resolvesAt. Null if none.
alertobject | optionalWhen the card’s owner declared the account looked up stolen, abandoned or moved and has not declared it regained: platform, subject, display, state, since, to, logIndex, publishedAt. Show it before anything else. The server’s word: the card’s page checks it.

Expand a nested object for its fields. Types ending in null allow a null value; optional fields may be absent. Other fields are present in that object.

Short card CardLite
FieldTypeMeaning
nintegerPermanent card number.
urlstringPermanent URL using the card number.
namestringCurrent display name; a hidden name becomes Card followed by its number.
initialsstringInitials for an image fallback.
sincestringVersion-one date in YYYY-MM-DD UTC.
idstringVersion-one commitment in hex; the source of the fingerprint.
versionintegerCurrent published version.
keysarray<CardKey>All device and recovery keys, including revoked keys.
linksarray<CardLink>Linked accounts and pending takeovers.
fingerprintFingerprintTwelve words in each language and twelve five-digit groups.
typestringperson or organization.
nameHiddenbooleanWhether staff hide the name.
logoobject, optionalImage type and URL; omitted without a visible image.
aliasstring | nullCurrent alias; it can change.
aliasUrlstring | nullCurrent alias address. Use n as the permanent identifier.
Device key CardKey
FieldTypeMeaning
idstringDevice label shown on the card.
algstringReadable algorithm name.
fpstringFull public key as stored in the signed record.
ed25519stringEd25519 key or composite-key half, in hex.
sincestringDate the key was added.
statestringactive, offline or revoked. Offline denotes a recovery key.
revokedstring | nullRevocation date, when revoked.
rolestringSigning role assigned to the key.
addedInintegerVersion that added the key.
revokedIninteger | nullVersion that revoked the key.
Linked account CardLink
FieldTypeMeaning
servicestringPlatform identifier.
handlestringDisplay handle or normalised account.
idstring | nullStable provider ID, when separate from the handle.
howstringProof method, such as oauth, dns_txt, well_known, emailCode or backlink.
atstringTime the link was established.
statestringactive or pending.
untilstring | nullPending takeover deadline.
takeoverinteger | nullPending takeover ID.
unicodestring, optionalUnicode spelling of an international domain. Keep the ASCII handle as the identifier.
addedIninteger | nullVersion that added the link.
logIndexinteger | nullZero-based log index of that version.
checkCardLinkCheck, optionalThe server’s periodic re-check of the proof (since 30 October 2026), for an active domain, Fediverse or GitHub link it has checked at least once. Its word, not part of the signed card.
Re-check of a proof CardLinkCheck
FieldTypeMeaning
statestringok, failing (the place answered and the proof is not there) or unreachable (no answer).
atstringTime of the last check that got an answer.
sincestring, optionalSince when the proof has not confirmed. Absent while ok.
reportedbooleanTrue once 30 days passed without a confirmation and the owner was told. The link stays.
Card fingerprint Fingerprint
FieldTypeMeaning
wordsobjecten and it each contain the same twelve word-list positions in their language.
digitsarray<string>Twelve groups of five decimal digits.

Response headers#

HeaderValueMeaning
Content-Typeapplication/jsonUse the declared media type before choosing a parser.
DateHTTP dateServer time. Compare it with your clock when signing requests.
Retry-Afterinteger seconds, on rate_limited or busyWait at least this long before retrying. Other 429/503 codes do not necessarily include it.

What to verify#

Resolve the number, then verify the full card and the matched account in its signed record.

Usage notes#

  • Supply exactly one query parameter. Display names are not unique.

Errors#

API errors return an error object. Use error.code for program logic; error.message is English text for people and can change. Response and error guide

HTTPCodeMeaning and next step
400invalid_parameter

A path, query or body field is missing, malformed or outside its accepted range.

Correct the field named in error.message before sending again.

404not_found

The requested card, key, alias, code or resource was not found.

Check the identifier. Temporary codes and previews may already have expired or been used.

When using an optional API key
HTTPCodeMeaning and next step
401invalid_api_key

The bearer credential is malformed, unknown, expired or revoked.

Use an active key. To use anonymous public access, remove Authorization entirely. Invalid credentials never fall back automatically.

403api_key_scope

The API key lacks read or verify scope, or the endpoint does not accept bearer keys.

Use the correct scope. Identity writes and key management still require a device signature.

403api_key_suspended

This API key is suspended.

Ask staff to restore it; another key cannot lift an account suspension.

403developer_suspended

The owner’s API account is suspended or the owner card is unavailable.

Check the owner account and any staff restriction. Creating another key does not bypass suspension.

Shared request errors
HTTPCodeMeaning and next step
429rate_limited

An anonymous, signed-request or API-key allowance was exceeded.

Wait at least Retry-After seconds. Share a queue and retry budget across your workers.

500internal_error

An unexpected server error occurred. Internal details are not returned.

Retry reads with bounded backoff. Check write results before sending a new signed operation.

503busy

The application has reached a temporary concurrency or database limit.

Wait Retry-After seconds and retry with bounded backoff.