Webhooks
TL;DR. Dr Green has inbound webhook endpoints that its payment and KYC processors call into. As an external store builder, you are not the consumer of these — they’re between Dr Green and its third-party services. There is currently no outbound webhook system for stores: your store must poll the relevant endpoints to detect order, KYC, and commission state changes.
What this means for your store
If you’ve built integrations with Stripe, Shopify, or PayPal, you’re used to the pattern:Inbound webhooks (between Dr Green and its processors — you can ignore these)
For completeness, the four webhook endpoints that exist on the Dr Green API:| Endpoint | Caller | Purpose |
|---|---|---|
POST /api/v1/kyc/webhook | FirstAML | KYC/AML verification status updates from FirstAML back to Dr Green |
POST /api/v1/payments/webhook | CoinRemitter | Crypto payment notifications |
POST /api/v1/payments/fiat/webhook | Payinn | Fiat payment notifications |
POST /api/v1/payments/pgpay/webhook | PGPay | Alternate fiat payment gateway notifications |
As a store builder, you don’t call these and they don’t call you. They’re listed here only so you understand the full surface — and so you don’t accidentally try to use them.
How the FirstAML KYC flow actually works
This is the most-asked-about flow, so worth spelling out clearly:- Your store does not integrate with FirstAML. You don’t have FirstAML credentials, you don’t render their UI, you don’t receive their callbacks.
- The outbound Dr Green → FirstAML webhook (step 2 above) is a separate, internal flow — not exposed in the public API surface.
- The customer interacts with FirstAML directly (typically via a hosted verification portal linked from the email Dr Green sends).
- All you do is
POST /dapp/clientsto start the flow, then pollGET /dapp/clients/{clientId}untilisKYCVerified === trueandadminApproval === 'VERIFIED'.
The polling pattern (what your store actually does)
Until outbound webhooks exist, build your store around polling. Here’s a battle-tested pattern.What to poll
| Concern | Endpoint | Why |
|---|---|---|
| Order status change (the big one) | GET /api/v1/dapp/orders/:orderId | Detect “approved”, “rejected”, “shipped” |
| KYC status change for a customer | GET /api/v1/dapp/clients/:clientId | Detect verification completion |
| Recent orders across all customers | GET /api/v1/dapp/orders/recent | Cheap heartbeat — surfaces anything new |
| Commission accrual | GET /api/v1/dapp/commissions/summary | Update holder’s earnings widget |
| Strain catalogue freshness | GET /api/v1/dapp/strains | Detect new products and price changes |
How to poll efficiently
Pattern: tiered polling intervals.| Resource freshness | Poll interval | Justification |
|---|---|---|
| Order status (active orders only) | 60s | Customers tolerate ~1min staleness on order status |
| Order status (orders >7 days old, not yet shipped) | 30 min | Long-tail; rarely changes |
| KYC status (pending) | 5 min | FirstAML verification timing varies by case complexity (minutes to hours) |
| Commission summary | 15 min | Updates aren’t time-critical |
| Strain catalogue | 1 hour | Catalogue is stable; refresh on cache miss |
shipped, cancelled, rejected). Maintain a list of “active” order IDs in your store DB; remove them once they reach a terminal status.
Pattern: jittered polling.
If your store has many holders, don’t poll all of them on the same cron-second — you’ll create thundering herds against the Dr Green API. Add ±10% random jitter to every interval.
What not to do
- Don’t poll every order on every tick. Use the active-set pattern above.
- Don’t poll faster than 1 req/sec per holder. The backend isn’t currently rate-limited but politeness avoids future enforcement pain.
- Don’t poll without backoff on errors. A backend hiccup shouldn’t get amplified by your retry storm. Exponential backoff on consecutive failures.
Future outbound webhook design (when it ships)
When Dr Green ships outbound webhooks for store builders, the design we’d recommend (and have flagged) looks like:- HMAC-SHA256 signing of payload with a per-store secret you configure in the DAPP
- Replay-protection timestamp in the signature payload
- Standard event types:
order.created,order.approved,order.rejected,order.shipped,client.kyc.completed,commission.accrued - At-least-once delivery with idempotency on the receiving side keyed by event ID
- Retry policy of ~5 attempts over 24 hours
Summary
| Question | Answer |
|---|---|
| Does Dr Green call my store on events? | ❌ Not currently. |
| Do I need to expose a webhook endpoint? | ❌ No. |
| How do I detect order status changes? | Poll GET /api/v1/dapp/orders/:orderId. |
| What about FirstAML KYC results? | Poll GET /api/v1/dapp/clients/:clientId. The KYC flow is handled entirely between Dr Green and FirstAML — your store doesn’t integrate with FirstAML. |
Are the /payments/webhook endpoints for me? | ❌ No — those are between Dr Green and CoinRemitter / Payinn / PGPay. |
| When will outbound webhooks ship? | 🔒 Not on a published roadmap. Worth requesting from Dr Green. |