Send email from your app
Send transactional email such as receipts and notifications with one API call, and check delivery in the Console.
Transactional mail is the email your app sends on its own: receipts, notifications, alerts, welcome messages. Each project can send it with one authenticated request. Sign-in emails such as verification codes and password resets are separate and are covered in Customize the emails your users receive.
Before you start
Sending needs your project's secret key (pgb_sec_...), so it must happen on your server, never in a browser or mobile app. See API keys. Your project also needs mail access: see Request approval to send email.
Open Transactional Mail
In the sidebar, under Core Services & Infrastructure, choose Transactional Mail. Once your project is approved you see:
- Monthly Quota: emails sent this month against the free allowance.
- Bounce Rate and Complaint Rate, with the quarantine thresholds beside them.
- Active Mail Provider and the Sender address.
- Email Event History & Delivery Logs: the latest 50 events, with recipient, subject, status and time.
- Sending Key & How To Send, with a ready-made example.
Send a test from the Console
- Choose Send a Test Email.
- Fill in Recipient Email, Subject and Message Body.
- Choose Send Live Test Email.
The message appears in Email Event History & Delivery Logs within moments.
Send from your code
curl -X POST https://my-project.pgbhub.app/mail/send \
-H "Authorization: Bearer pgb_sec_..." -H "Content-Type: application/json" \
-d '{"to": "[email protected]", "subject": "Welcome!", "text": "Thanks for signing up."}'
The request accepts:
| Field | Meaning |
|---|---|
to |
One recipient address |
subject |
Required, cannot be empty |
text |
Plain-text body. Required, cannot be empty |
html |
Optional HTML version |
from |
Optional sender. It must be on your verified domain or the default sender, otherwise the default sender is used |
reply_to |
Optional single address for replies. Line breaks, commas and semicolons are refused |
The response includes a message_id you can keep for your records.
With the TypeScript SDK:
const sent = await admin.mail.send({
to: "[email protected]",
subject: "Your receipt",
text: "Thanks for your order.",
html: "<p>Thanks for your order.</p>",
replyTo: "[email protected]",
});
console.log(sent.message_id);
The Python, Go and Rust SDKs have the same call. See Use the Python SDK and Use the Go and Rust SDKs.
Handle errors
| Response | What it means |
|---|---|
400 |
Something in the request is invalid, such as a bad address or an empty subject |
401 |
You did not use the project's secret key |
402 |
Your account is paused |
403 |
Mail is not approved, the project is quarantined, a limit was reached, or sending is paused. The message says which |
503 with MAIL_PROVIDER_UNAVAILABLE |
Sending is temporarily unavailable. Retry later |
Sends are never retried for you, because a retry could send the email twice. Retry only when you know the first attempt did not go out.
Good to know
totakes one address per request. To email many people, send one request per person.- Messages go out from the shared sender until you verify your own domain. See Send from your own domain.
- Keep subjects and content honest and expected by the recipient. High bounce or complaint rates lead to quarantine.
More guides in Console: sending email
Send email from your own domain
Verify your domain with DNS records so your app's email comes from your brand and your own address.
Request approval to send email, and how limits work
Why sending needs a quick review, how to request access, and the limits and reputation checks that protect your sending.