TRUSTYKYC verification platform

Verify real customers. Keep fraud out.

Trusty reads the identity document, checks a guided selfie for screens and printed photos, matches the face and, when you need it, verifies proof of address — then sends a signed decision to your backend.

Runs on Cloudflare: Workers, D1, R2, Queues and Workers AI

< 1 min
Typical time from upload to automated decision
1 iframe
Or a link your backend creates
Per contract
Evidence retention
Fig. 01 — Sample verification session · t_v9x2kf41
Built for digital onboarding teams
  • Encrypted in transit (TLS)
  • Signed, timestamped webhooks
  • Evidence retention configurable per contract
  • Audited access to evidence
  • Per-tenant isolation
  • GDPR-aligned handling
01How it works

From selfie to signed decision in four steps.

The capture runs in an iframe on your page or in a link your backend creates. Your backend gets a signed webhook when a verification completes or needs review.

  1. Consent & selfie

    → selfie frames

    The user reads the privacy notice and consents. A guided selfie follows: they start at arm’s length and move closer while three frames are captured. On desktop, the flow continues on the phone through a QR code.

  2. Documents

    → document images

    A photo of the passport, national ID card or driver’s license, with a live sharpness check before the shot. When you require it, a proof of address follows — as a PDF or a photo.

  3. Read & compare

    → structured result

    AI-assisted OCR extracts the document data, the selfie is compared with the ID portrait, and your policy is applied: expiry, minimum age, allowed countries and address recency.

  4. Decide & notify

    → signed decision

    The verification is approved, rejected or sent to your review queue. A signed webhook announces it, and the API returns the full result at any time.

02Capabilities

Five capabilities, one verification

Each check feeds the decision. The output is always the same: a result you can explain.

Document intelligence

Reads passports, national IDs and driver’s licenses

AI-assisted OCR extracts name, document number, dates and issuing country; expiry, minimum age and country policy are enforced per client.

PASSPORT · P
type PASSPORT
holder JANE A. SAMPLE
number P·48392017
expiry 2031-08-14
  • 3 document families
  • AI-assisted OCR
  • Expiry, age & country policy
  • Recapture & photocopy signals
Liveness

A guided selfie, checked for screens and printed photos

In the browser, the user starts at arm’s length and moves closer while three frames are captured — far, near and a confirmation. On the server, a vision model checks the confirmation frame for a single visible face, a screen or a printed photo. A suspected spoof does not reject on its own: it is flagged in the result, and only with manual review on does the verification wait for a reviewer instead of being approved.

  1. far
  2. near
  3. confirm

move from far to near

  • Guided far-to-near capture
  • Final frame analyzed
  • Screen & printed-photo flags
Face match

Compares the selfie with the ID portrait

The comparison yields a distance: lower means more alike. Above the threshold the verification is rejected; results just below it are flagged as borderline and, with manual review on, wait for a reviewer. Every analyzed result carries the distance or, when none could be computed, the face_match_unverified flag.

face distance 0.34
  • Distance, or a flag when missing
  • Borderline cases flagged
  • Evidence kept for audit
Proof of address

Checks a recent bill or statement against the ID

Utility bills, bank statements, telecom bills and official letters, as a PDF or a photo. Trusty reads the holder, address and issue date, applies your recency window and accepted types, and matches the name against the ID.

Without manual review, proof of address checks data consistency, not document authenticity.

UTILITY BILL
issuer CITY WATER CO.
holder JANE A. SAMPLE
address 14 HARBOUR RD, UTOPIA
issued 2026-09-02
  • name ↔ ID: match
  • age 22 d · max 90 d
  • PDF or photo
  • Recency window per client
  • Name matched against the ID
  • Off, optional or required
Decision & review

Every check ends in a decision you can trace

Approved, rejected or review. With manual review on, borderline and unreadable cases wait in a queue where your analysts approve or reject with a note. Each result records its reasons and the policy applied, and every decision bumps the revision and is announced by a signed webhook. Manual decisions, erasures and views of verification details land in the audit log.

  • approved / rejected / expired / review
  • Review queue with notes
  • Signed webhooks, retried & resendable
  • Audit log & CSV export
{
"event": "kyc.verification.completed",
"verification_id": "9f2c41d0-…",
"status": "approved",
"revision": 2,
"reasons": [],
"data": {
"document": { "document_type": "passport", … },
// distance: lower is closer · threshold 0.60
"face_match": { "distance": 0.34, … },
"proof_of_address": {
"outcome": { "accepted": true, "reasons": [] }
}
},
"completed_at": "2026-09-24T10:41:07Z"
}
03Why Trusty

Fewer manual checks. More real customers.

  1. 01

    An iframe or a link, no SDK

    Users verify inside your page or through a link your backend creates — no app to install.

  2. 02

    Every customer, same standard

    The same selfie, document and matching sequence for every verification, so outcomes stay comparable across cohorts.

  3. 03

    Automated fraud signals

    Screen recaptures, photocopies, printed photos and face mismatches are checked automatically before a result is issued.

  4. 04

    People where it matters

    Borderline and unreadable cases can wait for a reviewer instead of being rejected automatically.

  5. 05

    Decisions you can defend

    Signed, evidence-backed results your compliance team can search, audit and explain.

04Integration

Create a session on your server. Receive a signed result.

Your backend opens each verification with a secret key and learns the outcome by webhook or API. Your users stay in your product.

  1. 1

    Create a session

    POST /api/v1/verifications with your secret key and your external_user_id. The response includes session.url.

  2. 2

    Open it for the user

    Load session.url in an iframe with allow="camera", or send it as a link. On desktop, the user continues on the phone via a QR code.

  3. 3

    Receive the result

    Verify the signed webhook, or call GET /api/v1/verifications/:id — always the source of truth.

create-session.sh
# Server-side only: TRUSTY_SECRET_KEY holds your TR_SEC_… key
curl https://api.trusty.sh/api/v1/verifications \
  -H "Authorization: Bearer $TRUSTY_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "external_user_id": "user_8412", "lang": "en" }'

# 201 Created
# {
#   "verification": { "status": "pending", … },
#   "session": {
#     "token": "…",
#     "expires_at": "2026-09-25T10:40:00Z",
#     "url": "https://trusty.sh/verify?session=…"
#   }
# }
embed.html
<iframe
  src="https://trusty.sh/verify?session=…"
  allow="camera"
  referrerpolicy="strict-origin-when-cross-origin"
  title="Identity verification"
  style="width:100%;max-width:420px;height:640px;border:0">
</iframe>
verify-webhook.js
import express from 'express'
import { createHmac, timingSafeEqual } from 'node:crypto'

const app = express()
// The signature covers the exact bytes sent: keep the raw body.
const raw = express.raw({ type: 'application/json' })

app.post('/webhooks/trusty', raw, (req, res) => {
  // X-Trusty-Signature-V2: t=<unix seconds>,v1=<hex>
  const header = req.get('X-Trusty-Signature-V2') ?? ''
  const parts = Object.fromEntries(
    header.split(',').map((kv) => kv.trim().split('='))
  )
  const t = Number(parts.t)
  if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > 300) {
    return res.sendStatus(401) // missing, malformed or older than 5 minutes
  }

  const expected = Buffer.from(
    createHmac('sha256', process.env.TRUSTY_WEBHOOK_SECRET)
      .update(`${t}.`)
      .update(req.body)
      .digest('hex')
  )
  const received = Buffer.from(String(parts.v1 ?? ''))
  const valid =
    received.length === expected.length && timingSafeEqual(received, expected)
  if (!valid) return res.sendStatus(401)

  const event = JSON.parse(req.body.toString('utf8'))
  // Retries reuse X-Trusty-Delivery: skip deliveries already processed.
  // Keep the highest revision per verification_id; drop older events.
  if (event.event === 'kyc.verification.review_required') {
    // status "review": the outcome follows once your reviewers decide
  }
  // kyc.verification.completed → status approved | rejected | expired
  // kyc.verification.erased    → delete your copies of the personal data

  res.sendStatus(200)
})

Webhook events

  • kyc.verification.completed approved, rejected or expired
  • kyc.verification.review_required waiting in your review queue
  • kyc.verification.erased personal data erased — delete your copies

Deduplicate on X-Trusty-Delivery and apply an event only when its revision is higher than the one you hold. Deliveries are retried and can be resent from the backoffice.

Events for the embedding page

When framed, the widget posts trusty:ready, trusty:submitted, trusty:completed, trusty:consent_declined and trusty:error to your page, with the verification id and status — never personal data. Use them to update your interface; take the result from the webhook or the API.

embedding-page.js
window.addEventListener('message', (e) => {
  if (e.origin !== 'https://trusty.sh') return
  if (e.data?.source !== 'trusty') return
  // e.data: { source, version, type, verification_id, status? }
  if (e.data.type === 'trusty:completed') {
    // UI only: take the result from the webhook or the API
    showStatus(e.data.status)
  }
})

Simple mode

You can also embed /verify?public_token=… directly on an allowed domain. In that mode, metadata travels through the user’s browser: do not rely on it to link a result to an account — use an API session with external_user_id.

Full API documentation is available on request.

Request developer access

05Use cases

Where verification matters most

Contexts where a structured KYC check changes the risk profile of onboarding.

  1. 01

    Fintech

    Verify customers before granting access to regulated financial products such as accounts, cards and credit.

  2. 02

    iGaming

    Support age and identity checks during player onboarding and account review.

  3. 03

    Marketplaces

    Verify sellers, professionals or high-risk users before enabling sensitive actions such as payouts.

  4. 04

    Crypto

    Tie wallet opening and fiat on- and off-ramps to a verified identity.

  5. 05

    Digital services

    Gate regulated or high-trust actions behind an identity check without breaking the user flow.

Scope: identity document, liveness, face match and proof of address. Sanctions and PEP screening are not included — pair Trusty with your AML provider.

06Security & privacy

Biometric data, handled like it matters

Identity evidence demands the highest care. These are the controls in place today.

  • Per-verification erasure
  • Retention configurable per contract
  • Optional TOTP 2FA
  • Audited detail & evidence views
01

Encryption

Encrypted in transit (TLS) and server-side encryption at rest for every biometric artifact we store.

02

Evidence never public

Images and documents live in private storage, reachable only through authenticated, tenant-scoped endpoints.

03

Embedding on your domains

You list the domains that may embed the widget. While that list holds only your own domains, embeds from any other site are refused.

04

Roles, 2FA and sessions

Per-tenant roles — administrator and analyst — optional TOTP two-factor authentication, and 12-hour sessions that can be revoked.

05

Audited access

Views of verification details and evidence, searches, exports, erasures and manual decisions are recorded in the audit log.

06

Signed webhooks

Each tenant has its own signing secret. Signatures cover a timestamp and the raw body, so receivers can reject replays.

Security questionnaire available on request. Data processing agreement available on request. Designed for GDPR-aligned data handling.

07Pricing

Pay per verification. Scale when it works.

One metric, no hidden costs.

Starter

$99 /month

100 verifications included / month

then $0.90 per additional verification

For evaluation and small pilots.

  • Email support

Growth

Custom

from 2,500 verifications / month

For products running in production.

  • Volume pricing
  • Priority support

Enterprise

Custom

Unlimited volume, custom pricing

For regulated and high-volume teams.

  • SLA & dedicated support
  • Onboarding assistance

Included in every plan

  • Identity document, liveness & face match
  • Proof of address
  • Manual review queue
  • Server-to-server API
  • Signed webhooks
  • Backoffice roles
  • Audit log & CSV export
  • Per-client verification policy
08FAQ

Frequently asked questions

Identity documents (passport, national ID card, driver’s license), a guided selfie checked for screens and printed photos, a face match between the selfie and the ID portrait and, when you enable it, a proof of address. Each verification ends approved, rejected, expired or in review, and is delivered by signed webhook and through the API.

09Contact

Book a demo

Tell us about your product and what you need to verify.

Response time We reply within one business day.

The button opens your email client with the message pre-filled, addressed to [email protected]. Nothing is sent until you send it.

Make identity verification the boring part of onboarding

Book a walkthrough with the Trusty team. We will map the flow to your onboarding step and your compliance process.