Guides
Integration contract
The contract in one sentence
Keep each user's current state synced to Meisa via POST /api/v1/contacts/upsert/, storing product-specific telemetry under custom_fields. Meisa detects changes and runs the automations your team has configured.
Required identifiers
email— the contact's primary email (the upsert key).external_id— your internal user ID (stable, unique). Always send it.
Custom fields are the core
Put everything you want your team to automate on into custom_fields. Keep field names stable once introduced, and only send fields that matter to your lifecycle. Here's a copy/paste-friendly taxonomy — use what fits your domain:
Billing
plan·free / standard / pro / churnedsubscription_status·active / trialing / past_due / canceledbilling_cycle·monthly / annual / lifetime
Lifecycle & onboarding
signup_date·ISO stringlast_active·ISO stringonboarding_completed·booleansignin_count·number
Usage / telemetry (examples)
posts_generated·numberideas_generated·numberprojects_created·numberfeature_x_used·boolean
Acquisition & attribution
referral_source·stringutm_source·stringutm_campaign·stringcountry·string
Sync timing
- On signup — sync immediately.
- On plan / billing change — sync immediately.
- On login — sync to refresh
last_activeandsignin_countcheaply. - On milestones — sync when a threshold is crossed.
You don't need a nightly bulk re-sync. Event-driven deltas (signup, login, plan change, churn) keep Meisa accurate with minimal load.
How this enables non-technical workflows
Once state is flowing, your team builds automations against it without touching code:
- Contact created → enroll in onboarding sequence.
- Contact updated (e.g.
planfree → pro) → tag and enroll. - Conditions on any custom field (e.g.
posts_generated ≥ 5).
See How automations work for the full trigger and action set.
Minimal payload
{
"email": "[email protected]",
"external_id": "usr_12345",
"first_name": "Jane",
"custom_fields": {
"plan": "free",
"posts_generated": 0,
"onboarding_completed": false
}
}