- Contacts: users, buyers, admins, members, or invitees.
- Companies: accounts, workspaces, teams, stores, practices, or organisations.
- Memberships: which contact belongs to which company, including role and primary company.
- Properties: source-managed company fields such as plan, signup reason, account status, or onboarding answers.
- Events: stable product milestones that should trigger journeys.
Prerequisites
You’ll need a
sk_ project key with write access. See Authentication for key setup.Spotzee-Version: 2026-04-28 on each request so payload behaviour stays pinned.
Walkthrough
1
Choose your source namespace
Pick a short, stable source key for your product. It must start with a letter and only use lowercase letters, numbers, and underscores.Use the same
source value on identities, companies, property manifests, and memberships.2
Use stable source IDs
Keep your own product IDs as source IDs. They should be stable even if the customer changes email address, company name, or role.
3
Hash the normalised email
external_id must be the SHA-256 hex digest of the customer’s normalised email address.4
Declare source-managed properties
Create a property manifest before sending source-managed CRM properties. Property keys must start with your source namespace plus an underscore.Use
mode: "merge" or omit mode when you only want to create or update the listed properties. Use mode: "replace" with replace_scope.object_types when the submitted list is authoritative for those object types; Spotzee archives omitted source-managed properties in that scope.5
Upsert the contact identity
Send each known person with your source ID, the email-hash A successful response returns
external_id, and any useful contact data.status: "upserted". If the response returns status: "quarantined", do not retry blindly; review the identity conflict first.6
Upsert the company
Send each account, team, or workspace as a CRM company. Put source-managed fields in
properties.7
Link contacts to companies
Create a membership after both the identity and company exist. Mark one membership as
primary when that company should become the contact’s primary company in the CRM.8
Track product events with the same ID
Send journey-triggering events through the Events API using the same email-hash Keep event names stable. Put changing details in
external_id.data, not in the event name.Backfill order
For an existing product, backfill in this order:- Property manifests.
- Contact identities.
- Companies.
- Memberships.
- High-value historical events, if you want journeys and reporting to see past milestones.
Idempotency-Key values for retries and replays.
Pitfalls to avoid
- Don’t send company properties before the manifest. Spotzee validates source-managed company property keys against the latest manifest.
- Don’t omit the source prefix on property keys.
acmeapp_planis valid forsource: "acmeapp";planis not source-managed. - Don’t use replace mode with a partial manifest. In
mode: "replace", omitted source-managed properties are archived for the object types inreplace_scope.object_types. - Don’t send memberships before identities and companies. The membership endpoint links existing source records.
- Don’t retry quarantined identities as a normal failure. A quarantine means the same source person now points at an email hash already used elsewhere.
- Don’t include secrets or raw message content in event data. Send stable public IDs, status fields, plan fields, amounts, currency, and coarse failure categories.
Reference
- Source-sync endpoints: see Main API -> Source Sync
- Events: see Send events from your backend
- Authentication: see Authentication
- Safe retries: see Idempotency
- CRM concepts: see CRM
- Journeys: see Journeys