Skip to content

Core concepts

Ten objects carry almost everything. Learning these makes the rest of the product read easily.

Account

The tenant. Every query is scoped to one, and nothing crosses the boundary — including the API, where another account's record is reported as not found rather than forbidden, so the difference cannot be used to enumerate someone else's portfolio.

Entity

The business being verified. Carries the registration number, legal name, country, registration status, operator-maintained fields (website, social, IBAN, business activity summary) and two separate quantities that are easy to confuse:

FieldMeansScale
current_scoreVerification coverage — how much of the file is verified0–100
risk_levelThe assessed risk bandlow / medium / high

These answer different questions and are never folded together. A merchant can be thoroughly verified and high risk, or barely verified and low risk.

risk_level has a database default

The column defaults to low, so it is only meaningful alongside risk_level_updated_at. Everything in the product — UI, API, filters — gates on that timestamp. An entity that has never been assessed reports not assessed, not "low".

Entity status

draftready_for_reviewapproved / rejectedonboardedunder_monitoring

Registration status

unknown, valid_status, invalid_status, expired — read from the commercial registry.

Sanctions status

not_run, clear, hit, needs_review.

Person

A human, resolved and deduplicated across entities within an account by identifier. Holds names, identifiers, nationalities and date of birth. One person can appear on many entities, which is what makes portfolio linkage possible.

Note that a date of birth is stored in two columns, because Saudi identity services use two calendars — see Dates of birth and calendars.

Party

The link between an entity and a subject (a person or another entity), carrying the relationship:

owner, manager_role, authorized_signatory, parent_entity, stakeholder

plus ownership percentage and whether the relationship is current. Party checks (screening, identity, address) run against a party's subject, not against the entity.

Entity check

One check of one thing: "did we verify this?" Has a check_type, a status (pending, running, completed, failed), a triggering reason, an optional subject party, and a sanitised public result. See the check catalogue.

Provider fetch run

The evidence behind a check: the actual call. Holds the raw response, the normalised summary, a sanitised request/response snapshot (credentials filtered), the status and any error. Checks are claims; fetch runs are the receipts. A failed call still creates one — a failure that leaves no trace is the outcome an audit trail exists to prevent.

Entity review

The unit of decision:

openin_progresscompleted, or escalated, or cancelled

with a purpose (initial, periodic), an assignee, notes, an outcome and a reason. Approval is blocked while anything is outstanding — see Reviews and decisions.

Screening match

A hit returned by a screening provider, which a human must adjudicate as a true or false positive. An unadjudicated blocking match prevents approval outright. See Screening adjudication.

Denylist entry

A standing bar on accepting a merchant or a person again. Keyed on an identifier rather than a record, because the case it exists to catch is the same operator returning under a new company with a new registration number.

A strong identifier — national ID, Iqama, registration number, IBAN — blocks approval. A weak one — a legal or person name — only warns, because names collide.

source separates our own decision from a card-scheme listing (Mastercard MATCH, Visa VMSS), which is somebody else's finding that Verity surfaces as theirs. See Standing bars.

Risk assessment

A point-in-time scoring: the weighted score, the band, the per-factor breakdown with each value's provenance, the gate state, and a snapshot of the tier thresholds used. The snapshot is what stops an old assessment from silently re-banding itself when someone later moves the boundaries.

How they fit together

Account
└── Entity ── current_score (coverage)   risk_level + risk_level_updated_at (band)
    ├── Party ──> Person
    ├── EntityCheck ──> ProviderFetchRun (raw + normalised + snapshot)
    ├── EntityReview ──> notes, screening matches, outcome
    └── EntityRiskAssessment ──> items (factor, score, weight, provenance)

DenylistEntry ── matched by IDENTIFIER, never by id, so a return under a new
                 company is still caught