Getting started
Authentication & scopes
Base URL
https://api.meisa.io/api/v1The X-API-Key header
Send your key in the X-API-Key header on every request. Requests are JSON (Content-Type: application/json).
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]" }'Keep keys server-side
API keys grant write access to your contacts and can send email. Never embed a key in frontend, mobile, or any client the user controls. Call Meisa from your backend only.
Environments
Keys are either live or test. Use a test key while building so you don't touch real contacts or send real email. GET /ping/ echoes which environment a key belongs to.
Scopes
Each key is granted a set of scopes. A request to an endpoint whose scope the key lacks returns 403. Grant the minimum a given integration needs.
| Scope | Grants |
|---|---|
contacts:read | Read contacts and the unsubscribed-emails list. |
contacts:write | Create/update contacts, upsert, and add/remove tags on a contact. |
events:track | Record custom events. |
sequences:read | List sequences and read a contact's enrollments. |
sequences:enroll | Enroll contacts in sequences. |
emails:trigger | Send triggered/transactional emails. |
A note on tags:write
You may see a tags:write scope when creating a key. Tag changes are currently authorized by contacts:write (via the contact's add_tag/remove_tag actions), so you don't need tags:write for anything today.
Rate limits
Default limits are 60 requests per minute and 1,000 per hour per key. Exceeding them returns 429. Limits can be raised per key — reach out if you need more headroom.
Errors
| Status | Meaning |
|---|---|
200 / 201 | Success. |
202 | Accepted — the work was scheduled (e.g. a delayed triggered email). |
400 | Bad request — invalid or missing fields. |
401 | Invalid or missing API key. |
403 | The key is valid but lacks the required scope. |
404 | Resource not found (e.g. no matching contact). |
422 | Unprocessable — e.g. the recipient is unsubscribed, or no sender is configured. |
429 | Rate limit exceeded. |
Errors return JSON with a human-readable message. For retries, retry on 5xx and 429 with backoff; do not retry 4xx (they won't succeed on repeat).