Meisa Help

API quickstart: your first API call

Create an API key, call /ping/ to check it, then add a contact and send a transactional email in three calls.

Updated 2 min read
On this page

The Meisa API lives at <https://api.meisa.io/api/v1> and every call sends your key in the X-API-Key header. Create a key, call /ping/ to check it works, then add a contact and send your first email.

Step 1: Create an API key

  1. Go to Settings, then API keys and webhooks.
  2. Click Create API key, name it, and pick Everything under Permissions for this test. Use narrower permissions in production.
  3. Click Create key and Copy key.

Full details: Create and manage API keys.

Store the key in an environment variable so it stays out of your code:

export MEISA_API_KEY="meisa_live_your_key"

Step 2: Check the key

curl "https://api.meisa.io/api/v1/ping/" \
  -H "X-API-Key: $MEISA_API_KEY"

You get back "status": "ok", the key’s permissions and the product it belongs to. If you see 401, the key is wrong or revoked.

Step 3: Add a contact

curl -X POST "https://api.meisa.io/api/v1/contacts/upsert/" \
  -H "X-API-Key: $MEISA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "[email protected]", "first_name": "Sam", "source": "api" }'

Upsert creates the contact or updates it if it already exists. Use your own address for this test.

Step 4: Send a transactional email

First create a transactional email in Meisa with the key welcome (see Send transactional emails with triggers). Then:

curl -X POST "https://api.meisa.io/api/v1/emails/trigger/" \
  -H "X-API-Key: $MEISA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "trigger_key": "welcome", "to_email": "[email protected]", "variables": { "first_name": "Sam" } }'

A 200 with "status": "sent" means it’s on its way. Check your inbox.

The same calls in JavaScript

const MEISA = '<https://api.meisa.io/api/v1'>;
const headers = { 'X-API-Key': process.env.MEISA_API_KEY, 'Content-Type': 'application/json' };

await fetch(`${MEISA}/contacts/upsert/`, {
  method: 'POST', headers,
  body: JSON.stringify({ email: '[email protected]', first_name: 'Sam', source: 'api' }),
});

const res = await fetch(`${MEISA}/emails/trigger/`, {
  method: 'POST', headers,
  body: JSON.stringify({ trigger_key: 'welcome', to_email: '[email protected]', variables: { first_name: 'Sam' } }),
});
console.log(res.status, await res.json());

Call the API from your server only. Never ship your key in browser or mobile code.

Main endpoints

What Endpoint Permission
Check your key GET /ping/ any
Create or update a contact POST /contacts/upsert/ contacts:write
Get unsubscribed addresses GET /contacts/api/unsubscribed-emails/ contacts:read
Track an event POST /events/track/ events:track
List sequences GET /sequences/api/list/ sequences:read
Enroll in a sequence POST /sequences/enroll/ sequences:enroll
Send a transactional email POST /emails/trigger/ emails:trigger
Send a direct email POST /emails/send/ emails:trigger

The full reference is in the developer docs, linked from API keys and webhooks. That page also links a single spec file you can hand to your AI coding assistant.

Errors and limits

Code Meaning What to do
400 Missing or invalid field Read the error message in the response.
401 Missing, wrong or revoked key Check the X-API-Key header.
403 Key lacks the permission Create a key with the right permission.
404 Contact or item not found Upsert the contact first, or check the slug.
422 Can’t send (unsubscribed, no sender) Check the contact and your sender setup.
429 Rate limit hit Wait and retry with backoff.

Each key has its own per-minute and per-hour limit, shown in the /ping/ response. Retry 429 and 5xx errors with exponential backoff, and don’t retry other 4xx errors without fixing the request.

Did this answer your question?

Still need help?

Chat with us and get an answer in a few minutes.