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, so 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).