{"openapi":"3.1.0","info":{"title":"Verus API","version":"v1","description":"The open routes of a Verus deployment. Every other route is signed by the calling device; see docs/API.md."},"servers":[{"url":"https://api.verusapp.co.uk"}],"paths":{"/v1/deployment":{"get":{"summary":"Describe this deployment","description":"What this deployment is, the keys it publishes, what it will do, and what its database does and does not hold. Open and callable from any origin. A browser asking for text/html gets a readable page; ?format=json forces JSON.","parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","html"]}}],"responses":{"200":{"description":"The deployment description","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deployment"},"example":{"name":"Verus","mode":"standard","modes":["standard","verified","high-trust"],"jurisdiction":"GB","deploymentKey":"yDEBxYT4lUNqc3Qpzf51hdMQl2qGzre71Hl9mAesscQ","personhoodKey":"RBkWFO6Cz_4y51s0KsDmNemeOCnTLKI21Hi8VBuBnZE","demo":"PQZ6F7M3JJSC9Y9C2ZAC78H4","confrmoLogin":true,"push":true,"pushChannels":{"apns":true,"fcm":true},"subscriptions":true,"referralRewards":false,"liveness":true,"limits":{"maxEnvelopeBytes":65536,"maxQueuedEnvelopes":5000,"envelopeTtlSeconds":2592000,"idleBurnDays":30,"dropTokensPerIssue":64,"claimTtlSeconds":86400,"maxWaitSeconds":30,"maxBlobBytes":26214400,"blobTtlSeconds":604800},"holds":{"_litestream_lock":["id"],"_litestream_seq":["id","seq"],"abuse_report":["id","reported","reporter","category","note","evidence","reported_at","handled_at","outcome"],"account":["address","identity_key","created_day","last_seen_day","burn_after_day"],"account_points":["address","points","introductions","earned_on_day","earned_day","updated_day","proven_points","proven_introductions","rewards_granted","reward_plus_until"],"announcement":["id","title","body","severity","published_at","expires_at","withdrawn_at"],"blob":["id","body","stored_at","expires_at"],"call_feedback":["day","rating","issues","mode","codec","platform"],"call_session":["session","address","mode","self_token","peer_token","started_at","last_beat","seconds","relay_id"],"call_usage":["address","month","seconds"],"claim":["id","address","rp_domain","method","subject_ref","attributes","issued_at","expires_at","revoked_at","signature","assurance","checked_at"],"coin_order":["token_hash","coin","months","amount_units","after_height","created_at","expires_at","reserved_until","checked_at","seen_confirmations","paid","code_sealed","address","credited"],"daily_count":["day","name","count"],"device":["id","address","device_key","platform","cert_hash","created_day","revoked_day","environment"],"drop_token":["token_hash","expires_at"],"entitlement":["address","tier","expires_at","store","store_expires_at"],"envelope":["seq","id","to_address","to_device","body","received_at","expires_at","handed"],"grant_code":["code_hash","label","tier","days","uses","expires_at","revoked_at","code_sealed"],"grant_issued":["address","code_hash","issued_at"],"ha_heartbeat":["id","at"],"intro_human":["subject_hash","day"],"intro_pending":["nonce","subject_hash","expires_at"],"link_session":["sid","offer","bundle","expires_at","owner","proof"],"liveness_challenge":["id","address","nonce","prompts","status","reason","issued_at_ms","not_after_ms","expires_at"],"login_session":["sid","address","status","vcode_uti","open_url","created_at","expires_at"],"meet_group_usage":["address","month","seconds"],"meet_report_seen":["report","seen_at"],"offer_code":["code","product","added_day","expires_at"],"one_time_prekey":["device_id","key_id","public_key"],"operator_action":["id","at","subject_ref","action","target"],"operator_identity":["subject_ref","email","first_seen","last_seen","revoked_at"],"operator_login":["sid","status","vcode_uti","open_url","created_at","expires_at"],"operator_session":["token_hash","subject_ref","created_at","expires_at"],"personhood_use":["claim_id","audience","expires_at"],"presence_challenge":["sid","seq","kind","param","due_at_ms","issued_at_ms","issued_at","window_ms","answered_at_ms","answered_at","verdict"],"presence_contact_stat":["sid","channel","n","sum","sumsq","changed","reversals","travel","last_value","last_delta"],"presence_session":["sid","address","status","entropy","opened_at","deadline","last_t","samples_seen","frames_seen","issued","answered","next_due_ms","next_kind","next_param","reason","passed_at","expires_at"],"presence_use":["sid","audience","expires_at"],"purchase_code":["code_hash","tier","paid_until","uses","redeemed","expires_at","payment_ref","code_sealed"],"redemption":["transaction_hash","expires_at","uses"],"relay_application":["id","created_at","kind","country","uplink","contact_kind","contact","note","status"],"relay_bonus":["node_id","owner_address","points","at"],"relay_day":["relay_id","day","online_minutes","calls","call_seconds","credited_minutes","verified_callers"],"relay_enrolment":["code","public_key","expires_at","node_id","confrmo_sid","for_address","confrmo_address"],"relay_hardware":["id","hardware","at"],"relay_mesh_round":["round","starts_at","members"],"relay_mesh_route":["round","nonce","origin","kind","path","ok","ms","reply_at","reported_at"],"relay_node":["id","public_key","name","town","certificate_id","bonus_points","owner_address","created_day","revoked_day","owner_subject","owner_confirmed_at","released_day"],"relay_record":["relay_id","day","body","hash","signature","points","owner_address"],"reward_delivery":["id","account","code","redeem_url","created"],"seen_nonce":["nonce","expires_at"],"server_secret":["name","value"],"signed_prekey":["device_id","key_id","public_key","signature","created_day"],"vcode_mint":["uti","url","purpose","created_at","expires_at"],"vp_link_code":["code_hash","address","expires_at"],"vp_link_offer":["address","at","kind"],"vp_link_quiet":["address","until"],"vp_link_request":["id","address","secret_hash","check_number","status","relay_id","created_at","expires_at"],"vp_payout_address":["address","chain","payout_address","proved_at"],"vp_payout_challenge":["id_hash","address","chain","payout_address","message","expires_at"],"vp_payout_notice":["address","at"],"vp_payout_request":["id","address","secret_hash","check_number","chain","payout_address","proved_at","status","relay_id","created_at","expires_at"],"vp_redemption":["id","address","day","points","reward"],"vp_verification":["address","at","reason"],"vp_view_key":["key_hash","address","created_at"],"vsol_order":["token_hash","months","amount_sats","after_height","created_at","expires_at","reserved_until","checked_at","seen_confirmations","paid","code_sealed","address","credited"],"wake_token":["device_id","platform","token","updated_day","environment","voip_token"],"work_email_check":["address","email_mac","code_mac","attempts","expires_at"]},"neverHolds":{"account":["name","phone","email","ip","ip_address","user_agent","last_seen_at"],"envelope":["from_address","from_device","sender","plaintext","subject"],"drop_token":["address","account","issued_to"],"blob":["filename","mime","name","from_address","to_address","owner"],"link_session":["account","address","device","who_linked"],"wake_token":["address","message","body","last_sent_at"],"claim":["user_handle","biometric","device_id","presented_email"],"personhood_use":["address","account","group_id","chat_id","members","member_list","device"],"work_email_check":["email","email_address","code","domain","team","team_id","workspace","company","name","group_id"],"presence_session":["audience","frame","frames","image","media","video","face","template","embedding","landmarks","biometric","descriptor"],"presence_challenge":["address","account","audience","frame","frames","image","media","video","face","template","embedding","landmarks","biometric","descriptor"],"presence_contact_stat":["address","account","device","samples","values","raw"],"presence_use":["address","account","device","group_id","chat_id","members","member_list"],"liveness_challenge":["audience","metrics","results","yaw","roll","smiling","score","frame","frames","image","media","video","face","template","embedding","landmarks","biometric","descriptor"],"entitlement":["apple_account","transaction_id","original_transaction_id","email","price"],"call_usage":["peer","peer_address","started_at","ended_at","calls","duration"],"call_session":["peer","peer_address","to_address","ip","endpoint"],"meet_group_usage":["room","room_name","peer","participants","started_at","ended_at","meetings","duration"],"meet_report_seen":["address","room","room_name","participants","duration"],"redemption":["address","account","apple_account","email"],"vsol_order":["account","txid","from_address","payer","email","redeemed_by","paid_at","paid_until","payment_ref"],"coin_order":["account","txid","from_address","payer","email","redeemed_by","paid_at","paid_until","payment_ref"],"operator_identity":["address","account","user_handle","ip","password_hash"],"operator_session":["address","account","ip","user_agent"],"operator_login":["address","account","email","user_handle"],"operator_action":["address","account","user_handle","ip","user_agent"],"offer_code":["address","account","device","issued_to","redeemed_by","granted_to","inviter","invitee","given_at"],"intro_human":["address","account","claim_id","subject_ref","inviter","invitee","nonce"],"intro_pending":["address","account","claim_id","subject_ref","inviter","invitee"]}}},"text/html":{"schema":{"type":"string"}}}}}}},"/v1/health":{"get":{"summary":"Liveness check","responses":{"200":{"description":"The server is up","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ok"},"time":{"type":"integer","description":"Server time, Unix seconds"}}}}}}}}},"/v1/openapi.json":{"get":{"summary":"This document","responses":{"200":{"description":"OpenAPI 3.1","content":{"application/json":{}}}}}}},"components":{"schemas":{"Deployment":{"type":"object","required":["name","mode","modes","jurisdiction","deploymentKey","personhoodKey","confrmoLogin","push","pushChannels","subscriptions","referralRewards","liveness","limits","holds","neverHolds"],"properties":{"name":{"type":"string","description":"The name this deployment goes by."},"mode":{"type":"string","description":"The trust mode it runs in, one of modes. Standard lets anonymous addresses talk freely; verified relays only for accounts holding a live identity attestation; high-trust is set by the operator and also requires a Secure Enclave or StrongBox device key.","enum":["standard","verified","high-trust"]},"modes":{"type":"array","items":{"type":"string"},"description":"Every trust mode the software supports, so a client can tell an unknown mode from a misspelt one."},"jurisdiction":{"type":"string","description":"ISO 3166 country code for the law the operator answers to."},"deploymentKey":{"type":"string","description":"Ed25519 public key the deployment signs with. A client pins it on first contact."},"personhoodKey":{"type":"string","description":"Ed25519 public key a personhood attestation is checked against, published so a group can check one offline without telling the deployment who it checked."},"demo":{"type":["string","null"],"description":"Address of the deployment's own account, so a new install has somebody to talk to. Null when it runs none."},"confrmoLogin":{"type":"boolean","description":"Whether signing in with Confrmo is configured."},"push":{"type":"boolean","description":"Whether Apple push (APNs) is configured, so an iPhone can be woken."},"pushChannels":{"type":"object","description":"Push per channel: apns for Apple, fcm for Android.","properties":{"apns":{"type":"boolean"},"fcm":{"type":"boolean"}}},"subscriptions":{"type":"boolean","description":"Whether App Store receipts can be verified. False means the app offers no purchase."},"referralRewards":{"type":"boolean","description":"Whether invitation rewards are switched on. False means no reward can be earned or collected yet."},"liveness":{"type":"boolean","description":"Whether a phone can earn a presence pass with Confrmo's face test, run on the handset, through POST /v1/liveness/challenge and /v1/liveness/attest."},"limits":{"type":"object","description":"What a free account may do. Larger tiers raise some of these.","properties":{"maxEnvelopeBytes":{"type":"integer","description":"Largest single message envelope accepted. (bytes)"},"maxQueuedEnvelopes":{"type":"integer","description":"Envelopes held for one device before new ones are refused. (count)"},"envelopeTtlSeconds":{"type":"integer","description":"How long an uncollected envelope is kept before it is deleted. (seconds)"},"idleBurnDays":{"type":"integer","description":"Days without being seen before an account and everything it holds is deleted. (days)"},"dropTokensPerIssue":{"type":"integer","description":"Anonymous sending tokens handed out per request. (count)"},"claimTtlSeconds":{"type":"integer","description":"How long an identity claim lasts before it must be checked again. (seconds)"},"maxWaitSeconds":{"type":"integer","description":"Longest a client may hold a request open waiting for new messages. (seconds)"},"maxBlobBytes":{"type":"integer","description":"Largest attachment accepted. (bytes)"},"blobTtlSeconds":{"type":"integer","description":"How long an attachment is kept before it is deleted. (seconds)"}}},"holds":{"type":"object","description":"Every table and column the database holds, read from the live schema rather than typed out, so it cannot drift from what is stored.","additionalProperties":{"type":"array","items":{"type":"string"}}},"neverHolds":{"type":"object","description":"Columns that are absent by design, checked against the live schema on every request. A column that appears drops out of this list and raises an alarm in the operator console.","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}}}