# Sync new signups from your app to Meisa

Source: https://help.meisa.io/articles/sync-signups-from-your-app

To get every new user into Meisa, call `POST /contacts/upsert/` from your app's signup code with the user's email, your user ID and any fields you want to segment on. Then set up an automation on **Contact is created** to start your onboarding emails.

## What you need

- An API key with the **Add and update contacts** permission. See [Create and manage API keys](/articles/create-an-api-key).
- The key stored in your server's environment, for example as `MEISA_API_KEY`.

## Step 1: Send each signup to Meisa

Add one call where your app creates a user. Node.js example:

```js
async function syncToMeisa(user) {
  const res = await fetch('https://api.meisa.io/api/v1/contacts/upsert/', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.MEISA_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      email: user.email,
      external_id: String(user.id),
      first_name: user.firstName,
      source: 'signup',
      custom_fields: { plan: user.plan, signup_date: user.createdAt },
    }),
  });
  if (!res.ok) throw new Error(`Meisa sync failed: ${res.status}`);
}
```

Python example:

```python
import os, requests

def sync_to_meisa(user):
    r = requests.post(
        "https://api.meisa.io/api/v1/contacts/upsert/",
        headers={"X-API-Key": os.environ["MEISA_API_KEY"]},
        json={
            "email": user.email,
            "external_id": str(user.id),
            "first_name": user.first_name,
            "source": "signup",
            "custom_fields": {"plan": user.plan},
        },
        timeout=10,
    )
    r.raise_for_status()
```

Run the call in a background job so a slow network never holds up signup, and retry on `429` or `5xx` errors.

## Step 2: Keep the contact up to date

Call the same upsert when something changes, like an upgrade or a new email address. Meisa matches on `external_id` first, then `email`, so the person stays one contact. Only the fields you send change.

```json
{ "email": "maya@example.com", "external_id": "8412", "custom_fields": { "plan": "pro" } }
```

## Step 3: Start onboarding automatically

1. In Meisa, go to **Automations** and click **New automation**.
2. Under **When**, pick **Contact is created**. Under **Which contacts count**, keep **Your app** and **Signup forms** ticked.
3. Under **Then**, pick **Start a sequence** and choose your onboarding sequence.
4. Click **Turn on**.

To react to upgrades, add a second automation on **Field changes** for `plan`. See [Create an automation rule](/articles/create-an-automation-rule).

## Bring in your existing users

For users who signed up before you connected Meisa, either [import a CSV](/articles/import-contacts-from-csv) or run a one-off script that upserts each user with `"source": "initial_sync"`. Contacts with that source are left out of **Contact is created** automations by default, so your existing users don't get a welcome email.

## Respect unsubscribes in your app

If your app also sends email, fetch the list of people who unsubscribed in Meisa with `GET /contacts/api/unsubscribed-emails/` (needs **Read contacts**) and skip them on your side.

## Troubleshooting

- **401 or 403**: check the key and that it has **Add and update contacts**.
- **Duplicates**: always send the same `external_id` for the same user.
- **No welcome email**: check the automation is on and the onboarding sequence is on.

## Related articles

- [Send events and contacts from your app](/articles/send-events-from-your-app)
- [Create an automation rule](/articles/create-an-automation-rule)
- [Import contacts from a CSV file](/articles/import-contacts-from-csv)
- [Create an onboarding email sequence](/articles/create-an-email-sequence)
