{"openapi":"3.1.0","info":{"title":"VerifyYou API","description":"The external surface — API-key authed.","version":"v3"},"paths":{"/v3/initialize":{"post":{"tags":["Verification Flow"],"summary":"Initialize a verification session","description":"Queue up a run before the person verifies and get back a hosted verification link plus the `session_id` your frontend opens. They return to `redirect_url` if you passed one, else the verification's saved redirect URL, with `?vyt=<token>&vyc=<0|1>` appended — confirm that token server-side at `GET /v3/confirmations/{token}`. Accepts a publishable key (browser) or a secret key (server); identifiers, targeting and `redirect_url` need the secret key (and `redirect_url` needs a session, so it cannot be combined with the deprecated `expire_in_days`); `config` needs a test key.","operationId":"Verification Flow-initialize","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitializeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitializeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v3/confirmations/{token}":{"get":{"tags":["Confirmations"],"summary":"Confirm a verification result","description":"Exchange the `vyt` token from the return URL for the authoritative verdict. A token minted for another company — or the other test/live partition of your own keys — reads as nonexistent. Secret key only.","operationId":"Confirmations-get_confirmation","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/confirmations/{token}/lock":{"post":{"tags":["Confirmations"],"summary":"Consume a verification result","description":"Single-use enforcement: mark the pass consumed. A locked pass reads as not-passed everywhere, so the person re-verifies on their next run — one pass, one use. Idempotent. Secret key only.","operationId":"Confirmations-lock","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/confirmations":{"post":{"tags":["Confirmations"],"summary":"Look up a verification result by identity","description":"The token-free read: the person's latest settled pass with you, found by the credential you already hold. For when no token reached you — they closed the tab before the redirect, or the run had no redirect at all (an emailed invite they finished on their phone). `GET /v3/confirmations/{token}` stays the stronger check: a token proves THIS run just finished and came back to you, while this answers the looser question of where the person stands. Scoped to your company and your key's test/live partition — it can never see anyone else's traffic. 404 when that credential has never settled a pass with you. Secret key only.","operationId":"Confirmations-lookup_confirmation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v3/keys/test":{"post":{"tags":["API Keys"],"summary":"Test an API key (deprecated)","description":"**Deprecated.** Check that an API key works and see what it is: publishable or secret, test or live, and which company it belongs to. Send the key as the bearer token, like any other call. Always returns `200`: a bad key comes back as `valid: false` rather than an error, so it's safe to wire into a healthcheck or setup step.","operationId":"API Keys-test_key","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyTestResponse"}}}}},"deprecated":true,"security":[{"HTTPBearer":[]}]}},"/v3/test/confirmation-token":{"post":{"tags":["Testing"],"summary":"Mint a test confirmation token","description":"Settle a REAL test pass with the verdict you choose and get its `vyt` — no flow run needed, useful for exercising the confirmation exchange from a test suite. The pass lands in your test partition and dies with normal test-data cleanup; live keys can never see it. Test secret key only (`sk_test`).","operationId":"Testing-create_test_confirmation_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestConfirmationTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConfirmationTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}}},"components":{"schemas":{"ConfirmationLookupRequest":{"properties":{"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"The person's email, as you sent it to `initialize`.","examples":["user@example.com"]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"The person's phone, as an alternative."},"verification_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Verification Id","description":"Narrow to one verification. Omit to read across all of yours."}},"type":"object","title":"ConfirmationLookupRequest"},"ConfirmationResponse":{"properties":{"verified":{"type":"boolean","title":"Verified","description":"Authoritative result: true only if the verification passed and the pass is unlocked. Gate access on this, never on the client-side `vyc` hint."},"id":{"type":"string","title":"Id","description":"**Deprecated.** The pass id for this person's run through the verification.","deprecated":true},"status":{"type":"string","title":"Status","description":"Verdict detail: approved or denied — approved WITH reasons is 'flagged'."},"reasons":{"items":{"type":"string"},"type":"array","title":"Reasons","description":"Rule findings behind the status; a denied pass always carries at least one, an approved pass with reasons passed with findings."},"confirmed_at":{"type":"string","format":"date-time","title":"Confirmed At","description":"**Deprecated.** When the verdict settled.","deprecated":true},"locked":{"type":"boolean","title":"Locked","description":"**Deprecated.** You consumed this pass via the lock endpoint — it reads as not-passed.","deprecated":true},"declined":{"type":"boolean","title":"Declined","description":"The person chose not to scan — a denied pass, but not a failed one.","default":false},"is_test":{"type":"boolean","title":"Is Test","description":"**Deprecated.** Settled by a test run.","deprecated":true},"score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score","description":"**Deprecated.** Trust score, 0-100 higher = riskier.","deprecated":true},"band":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Band","description":"**Deprecated.** Trust band the score landed in.","deprecated":true},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id","description":"**Deprecated.** Your own id for the run, when `initialize` was called with one.","deprecated":true},"identity":{"anyOf":[{"$ref":"#/components/schemas/RevealedIdentityView"},{"type":"null"}],"description":"**Deprecated.** The proven identity, present only when the verification's config enables reveal and the run proved a credential. Null otherwise — never absent.","deprecated":true}},"type":"object","required":["verified","id","status","confirmed_at","locked","is_test"],"title":"ConfirmationResponse"},"ConfirmationStatus":{"type":"string","enum":["approved","denied"],"title":"ConfirmationStatus","description":"Binary: APPROVED = exit unblocked; DENIED = exit blocked. There is no\npending status — rows are born settled (the in-flight run lives on the\nsession, never in this table) — and no flagged status: \"flagged\" is\nPRESENTATION, derived downstream as approved-with-reasons."},"CreateTestConfirmationTokenRequest":{"properties":{"status":{"$ref":"#/components/schemas/ConfirmationStatus","description":"The verdict the test pass settles with.","default":"approved"},"reasons":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Reasons","description":"Rule findings to settle the pass with (e.g. `collision_company`, `identity_mismatch`). Unknown reasons are rejected."},"verification_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Verification Id","description":"The verification to settle under; your default verification when omitted."}},"type":"object","title":"CreateTestConfirmationTokenRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InitializeRequest":{"properties":{"verification_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Verification Id","description":"Secret key only. Target a verification directly instead of running the company's default verification."},"verification_external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verification External Id","description":"**Deprecated.** Target by `verification_id` instead. Still accepted: your own external id for the verification, as an alternative to `verification_id`.","deprecated":true,"examples":["signup-flow"]},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Secret key only. Seed the run with a provided identity — the flow is locked to it and can never collect a different one.","examples":["user@example.com"]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Secret key only. Seed the run with a provided phone identity."},"external_id":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"External Id","description":"Secret key only. Your own id for this run — carried through the flow and returned on the confirmation so you can tie the result back to your records.","examples":["user-8842"]},"external_tracker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Tracker","description":"**Deprecated.** Accepted for wire compatibility; not recorded.","deprecated":true},"redirect_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Url","description":"Secret key only. Where the person lands when this run ends, with the result appended as `?vyt=<token>&vyc=<0|1>`. Takes precedence over the redirect URL saved on the verification. Must be absolute and https, except on localhost or a private address, where http is accepted so you can point it at a dev server.","examples":["https://yourapp.com/verified","http://localhost:3000/verified"]},"pass_params":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Pass Params","description":"Extra query params carried through the flow and appended to the return URL. Reserved `vy*` keys are ignored."},"expire_in_days":{"anyOf":[{"type":"integer","maximum":365.0,"minimum":1.0},{"type":"null"}],"title":"Expire In Days","description":"**Deprecated — the number you pass is ignored.** Invites stopped expiring when `verification_invites.expires_at` was dropped, so this survives only as the switch that mints a durable invite instead of a one-shot session; any value in range behaves identically. Requires `email`. The link stays claimable until redeemed or revoked, and resumes where the person left off. The response carries `invite_id` instead of `session_id`. Kept because `/v3` is append-only — it goes away when the next external version is minted.","deprecated":true},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config","description":"Test key only. Override the verification's stored config for THIS run. The override is used verbatim — never merged with the stored config — and dies with the run. Rejected with a live key."}},"type":"object","title":"InitializeRequest"},"InitializeResponse":{"properties":{"url":{"type":"string","title":"Url","description":"Hosted verification link with a queued-up run. Redirect the person here.","examples":["https://app.verifyyou.com/verification?vys=..."]},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id","description":"The minted session, for a plain initialize. Null when `expire_in_days` was set."},"invite_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Invite Id","description":"**Deprecated.** The durable invite, only when the deprecated `expire_in_days` was set.","deprecated":true}},"type":"object","required":["url"],"title":"InitializeResponse"},"KeyTestResponse":{"properties":{"valid":{"type":"boolean","title":"Valid","description":"Whether the key resolved to an active account. An unknown or revoked key comes back as `false`, not an error."},"key_type":{"type":"string","title":"Key Type","description":"Prefix of the key you sent: `pk_live`, `pk_test`, `sk_live`, `sk_test`, or `unknown` if it matched none of them.","examples":["sk_test"]},"is_test":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Test","description":"Whether the key is a test key. `null` when the key didn't resolve."},"customer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Customer Id","description":"The company the key belongs to. `null` when the key didn't resolve."}},"type":"object","required":["valid","key_type"],"title":"KeyTestResponse"},"RevealedIdentityView":{"properties":{"provider":{"type":"string","title":"Provider","description":"The credential's channel: email, phone, or test."},"identifier":{"type":"string","title":"Identifier","description":"The proven identifier itself."}},"type":"object","required":["provider","identifier"],"title":"RevealedIdentityView"},"TestConfirmationTokenResponse":{"properties":{"token":{"type":"string","title":"Token","description":"A real `vyt` for a real test pass. Exchange it at `GET /v3/confirmations/{token}` with the same test secret key."},"verified":{"type":"boolean","title":"Verified","description":"The `verified` value the exchange will report for this token."}},"type":"object","required":["token","verified"],"title":"TestConfirmationTokenResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}