Architecture in two paragraphs
Your CRM is the source of truth for contact details. Orgo is the source of truth for what that contact has done inside Orgo — events attended, payments made, contracts signed, newsletter engagement. The sync pushes contact details one way and pulls Orgo activity the other way. Day-to-day, both sides change. Without webhooks, you’d have to poll Orgo for “what changed since yesterday?” — expensive and slow. With webhooks, Orgo tells you the moment a contact subscribes, a payment clears, or a contract is signed. We use webhooks for the Orgo → CRM direction.Step 1 — Bulk import from CRM to Orgo (initial load)
Iterate over your CRM and create one Contact per record. The endpointPOST /api/v1/contacts returns 409 Conflict if an email already exists in Orgo (either as a Contact or as a User), so you can rerun safely.
Conflict handling
WhenPOST returns 409, the email already exists. Options:
- Skip — your CRM was already in sync; no action needed.
- Merge — look up the existing Contact by email (
GET /api/v1/contacts?email=...) andPATCHit with the fresher CRM data.
Step 2 — Tag contacts for audience filtering
Tags are how Orgo segments contacts in newsletter audiences and event invite filters. Sync your CRM segments to OrgoProfileTag entries.
Step 3 — Subscribe to Orgo events
Register a webhook so Orgo pushes updates the moment they happen — no polling needed.Step 4 — Receive and write back to CRM
When Orgo fires acontact.updated webhook, your handler:
- Verifies the signature.
- Looks up the same contact in your CRM by email.
- Writes back the fields Orgo owns (newsletter opt-in, last event attended, total payments).
previous_attributes is the diff — fields not mentioned didn’t change. This is enough to detect “unsubscribed” events without diffing against a stored snapshot.
Step 5 — Incremental backfill (catching up after webhook downtime)
If your webhook receiver was down for a while, replay missed events with the delivery-log endpoint:dateUpdated seen as the watermark for the next sync.
Common gotchas
My import is creating duplicate contacts
My import is creating duplicate contacts
Orgo deduplicates by email — but only on
POST /api/v1/contacts. If your CRM has multiple records for the same person under different emails, Orgo will store them as separate Contacts. Dedupe in your CRM first, or merge in Orgo by DELETE-ing the older one and PATCH-ing the survivor.A contact converted into a User mid-sync — my CRM has stale state
A contact converted into a User mid-sync — my CRM has stale state
When a Contact becomes a User (via adhesion success or invite acceptance), Orgo keeps the Contact record but flips the linked User’s status. The
user.created webhook fires; subscribe to it and update your CRM to point at the User. The Contact remains for historical audit.Webhook deliveries are failing silently
Webhook deliveries are failing silently
Check
GET /api/v1/webhook_subscriptions/3/delivery_logs. Common causes: receiver returning a non-2xx, receiver taking >30s to respond, TLS certificate issues. Orgo retries 3 times with exponential backoff before giving up.Can I import Users directly instead of Contacts?
Can I import Users directly instead of Contacts?
Only if you also have authority to skip the adhesion (HR_TENANT).
POST /api/v1/users works server-to-server and creates a NEW user with an unverified email. The user can’t log in until they verify their email. For most CRM use cases, Contacts are the right primitive — promote selected ones to User via the adhesion flow when they’re ready to become members.What to do next
- Handle webhooks — the receiver implementation in detail
- Send a newsletter campaign — once contacts are synced, target them
- Onboard a new member — promote a Contact into a full member

