Skip to main content

Send an email

POST/email/v1/emails

Sends an email from one of your templates to one address, with your values filled in. The email is charged and queued at once, then leaves within seconds.

Your key needs the Email API turned on, and in live your team must be approved. Your domain, senders, brand and templates are set up in the app. See Email.

Request body​

Content-Type: application/json

  • #tostringRequired
    The one address to send to. Up to 254 characters.
    Example: ada@example.com
  • #templatestringRequired
    The handle of one of your templates. Each template's handle is under Email › Templates.
    Example: verification-code
  • #valuesobjectOptional
    A value for each of the template's {{variables}}, by name. Every variable the template uses needs one. Each value is text, up to 1,000 characters. Leave it out for a template without variables.
    Example: {"first_name": "Ada", "code": "482913", "expires_in": "10 minutes"}
  • #fromstringOptional
    The address of one of your senders. Its name goes with it. Leave it out to send from your default sender.
    Example: billing@mail.example.com
  • #externalIdstringRequired
    Your own reference for the email, such as a sign-up or order number. Up to 64 characters, unique within your team. Reusing one returns the first email without charging again.
    Example: signup-8812
Retrying safely

If a request times out, send it again with the same externalId. If the first request went through, you get its email back with 200. You're charged once. See Retries and externalId.

Example request​

curl -X POST "https://sandbox-api.ponitor.com/email/v1/emails" \
-H "apiKey: $PONITOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "ada@example.com",
"template": "verification-code",
"values": {
"first_name": "Ada",
"code": "482913",
"expires_in": "10 minutes"
},
"externalId": "signup-8812"
}'

To send from another of your senders, add "from": "billing@mail.example.com".

Responses​

Created. The email was charged and queued. The body is the email, with status QUEUED. Follow it with Get an email or the email.* webhook events.

{
"id": "3f0e8a52-6f4b-4d0e-9b8a-2c1d0e9f8a7b",
"externalId": "signup-8812",
"from": "\"Example\" <hello@mail.example.com>",
"to": "ada@example.com",
"subject": "Your code is 482913",
"templateName": "Verification Code",
"status": "QUEUED",
"cost": 0.002,
"refunded": false,
"failureReason": null,
"createdAt": "2026-11-02T12:00:00.000Z",
"sentAt": null
}

The email object​

FieldDescription
idPonitor's ID for the email. Use it with GET /emails/{id}.
externalIdThe reference you sent. null for an email sent from the app.
fromThe sender's name and address, as inboxes show it.
toThe address it was sent to.
subjectThe subject, with your values filled in.
templateNameThe name of the template it was drawn from, as it was when sent.
statusQUEUED, SENT, DELIVERED, DELAYED, BOUNCED, COMPLAINED or FAILED. See What happens to an email.
costWhat your account was charged, in USD.
refundedWhether its cost went back to your account. true for a FAILED email, and only then.
failureReasonWhy a FAILED email failed. null otherwise.
createdAtWhen it was charged and queued.
sentAtWhen it left for the inbox. null until then.

Get an email also returns events, everything that happened to it.

Refused emails​

A refused email answers 400 or 404, and nothing is charged. Fix the request and send it again.

ProblemCodeMessage
A field is missing or invalid, such as toE01001Each field's message is in details, for example to is required
A variable the template uses has no valueE01002Give a value for {{code}}.
No from, and your team has no default senderE01002Add a sender under Email › Domains first.
The sender's domain isn't verifiedE01002This sender's domain isn't verified. Check it under Email › Domains.
The request names a workspaceE01002Email is your team's, not a workspace's. Leave out workspace.
No template has the handleE01005No template has the handle verification-code. Each template's handle is under Email › Templates.
from isn't one of your sendersE01005billing@mail.example.com isn't one of your email senders. Add it under Email › Domains.
Your account can't cover the emailE03001Insufficient account balance. Top up under Billing to continue.