Email API
Send transactional emails (password reset, notices, confirmations) through Sendeasy from your own application, authenticated by the token of the email itself — every email configured in the project has its own.
Messages go out from the email that owns the token and consume 1 email credit of the project. You never pass the sender: it is the token's email. Have more than one email? Use the token of the one you want to send from.
Prerequisites
- Email token — in Channels → Email (or on the email card in Channels) → Settings → Sending API section. Each email has its own token; you can also generate a new one there (the previous one stops working immediately).
- The email with status Verified (same place). Without it the route answers
503 ERR_EMAIL_SENDER_NOT_CONFIGUREDand nothing is sent, even with credits. - Email credits available in the project plan.
Use GET /api/v1/email/health to check items 1 and 2 without spending credits.
Authentication
Required header, with the sender email's token:
Authorization: Bearer <email_token>
The token identifies the sender email and, through it, the project — there is no whatsappId/emailId in the URL.
Compatibility: the project API Token (the WABA API one) is also accepted in this header. In that case the sender is the project's first verified email — handy for integrations built before per-email tokens, but to choose the sender use the email token.
Endpoints
| Method | Endpoint | Purpose | Credit |
|---|---|---|---|
POST | /api/v1/email/send | Send a transactional email | 1 per send |
GET | /api/v1/email/health | Diagnostics: is the token's email verified? | none |
Rate limit: 20 requests per minute per origin (429 ERR_PUBLIC_EMAIL_RATE_LIMIT).
Sending an email
POST /api/v1/email/send
Payload
| Field | Type | Required | Notes |
|---|---|---|---|
to | string or string[] | Yes | up to 10 recipients per send |
subject | string | Yes | up to 200 characters |
html | string | One of the two | HTML body, up to 200,000 characters |
text | string | One of the two | plain-text body, up to 20,000 characters |
fromName | string | No | sender display name (up to 80 characters). The address is always the email that owns the token |
The sender address (fromEmail) is not accepted in the payload: the route always uses the email that owns the token. This prevents a token from sending on behalf of an email that is not yours.
Example
curl --location 'https://server.sendeasy.pro/api/v1/email/send' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer EMAIL_TOKEN' \
--data '{
"to": "customer@example.com",
"subject": "Password reset",
"fromName": "My Platform",
"html": "<p>Hi! Click the link below to create a new password.</p>"
}'
Success response:
{
"success": true,
"id": "9fbbb3a9-4c1e-4b1a-9d1e-0c2b7e3f5a61"
}
id is the provider's identifier for the send. The response confirms the email was accepted for delivery — final delivery depends on the recipient's mail server.
Integration diagnostics
GET /api/v1/email/health
Does not consume credits. Tells whether the token's email is already verified — the most common reason a send fails even with credits available.
curl --location 'https://server.sendeasy.pro/api/v1/email/health' \
--header 'Authorization: Bearer EMAIL_TOKEN'
{
"ok": true,
"senderConfigured": true,
"sender": "no-reply@yourcompany.com",
"domain": "yourcompany.com",
"channelId": 12
}
With senderConfigured: false, finish verifying the email in Channels → Email before sending. (With the project API Token the response has no channelId and tells whether the project has any verified email.)
Credits and refunds
- Every accepted send debits 1 email credit from the project.
- With no credits, the route answers
402 ERR_NO_EMAIL_CREDITSbefore any debit. - If the send fails after the debit (sender not configured, provider unavailable), the credit is refunded automatically and the route answers
502/503.
Error codes
| HTTP | error | When it happens |
|---|---|---|
| 400 | ERR_EMAIL_INVALID_BODY | invalid payload (missing to/subject, neither html nor text, no valid recipient) |
| 400 | ERR_EMAIL_TOO_MANY_RECIPIENTS | more than 10 recipients in one send |
| 401 | ERR_API_TOKEN_NOT_PROVIDED / ERR_API_TOKEN_INVALID | header missing or token invalid/inactive |
| 402 | ERR_NO_EMAIL_CREDITS | project has no email credits |
| 429 | ERR_PUBLIC_EMAIL_RATE_LIMIT | more than 20 requests per minute |
| 502 | ERR_EMAIL_SEND_FAILED | provider failure while sending (credit refunded) |
| 503 | ERR_EMAIL_SENDER_NOT_CONFIGURED | the token's email is not verified yet (with an email token, before any debit) |
Email API vs. Custom integration
Sendeasy offers two ways to send email by API — pick by the kind of token you have:
Email API (/api/v1/email/send) | Custom (/api/integration/generic) | |
|---|---|---|
| Token | email token (Channels → Email → Sending API) | integration token bound to one email channel |
| Sender | the email that owns the token | the token's channel |
| Typical use | transactional emails from your own application | per-channel integrations with bcc, inReplyTo, etc. |
Custom integration details at /en/server/integracoes.
Security: treat the token like a password. Never embed it in browser JavaScript, public repositories or logs — keep it in environment variables or a secret manager on your server.