Quickstart
Send your first transactional email through the public API, check its status, and learn where to go next. This guide is for anyone integrating EmailMassivo for the first time.
Before you start
- A EmailMassivo account and a verified domain in the dashboard.
- An enabled default key of that domain — the email from step 2 goes through it.
How to assign and change the default key is covered in Sending keys.
Step 1. Create a token
Issue a token with the email.send and email.read scopes — there's a step-by-step walkthrough in Authentication → Creating a token. Save the value right away: it's shown only once.
Put the token in an environment variable — substitute your full value, starting with rs_ck_v1_:
export API_TOKEN="rs_ck_v1_..."
Step 2. Send an email
The minimal body is a sender, a recipient, a subject, and html. In the example, replace noreply@yourdomain.com with an address in your verified domain, and you@example.com with your own mailbox: that's where the email arrives. You don't need to pass the key id: the email goes through the default key of the sender's domain.
- TypeScript
- Go
- Python
- cURL
async function main() {
const response = await fetch('https://api.emailmassivo.com/api/v1/public/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'quickstart-1',
},
body: JSON.stringify({
data: {
from: { email: 'noreply@yourdomain.com' },
to: { email: 'you@example.com' },
subject: 'My first email via the API',
html: '<h1>It works!</h1>',
},
}),
});
console.log(response.status, await response.text());
}
main().catch(console.error);
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"os"
)
func main() {
body := []byte(`{
"data": {
"from": {"email": "noreply@yourdomain.com"},
"to": {"email": "you@example.com"},
"subject": "My first email via the API",
"html": "<h1>It works!</h1>"
}
}`)
req, err := http.NewRequest("POST", "https://api.emailmassivo.com/api/v1/public/emails", bytes.NewReader(body))
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "quickstart-1")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
out, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.StatusCode, string(out))
}
import os
import requests
response = requests.post(
'https://api.emailmassivo.com/api/v1/public/emails',
headers={
'Authorization': f'Bearer {os.environ["API_TOKEN"]}',
'Idempotency-Key': 'quickstart-1',
},
json={
'data': {
'from': {'email': 'noreply@yourdomain.com'},
'to': {'email': 'you@example.com'},
'subject': 'My first email via the API',
'html': '<h1>It works!</h1>',
},
},
)
print(response.status_code, response.text)
curl -sS -w '\n%{http_code}\n' -X POST https://api.emailmassivo.com/api/v1/public/emails \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-1" \
-d '{
"data": {
"from": {"email": "noreply@yourdomain.com"},
"to": {"email": "you@example.com"},
"subject": "My first email via the API",
"html": "<h1>It works!</h1>"
}
}'
Step 3. Check the response
A successful response is 202 Accepted:
{
"ok": true,
"data": {
"id": "0199b2f4-6c1e-7a3d-9f2b-4e8c1d7a5b60",
"status": "queued",
"createdAt": "2026-09-30T10:15:00.000Z",
"recipients": [
{
"id": "3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e01",
"email": "you@example.com",
"name": null,
"type": "to",
"status": "queued",
"reason": null
}
]
},
"meta": { "requestId": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2026-09-30T10:15:00.120Z" }
}
data.id is the email identifier: store it to track what happens to the send. The Idempotency-Key header protects against duplicates: if you repeat the request with the same key, no second email goes out. To send the example again, change the value — for example, to quickstart-2. See Idempotency and quota for details.
If the response is an error, look up its error.code in Send error codes. The most common errors on a first request are SENDER_DOMAIN_MISMATCH (the sender address isn't in the key's domain) and SENDING_KEY_NOT_ACTIVE (the key isn't enabled yet). 401 and 403 errors concern the token — see Authentication → Handling errors.
Step 4. Check the email status
Save data.id from the step 3 response in an environment variable — the example uses the value from the response above; substitute your own:
export EMAIL_ID="0199b2f4-6c1e-7a3d-9f2b-4e8c1d7a5b60"
- TypeScript
- Go
- Python
- cURL
async function main() {
const response = await fetch(`https://api.emailmassivo.com/api/v1/public/emails/${process.env.EMAIL_ID}`, {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
},
});
console.log(response.status, await response.text());
}
main().catch(console.error);
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.emailmassivo.com/api/v1/public/emails/"+os.Getenv("EMAIL_ID"), nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
out, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.StatusCode, string(out))
}
import os
import requests
response = requests.get(
f'https://api.emailmassivo.com/api/v1/public/emails/{os.environ["EMAIL_ID"]}',
headers={'Authorization': f'Bearer {os.environ["API_TOKEN"]}'},
)
print(response.status_code, response.text)
curl -sS -w '\n%{http_code}\n' https://api.emailmassivo.com/api/v1/public/emails/$EMAIL_ID \
-H "Authorization: Bearer $API_TOKEN"
Once the recipient's mail server confirms receipt, the recipient status becomes delivered. What the other statuses mean is covered in Email statuses and events.
What's next
- Send production transactional emails (copies, templates, attachments, idempotency) → Send a transactional email.
- Receive statuses on your server → Email webhooks.
- Send from a template → Templates and aliases.
- Manage your contact base via the API → Reference: lists.