{"revision":"0ed62d2c742f8e20","language":"en","entry":{"id":"contact-file","kind":"endpoint","group":"share","title":"Save a card as a contact","method":"GET","path":"/u/{card}.vcf","paths":[],"summary":"Download a person’s card as a vCard for a phone or a mail client: the name, the card’s address, the verified accounts and the 12 words.","response":"A vCard 4.0 (text/vcard): FN and N with the card’s name, UID and URL with the card’s permanent address (and its alias), EMAIL for each verified email address, URL for each verified GitHub, Discord, domain and Fediverse account, PHOTO with the profile picture (a small PNG inline, or a GIF by address), NOTE with the 12-word fingerprint and where to check it, REV and SOURCE.","parameters":[{"name":"card","description":"A person’s permanent card number or its current alias.","in":"path","required":true},{"name":"lang","description":"en or it: the note’s words and the fingerprint’s word list. English is the default.","in":"query","required":false}],"sample":"/u/1.vcf","access":"public","base":"directory","notes":["The file is the server’s word, built from the same data as the card’s previews. Its note says so, and names the card where the check runs in the reader’s browser.","Only for a card shown as it is: never for one that is suspended, closed or removed, or whose name the Veil staff hid. Organisations have no contact file.","No platform the directory links today has a standard instant-messaging address, so the file has no IMPP line: Discord, GitHub, a domain and the Fediverse are profile URLs."],"errors":["401 invalid_api_key","403 api_key_scope","403 api_key_suspended","403 developer_suspended","404 not_found","410 erased","429 rate_limited","500 internal_error","503 busy"],"related":["person-card","card-image","external-keys-file","sharing"],"sections":[{"kind":"code","language":"shell","code":"curl -fsS -o veil-1.vcf 'https://veil.rip/u/1.vcf'"}],"verify":"Before you trust a saved contact for anything that matters, open the card it names and compare the 12 words with the ones in the note: the card checks its keys in your browser, the file does not.","live":false,"responses":[{"status":200,"contentType":"text/vcard","description":"A vCard 4.0 (text/vcard): FN and N with the card’s name, UID and URL with the card’s permanent address (and its alias), EMAIL for each verified email address, URL for each verified GitHub, Discord, domain and Fediverse account, PHOTO with the profile picture (a small PNG inline, or a GIF by address), NOTE with the 12-word fingerprint and where to check it, REV and SOURCE.","fields":[]}],"responseObjects":[],"errorFormat":"json","errorDetails":[{"status":401,"code":"invalid_api_key","description":"The bearer credential is malformed, unknown, expired or revoked.","action":"Use an active key. To use anonymous public access, remove `Authorization` entirely. Invalid credentials never fall back automatically.","scope":"optional-api-key"},{"status":403,"code":"api_key_scope","description":"The API key lacks read or verify scope, or the endpoint does not accept bearer keys.","action":"Use the correct scope. Identity writes and key management still require a device signature.","scope":"optional-api-key"},{"status":403,"code":"api_key_suspended","description":"This API key is suspended.","action":"Ask staff to restore it; another key cannot lift an account suspension.","scope":"optional-api-key"},{"status":403,"code":"developer_suspended","description":"The owner’s API account is suspended or the owner card is unavailable.","action":"Check the owner account and any staff restriction. Creating another key does not bypass suspension.","scope":"optional-api-key"},{"status":404,"code":"not_found","description":"No person card has this number or alias; or the card is an organisation, is suspended, or has its name hidden by the Veil staff, so it has no contact file.","action":"Open the card to see its state. A contact file comes back once the card is shown as it is again.","scope":"endpoint"},{"status":410,"code":"erased","description":"The card was closed or removed, so it has no contact file.","action":"Remove the contact you saved from it, or mark it as closed.","scope":"endpoint"},{"status":429,"code":"rate_limited","description":"An anonymous, signed-request or API-key allowance was exceeded.","action":"Wait at least `Retry-After` seconds. Share a queue and retry budget across your workers.","scope":"common"},{"status":500,"code":"internal_error","description":"An unexpected server error occurred. Internal details are not returned.","action":"Retry reads with bounded backoff. Check write results before sending a new signed operation.","scope":"common"},{"status":503,"code":"busy","description":"The application has reached a temporary concurrency or database limit.","action":"Wait `Retry-After` seconds and retry with bounded backoff.","scope":"common"}],"responseHeaders":[{"name":"Content-Type","value":"text/vcard; charset=utf-8","description":"A vCard 4.0 in UTF-8, with CRLF line ends."},{"name":"Cache-Control","value":"no-cache","description":"Ask again each time: a removed key leaves the file at once."},{"name":"Content-Disposition","value":"attachment; filename=\"veil-<n>.vcf\"","description":"Saved under the card’s number, never its name."}],"documentationUrl":"https://veil.rip/docs/contact-file","supportsBrowserFetch":true,"browserMode":"fetch"}}