← Blog

· 18 min read

Sumsub for Armenian CASPs, end to end

From an empty Sumsub account to verified customers whose records meet Armenian rules: levels, questionnaires, keys, webhooks, retention and testing — with every requirement traced to its article.

What you will have at the end

This guide is for crypto-asset service providers and brokers in Armenia whose compliance officer and engineers set up Sumsub together. It follows the rules that exist today: the AML/CFT Law (as amended through July 2025), the Law on Non-Cash Operations, the Central Bank's Decision 12-N of 26 January 2026, and the Law on Protection of Personal Data.

  • A standard level for individuals that collects everything Armenian law asks for — not just what a generic KYC template collects.
  • An enhanced level for PEPs and high-risk customers, and a company (KYB) level with the Armenian 20% beneficial-ownership threshold.
  • Signed API access and verified webhooks, with personal data kept out of logs.
  • Your own copies of the records you must keep for five years, even though Sumsub did the checking.
flowchart LR
  C["Customer"] -->|"verification link"| S["Sumsub level"]
  S -->|"webhook: applicantReviewed"| B["Your backend"]
  B -->|"GET applicant"| S
  B --> K[("Your KYC records<br/>5 years after the relationship")]
  B --> L["Application logs<br/>no personal data"]
  B --> D["Decision: approve / more docs / reject"]
  K -->|"on request, 5 working days"| CBA["Central Bank of Armenia"]
Who does what. Sumsub checks documents and faces; you decide, keep the record, and answer the Central Bank.

What Armenian rules ask you to collect

Article 16(4)(1) of the AML/CFT Law lists the minimum identification data for a natural person, taken from an identity document that bears a photograph. Several items are routinely missed by default KYC flows — note the place of birth and the document issue date.

WhatRequired byHow you get it with Sumsub
First name, last nameAML Art. 16(4)(1); Non-Cash Operations Art. 6.1(3)Identity document step
CitizenshipAML Art. 16(4)(1)Passport country / nationality; questionnaire for other citizenships
Date and place of birthAML Art. 16(4)(1)Document for the date; place of birth from the document or the questionnaire
Document series, number and issue dateAML Art. 16(4)(1); Non-Cash Operations Art. 6.1(3)Identity document step — check each applicant
Registration address (if any) and place of residenceAML Art. 16(4)(1)Questionnaire, or Proof of residence
Residency (resident / non-resident)Decision 12-N point 3Questionnaire
PEP status (and of beneficial owners)AML Art. 18(2.1)Questionnaire plus AML screening
Business profile, purpose and intended natureAML Art. 16(7)Questionnaire
Core of vital interests (foreign persons)AML Art. 18(4)Questionnaire, only for foreign customers
Source of funds and of wealth, senior management approvalAML Art. 3(1)(22) — enhanced CDDEnhanced level; approval is recorded in your own system
Copy of the identity documentDecision 12-N point 4; AML Art. 16(8)Download from Sumsub and keep your own copy

Which level applies is a risk decision (AML Art. 18). Any high-risk criterion — a politically exposed person, a link to a non-compliant country, unusual activity, or an assignment from the Central Bank — means enhanced due diligence. Simplified due diligence needs a low-risk criterion and no suspicion; in the current law it reduces ongoing monitoring, not the identification data.

flowchart TD
  A["New customer"] --> B{"Any high-risk criterion?<br/>PEP, non-compliant country,<br/>unusual activity, CBA assignment"}
  B -->|"yes"| E["Enhanced CDD<br/>am-individual-enhanced"]
  B -->|"no"| C{"Low-risk criterion<br/>and no suspicion?"}
  C -->|"yes"| S["Simplified CDD<br/>same identification data,<br/>lighter monitoring"]
  C -->|"no"| N["Standard CDD<br/>am-individual-standard"]
  E --> R["Review at least yearly"]
  N --> R
  S --> R
Choosing the CDD level (AML/CFT Law Art. 18).

Account, modes and paperwork

  1. Sumsub has two modes, Sandbox and Production, with separate data and separate app tokens. Build everything in Sandbox first.
  2. Invite your compliance officer and engineers as team members with only the permissions they need, and turn on two-factor authentication.
  3. Sign Sumsub's data processing agreement. Under the Personal Data Law (Art. 14) a processor acts on a written assignment that names the purpose, the data and the protection measures — this is that document.
  4. Sumsub processes data outside Armenia. Check the transfer rules of Art. 27 of the Personal Data Law (adequate-protection countries, or authorisation by the Personal Data Protection Agency) and keep the result in your compliance file.

Create the Armenian CDD questionnaire

Go to Questionnaires → Create questionnaire. Sumsub generates ids for the questionnaire, its sections and questions; edit them to the ids below so your code (and the open-source kyc-am mapping) can read the answers without changes.

Item idTypeQuestionAsk
biometric_consentConsent (bool)I agree that my photo and video are processed to check my identity.Always, first
residence_addressParagraphWhere do you live? (full address)Always
registration_addressParagraphRegistration address, if differentOptional
place_of_birthShort answerPlace of birthWhen the document does not show it
residency_statusMultiple choiceAre you a resident of Armenia?Always
other_citizenshipsCountry (multiple)Other citizenships (if any)Optional
pep_statusMultiple choiceAre you a politically exposed person, or a family member or close associate of one?Always
purpose_and_natureParagraphWhat will you use our services for?Always
business_profileParagraphOccupation or business, and expected monthly volume (AMD)Always
core_of_vital_interestsParagraphWhere are your family and main economic interests based?Foreign customers (use a condition)

Name the questionnaire and its section am_cdd. For the enhanced level, create a second questionnaire am_edd with two paragraph questions, source_of_funds and source_of_wealth. Conditions refer to questions as sectionid.itemid.

Questionnaire answers are the customer's own statements. Treat them as declarations; verify what the law requires you to verify (for example PEP status also through AML screening).

The standard level for individuals

  1. Go to the Individuals page → Create level. Name it am-individual-standard (level names are case-sensitive in the API).
  2. Steps tab, in this order: Questionnaire (am_cdd) — so the biometric consent comes before the selfie; Identity document — passport, ID card, residence permit; Liveness & Face match.
  3. Email and phone verification are optional; useful as contact data.
  4. Configurations tab: in ID document settings turn on "Accept only valid documents"; turn on AML screening so PEP and sanctions hits are checked, not only declared.
  5. Save, then use Run level to try it yourself in Sandbox.
sequenceDiagram
  actor Customer
  participant App as Your app
  participant S as Sumsub
  App->>S: create applicant (externalUserId = your customer id)
  App->>S: create verification link
  App-->>Customer: send link
  Customer->>S: consent + questionnaire
  Customer->>S: identity document
  Customer->>S: liveness and face match
  S->>S: document, face and AML checks
  S-->>App: webhook applicantReviewed
  App->>S: GET applicant (data + questionnaire answers)
  App->>App: map to Armenian fields, list gaps, decide
What the customer goes through, and what you get back.

Sumsub extracts the document number and issue date from most documents, but you cannot mark them as mandatory. Armenian rules require both, so check them on every applicant and, if one is missing, get it through the questionnaire or manual review before you approve.

The enhanced level

  1. Duplicate am-individual-standard as am-individual-enhanced.
  2. Add Proof of residence (a recent utility bill or bank statement).
  3. Add the am_edd questionnaire: source of funds and source of wealth — both required for enhanced due diligence (AML Art. 3(1)(22)(b)).
  4. Add a document step for evidence of the source of funds (salary statement, sale contract, tax return).
  5. Record senior management approval in your own system: who approved and when. Sumsub does not hold this for you.
Moving a customer to the enhanced level when a high-risk criterion appears
POST /resources/applicants/{applicantId}/moveToLevel?name=am-individual-enhanced

// with kyc-am
await sumsub.moveToLevel(applicantId, "am-individual-enhanced");

The company level (KYB)

Go to the Companies page → Create level and name it am-company. For legal persons the law asks for the name, registered office, place of business when different, the charter, the state registration number, the executive officer's name and, if available, the tax number (AML Art. 16(4)(2)); Decision 12-N also asks for the tax number and the representative's identification data.

  • Company documents: registry extract or registration certificate, charter (կանոնադրություն), shareholder register, and a document on the powers of management bodies (Art. 16(6)).
  • Beneficial owners start at 20% in Armenia — direct or indirect holding, or control by other means; if nobody qualifies, the senior managing official (Art. 3(1)(14)). Many tools default to 25%: set 20% in your beneficiary settings, or collect holders from 20% yourself.
  • Verify the executive officer, representatives and beneficial owners as individual applicants with am-individual-standard.
  • Write down how you determined the beneficial owners. The law requires the reasoning to be documented and kept (Art. 16(5.1)).
flowchart TD
  C["Company customer"] --> A{"Anyone holding 20% or more,<br/>directly or indirectly?"}
  A -->|"yes"| O["Beneficial owner(s)"]
  A -->|"no or not only"| B{"Anyone controlling<br/>by other means?"}
  B -->|"yes"| O
  B -->|"no one found"| M["Senior managing official<br/>is the beneficial owner"]
  O --> V["Identify and verify,<br/>check PEP status"]
  M --> V
  V --> R["Document how you decided<br/>(Art. 16(5.1))"]
Who counts as a beneficial owner (AML/CFT Law Art. 3(1)(14)).

Where each Armenian field comes from

FieldSumsub sourceWatch out for
first_name, last_name, patronymicinfo.firstName / lastName / middleName—
date_of_birthinfo.dob—
place_of_birthinfo.placeOfBirth, else questionnaireOften empty for ID cards
citizenshipinfo.nationality or passport countryAsk for other citizenships
id_document_number, id_document_seriesidDocs[].number, serialNumberCheck per applicant
id_document_issue_dateidDocs[].issuedDateNot every document yields it
residence_addressinfo.addresses, questionnaire, or Proof of residence—
registration_addressquestionnaire, or address on the ID cardCollect if it exists
residency_status, pep_status, purpose_and_nature, business_profilequestionnaire am_cddDeclarations
source_of_funds, source_of_wealthquestionnaire am_eddEnhanced level only
id_document_copydocument images APIKeep your own copy

The open-source module kyc-am does this mapping (toDictionary) and returns the list of Armenian-required fields still missing for the level, each with the article behind it.

App token, secret and IP allowlist

  1. Switch to the mode you are configuring (Sandbox first). Tokens only work in the mode they were created in.
  2. Go to Dev space → App Tokens → Generate app token.
  3. Give only the permissions your backend needs: create and read applicants, generate links, read document images, change levels.
  4. Under Whitelisted IPs, restrict the token to your servers' addresses.
  5. The token and secret are shown once. Put them straight into your secret manager — never in the database next to KYC data, never in logs.
Every request is signed: HMAC-SHA256 over timestamp + method + path + body
import { SumsubClient } from "kyc-am/sumsub";

const sumsub = new SumsubClient({
  appToken: process.env.SUMSUB_APP_TOKEN,   // "sbx:…" in Sandbox, "prd:…" in Production
  appSecret: process.env.SUMSUB_APP_SECRET,
});
await sumsub.testConnection(); // { ok: true } — creates nothing

await sumsub.ensureApplicant("am-individual-standard", { externalUserId: "C-000123", email: "anna@example.am" });
const { url } = await sumsub.createLink("am-individual-standard", { externalUserId: "C-000123" });

Use your own customer identifier as externalUserId — the same identifier Decision 12-N requires in every record — never a document number or an email address.

Webhooks and signature checks

  1. Go to Dev space → Webhooks → Webhook manager → Create webhook.
  2. Receiver: HTTP address; target: your HTTPS endpoint (Sumsub does not send to plain HTTP).
  3. Types: applicantReviewed at minimum; applicantPending and applicantOnHold are useful for status.
  4. Applicant types: individuals and companies. Signature algorithm SHA256; keep the secret key in your secret manager.
  5. Answer within 10 seconds (accept the connection within 1 second); failed deliveries are retried.
sequenceDiagram
  participant S as Sumsub
  participant W as Your webhook endpoint
  participant K as KYC records
  participant L as App logs
  S->>W: POST applicantReviewed + x-payload-digest
  W->>W: HMAC of the raw body = digest?
  alt digest does not match
    W-->>S: 401
  else digest matches
    W->>S: GET applicant
    S-->>W: data, documents, answers
    W->>K: append status + Armenian fields (hash-chained)
    W->>L: summary only - status, ids, no personal data
    W-->>S: 200
  end
Handling a webhook. The webhook is only a signal; the applicant is the record.
Verify against the raw body — re-serialised JSON will not match
import { verifyWebhookDigest, parseWebhook, toDictionary } from "kyc-am/sumsub";

if (!verifyWebhookDigest(rawBody, req.headers, process.env.SUMSUB_WEBHOOK_SECRET)) return res.status(401).end();
const hook = parseWebhook(rawBody);
const applicant = await sumsub.getApplicant(hook.applicantId);
const { values, gaps } = toDictionary(applicant, { level: "standard" });
// gaps → e.g. [{ field: "place_of_birth", rules: ["AML-16.4.1"], howToFill: "…" }]

No public web address? Open Dram's desktop app has none, so it uses Fetch status on the user page instead of a webhook. The result is mapped the same way.

Records, reliance and retention

Relying on Sumsub does not move responsibility. Under AML Art. 16(8) the responsibility stays with you, and you must be able to produce the identification data and copies of documents immediately on request. Decision 12-N (point 4) asks you to keep the customer data and a copy of the identity document for at least five years, and point 30 gives five working days to answer the Central Bank.

Keep your own copy of the document images
const images = await sumsub.listDocumentImages(applicantId);
for (const img of images) {
  const { bytes, contentType } = await sumsub.downloadDocumentImage(applicantId, img.id);
  await yourVault.put(`kyc/${customerId}/${img.id}`, bytes, contentType);
}
flowchart LR
  A["Relationship starts"] --> B["Identity verified<br/>within 7 days (Art. 16(1))"]
  B --> C["Data refreshed<br/>at least yearly (Art. 17(2))"]
  C --> D["Relationship ends"]
  D --> E["Keep identification data,<br/>document copy, BO reasoning<br/>5 years (Art. 22, 12-N p.4)"]
  T["Each transaction"] --> F["Keep transaction data<br/>5 years from its date<br/>(Art. 22, 12-N p.7)"]
  V["Cash-desk video"] --> G["Keep 6 months<br/>(12-N p.12)"]
  E --> H["Then erase or anonymise<br/>(Personal Data Law Art. 5)"]
  F --> H
How long to keep what (minimums).
  • Retention runs from the end of the relationship for customer data and from the transaction date for transactions — whichever is later when both apply.
  • Keep longer when a request, an investigation or another law requires it.
  • Sumsub's own retention settings are a separate question: your obligation is met by your records, not by the processor's.

Connect: Open Dram or your own backend

  • Open Dram desktop: Settings → Integrations · Sumsub → Connect Sumsub, paste the token and secret, set the level name am-individual-standard, and make Sumsub the default KYC method. The keys stay in your computer's keychain.
  • Your own backend: the open-source kyc-am module (Apache-2.0) gives you the Armenian data dictionary in three languages, CDD validation, retention dates, a hash-chained KYC log with log-safe summaries, Decision 12-N record shapes and this Sumsub adapter. Every rule in it links to its article.

Test in Sandbox, then go live

Simulate review results in Sandbox
POST /resources/applicants/{applicantId}/status/testCompleted
{ "reviewAnswer": "GREEN", "rejectLabels": [] }

{ "reviewAnswer": "RED", "reviewRejectType": "RETRY",
  "rejectLabels": ["UNSATISFACTORY_PHOTOS"] }   // → needs documents

{ "reviewAnswer": "RED", "reviewRejectType": "FINAL",
  "rejectLabels": ["FORGERY"] }                 // → rejected
  • A GREEN applicant maps to approved; RED + RETRY to needs documents; RED + FINAL to rejected.
  • Run an Armenian passport, an Armenian ID card and a foreign passport; check that no required field is left in the gap list.
  • Send a webhook with a wrong signature and make sure it is refused.
  • Check your logs: no names, document numbers, addresses or emails.
  • Create Production tokens and a Production webhook — Sandbox tokens do not work there — and rerun one real verification with your own documents.
  • Put the next review date (at most a year) and the retention dates in your system from day one.

Read next

Connect Sumsub with your own keys →Create a user with KYC →KYC data reference →