Skip to main content

KYC Flow Guide (FirstAML Integration)

Audience: Engineers integrating customer onboarding into a Dr Green-backed store. TL;DR: You create the customer; Dr Green handles everything else. Poll until verified. You do not integrate with FirstAML directly.

The mental model

KYC is a Dr Green ↔ FirstAML concern. Your store sits outside that loop:
  • Dr Green owns the FirstAML relationship (commercial, contractual, technical)
  • Dr Green emails the customer with verification instructions
  • Dr Green fires the outbound webhook to FirstAML when a client is created
  • Dr Green receives FirstAML’s verification result via /api/v1/kyc/webhook
  • Dr Green updates the client’s isKYCVerified flag in its database
  • Your store sees the updated flag via GET /dapp/clients/{clientId}
You never call FirstAML, never embed their JS, never hold their credentials, never receive their webhooks. If a customer asks about KYC issues, you escalate to Dr Green — you can’t resolve them yourself.

The full flow


What you actually code

For most stores, exactly two pieces of code:

Piece 1 — submit on signup

Piece 2 — poll until verified

That’s it. Two functions. No FirstAML SDK, no FirstAML credentials, no webhook endpoint to expose.

State machine

A client’s KYC-relevant fields transition like this:
🪲 adminApproval and isKYCVerified are independent. Both can change in either order. Don’t write code that assumes adminApproval flips first or isKYCVerified flips first — guard on both being correct before you allow the customer to transact.

Timing expectations

🔒 These are estimates based on typical KYC/AML pipelines; specific timings for FirstAML’s Dr Green integration are not formally documented to store builders. Confirm with Dr Green if you need SLAs.
Polling cadence: every 5 minutes is the recommended sweet spot. Faster doesn’t make verification go quicker and adds load. Slower delays your customer experience. Total expectation to set with the customer:
  • Best case: 10–15 minutes from signup to “you can order”
  • Realistic case: 1–2 hours
  • Worst case: 1–2 days (manual review queues, AML escalations)
Don’t promise a fixed time. Let the email do the talking.

Edge cases

Customer abandons KYC

The customer signs up, gets the email, never clicks the link. Their record sits in adminApproval: PENDING, isKYCVerified: false indefinitely. Handling:
  • After ~24 hours, send them a follow-up email from your store reminding them
  • After ~7 days, mark as “abandoned” in your DB and stop polling them (set their kycState='abandoned')
  • If they later return and click the original email link, FirstAML will still process them; periodically (e.g. weekly) re-poll abandoned customers in case they re-engaged

KYC rejected

If adminApproval flips to REJECTED, the customer cannot transact. Show them a clear “your application was not approved — please contact support” message.
🔒 Re-submission policy — whether a rejected customer can re-apply with corrected info is a Dr Green policy decision. From the API surface, PATCH /dapp/clients/{id} exists for updates, but whether updating a rejected client moves them back to PENDING and re-fires the FirstAML webhook is not formally documented. Confirm with Dr Green before you build a re-submission UX.

KYC stuck >24 hours

Most cases verify within a few hours. If a customer has been PENDING + isKYCVerified: false for >24 hours, escalate:
  • Surface the customer’s id and email to your support team
  • Your support contacts Dr Green support
  • Dr Green checks the FirstAML case status (which they can see; you can’t)
  • Resolution path depends on the issue (customer didn’t complete? FirstAML asking for more info? Manual review queue?)

Customer wants to update their address

Use PATCH /dapp/clients/{id} for non-PII updates (phone, name, isActive).
🔒 Editing the shipping address post-verification has implications for AML — if FirstAML verified them at one address and they move, Dr Green may require re-verification. The exact policy isn’t formally documented. Build the UX cautiously: allow address edits, but warn that “your verification may need to be repeated.”

What’s in the email Dr Green sends

You don’t control the email content, but for customer-support purposes, here’s what your customers will see in broad strokes:
  • From address: a Dr Green / Cannexis Biopharma address (not yours)
  • Subject: something like “Complete your verification” or “Welcome — finish setting up your account”
  • Content: a link to the FirstAML hosted portal, with the customer’s name pre-populated
  • Branding: Dr Green’s, not yours
You should:
  • Tell customers in your post-signup UI to check their inbox (and spam folder)
  • Set expectations: “You’ll receive an email from Dr Green to complete verification”
  • Provide your support email for issues
You should not:
  • Promise specific timing
  • Try to forward or recreate the email
  • Embed a FirstAML-style verification flow yourself

Frequently asked questions

Q: Can I show the customer a real-time KYC progress UI? A: Limited. You can show the binary state (pending / verified / rejected) by polling GET /dapp/clients/{id}. You don’t have visibility into FirstAML’s internal substates (e.g. “ID document accepted, awaiting liveness”). Q: Can I trigger the email to be re-sent? A: There’s no documented API for this. If a customer needs the email re-sent, they contact Dr Green support, or you escalate. Q: Can my store skip KYC for “low-risk” customers? A: No. KYC is a regulatory requirement; Dr Green enforces it for every customer. There’s no opt-out. Q: Are KYC documents accessible to me? A: No, and that’s by design. They’re held by FirstAML / Dr Green for compliance. You shouldn’t have access — it would push you into a compliance scope you don’t want to be in. Q: What happens if I create a duplicate client (same email twice for the same holder)? A: 409 Conflict typically. Handle it gracefully: surface “an account already exists for this email; would you like to log in?” rather than retrying the create. Q: Different holders, same customer email — what happens? A: Each holder has their own client list. The same email can exist as a client under multiple holders independently. From your store’s perspective, you’re scoped to one holder’s API key, so you only see “your” holder’s clients.

Where to next