Meisa API Documentation

Integrate your application with Meisa

Get API Key

Quick Start

The Meisa API allows you to sync contacts, manage tags, and enroll users in sequences programmatically.

For integrations, use an API key (write-only syncing). For the Meisa dashboard, use JWT (Bearer token).

Base URL

https://api.meisa.io/api/v1

Authentication

Include your API key in the X-API-Key header with every request.

Need a higher-level overview? Read the Integration Contract.

# API keys are intended for write-only syncing from your backend.
curl -X POST "https://api.meisa.io/api/v1/contacts/upsert/" \
  -H "X-API-Key: meisa_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","external_id":"usr_123","custom_fields":{"plan":"free"}}'

Endpoints

Create a new contact or update an existing one by email or external_id. This is the recommended endpoint for syncing user data from your application.

Request Body

{
  "email": "[email protected]",
  "external_id": "usr_12345",          // Your internal user ID
  "first_name": "John",
  "last_name": "Doe",
  "custom_fields": {
    "plan": "pro",
    "mrr": 99.00,
    "signup_date": "2024-01-15"
  },
  "tag_names": ["paying-customer", "pro-plan"]
}

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "external_id": "usr_12345",
  "custom_fields": {
    "plan": "pro",
    "mrr": 99.00,
    "signup_date": "2024-01-15"
  },
  "tags": [
    {"id": "...", "name": "paying-customer"},
    {"id": "...", "name": "pro-plan"}
  ],
  "status": "active",
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}

Example: Python

import requests

MEISA_API_KEY = "meisa_live_your_api_key"
MEISA_BASE_URL = "https://api.meisa.io/api/v1"

def sync_user_to_meisa(user):
    """Sync a user to Meisa when they sign up or update their account."""
    response = requests.post(
        f"{MEISA_BASE_URL}/contacts/upsert/",
        headers={
            "X-API-Key": MEISA_API_KEY,
            "Content-Type": "application/json"
        },
        json={
            "email": user.email,
            "external_id": str(user.id),
            "first_name": user.first_name,
            "last_name": user.last_name,
            "custom_fields": {
                "plan": user.subscription.plan,
                "mrr": user.subscription.mrr,
                "signup_date": user.created_at.isoformat()
            }
        }
    )
    return response.json()

Example: JavaScript/Node.js

const axios = require('axios');

const meisa = axios.create({
  baseURL: 'https://api.meisa.io/api/v1',
  headers: {
    'X-API-Key': process.env.MEISA_API_KEY,
    'Content-Type': 'application/json'
  }
});

async function syncUserToMeisa(user) {
  const response = await meisa.post('/contacts/upsert/', {
    email: user.email,
    external_id: user.id,
    first_name: user.firstName,
    last_name: user.lastName,
    custom_fields: {
      plan: user.subscription?.plan,
      mrr: user.subscription?.mrr,
      signup_date: user.createdAt
    }
  });
  return response.data;
}

How Automations Work

The Simple Integration Pattern

Your integration only needs to sync data. Meisa's automation engine handles everything else-adding/removing tags, enrolling in sequences, and triggering actions based on field changes.

1. Your app sends: POST /contacts/upsert/ with current user state

2. Meisa detects which fields changed (e.g., plan: free → pro)

3. Automations you've configured in Meisa run automatically

Configure automations in Meisa to react to field changes. For example:

WhenThen
plan changes to "pro"Add tag "pro-plan", Remove tag "free-plan"
plan changes from "free" to any paidAdd tag "paying-customer", Enroll in "welcome-pro" sequence
plan changes to "churned"Add tag "churned", Enroll in "win-back" sequence

When to Sync Contacts

Best Practice: Sync on Key Events

Sync your contact data whenever user state changes that you care about. Meisa automations will detect field changes and react accordingly.

  • User Registration - Sync new user with initial plan, source, signup date
  • Plan Changes - Upgrade, downgrade, or cancellation events
  • User Login - Captures any profile updates since last sync
  • Profile Updates - When user updates important fields (optional)
  • Milestones - First purchase, usage thresholds, feature adoption (optional)

Remember: You don't need to manage tags or sequences in your code. Just sync the current user state, and Meisa automations handle the rest based on field changes.

Integration Examples

1. User Signup

When a user signs up, sync their initial state to Meisa.

// After user signup - just send the data
meisa.post('/contacts/upsert/', {
    email: user.email,
    external_id: user.id,
    first_name: user.firstName,
    custom_fields: {
        plan: 'free',
        signup_source: 'website',
        signup_date: new Date().toISOString()
    }
})
// Meisa automation handles: Add "free-plan" tag, Enroll in welcome sequence

2. Plan Upgrade

When a user upgrades, just update the plan field. Automations handle the rest.

// After successful payment - just update the plan
meisa.post('/contacts/upsert/', {
    email: user.email,
    custom_fields: {
        plan: 'pro',
        billing_cycle: 'annual',
        mrr: 99,
        upgraded_at: new Date().toISOString()
    }
})
// Meisa detects: plan changed from "free" to "pro"
// Automation runs: Remove "free-plan", Add "pro-plan", Add "paying-customer"

3. User Churns

When a user cancels, update their status. Automations trigger win-back campaigns.

// After cancellation - just update the state
meisa.post('/contacts/upsert/', {
    email: user.email,
    custom_fields: {
        plan: 'churned',
        previous_plan: 'pro',
        churned_at: new Date().toISOString(),
        churn_reason: reason
    }
})
// Meisa detects: plan changed to "churned"
// Automation runs: Remove "paying-customer", Add "churned", Enroll in win-back sequence

4. Complete Integration Example

A minimal integration class that syncs user events to Meisa.

class MeisaIntegration {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://api.meisa.io/api/v1';
    }

    async syncUser(user, extraFields = {}) {
        return fetch(`${this.baseUrl}/contacts/upsert/`, {
            method: 'POST',
            headers: {
                'X-API-Key': this.apiKey,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                email: user.email,
                external_id: user.id,
                first_name: user.firstName,
                last_name: user.lastName,
                custom_fields: {
                    plan: user.plan,
                    billing_cycle: user.billingCycle,
                    mrr: user.mrr,
                    ...extraFields
                }
            })
        });
    }
}

// Usage
const meisa = new MeisaIntegration(process.env.MEISA_API_KEY);

// On signup
await meisa.syncUser(user, { signup_date: new Date().toISOString() });

// On plan change
await meisa.syncUser(user, { upgraded_at: new Date().toISOString() });

// On churn
await meisa.syncUser({ ...user, plan: 'churned' }, {
    churned_at: new Date().toISOString(),
    churn_reason: 'too_expensive'
});

Rate Limits

LimitValue
Per Minute60 requests
Per Hour1,000 requests

Rate limits can be customized per API key. Contact support for higher limits.

Error Handling

The API returns standard HTTP status codes. Errors include a message explaining what went wrong.

StatusDescription
200Success
201Created
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - Insufficient permissions (check scopes)
404Not Found - Resource doesn't exist
429Too Many Requests - Rate limit exceeded

Need Help?

If you have questions or need assistance with your integration, we're here to help.

Contact Support