Send events and contacts from your app
Keep Meisa in sync with two calls: upsert the contact when their details change, and track an event when they do something that matters.
On this page
Your app keeps Meisa up to date with two calls: POST /contacts/upsert/ whenever a user signs up or their details change, and POST /events/track/ when they do something that matters, like starting a trial. Automations in Meisa then decide what to send.
Both calls need an API key. Upsert needs Add and update contacts (contacts:write) and tracking needs Track events (events:track). See Create and manage API keys.
Step 1: Create or update the contact (upsert)
Call upsert on signup and whenever something you segment on changes, like the plan.
curl -X POST "https://api.meisa.io/api/v1/contacts/upsert/" \
-H "X-API-Key: meisa_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"external_id": "user_8412",
"first_name": "Maya",
"last_name": "Chen",
"source": "signup",
"custom_fields": { "plan": "trial", "company": "Acme" },
"tag_names": ["trial-user"]
}'
How it works:
- Meisa looks for the contact by
external_idfirst, then byemail. If neither matches, it creates a new contact. emailis required. Sendexternal_id(your own user ID) too, so a user who changes their email stays the same contact.custom_fieldsare merged: fields you send are updated, fields you leave out are kept.tag_namesonly adds tags. To remove a tag, usePOST /contacts/{id}/remove_tag/withtag_name.sourcetells automations where the contact came from:api,signup,import,manualorinitial_sync. Useinitial_syncfor a one-off backfill so Contact is created automations can ignore it.
Upsert can start automations: Contact is created for new contacts, Field changes when a custom field changes, and Tag is added for new tags.
Step 2: Track events
Send an event when the user does something you want to react to.
curl -X POST "https://api.meisa.io/api/v1/events/track/" \
-H "X-API-Key: meisa_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"event_name": "trial_started",
"external_id": "user_8412",
"properties": { "plan": "pro" }
}'
event_nameis required. Identify the person withemailorexternal_id.- The contact must already exist, so upsert first. Tracking an event for an unknown person returns
404. - A successful call returns
"status": "tracked"with thecontact_id.
Use short, stable names in snake_case, like trial_started, project_created or hit_usage_limit. The automation trigger Your app sends an event must use exactly the same name.
Step 3: Let automations do the rest
In Meisa, create automations that react to your data:
- Your app sends an event
trial_started, then Start a sequence “Trial onboarding”. - Field changes on
planchanged topro, then Stop a sequence “Trial onboarding” and Start a sequence “Welcome to Pro”.
See Create an automation rule.
Good practice
- Make the calls from your backend, not the browser, so your API key stays secret.
- Don’t block your signup flow on Meisa. Send the calls in a background job and retry on
429or5xxerrors with backoff. - Keep field names consistent. A field called
planin one call andPlanin another becomes two fields.
Troubleshooting
- 404 on events/track: the contact doesn’t exist yet, or the
external_iddoesn’t match. Call upsert first. - 403: the key is missing the permission for that call.
- The automation didn’t fire: check the event name matches exactly, the automation is on, and for new contacts that the source is ticked under Which contacts count.
Related articles
Did this answer your question?
Thanks for letting us know.Thanks, we will improve this article. Want a hand right now?
Still need help?
Chat with us and get an answer in a few minutes.