Send product email from Go. One request, explicit failure modes.
Send transactional email and publish lifecycle events from small, explicit Go services with the Send & Retain API.
✓Use net/http, pass context deadlines, and keep the accepted message ID.
One request, complete trace
Request
POST /api/v1/emails
Authorization: Bearer aem_…
Idempotency-Key: welcome-8f21
{ "to": "[email protected]", "template": "welcome" }
202 Accepted
{ "id": "msg_7ca31", "status": "queued" }
[ 01 / 04 ]Client contract
Keep the integration explicit and dependency-light.
Start with net/http
Build the request with net/http and encoding/json, using the client and context your service already owns.
Send typed payloads
Struct tags map cleanly onto the payload, so the compiler catches a wrong field name.
Handle delivery events
Read the body with io.ReadAll before decoding, so the HMAC covers the exact bytes.
[ 02 / 04 ]Server quickstart
Queue one email from Go.
One call, one message ID, one delivery timeline.
Close the response body and distinguish transport failure from an accepted queued message.
req, err := http.NewRequest(http.MethodPost, emailURL, payload)
if err != nil { return err }
req.Header.Set("Authorization", "Bearer "+os.Getenv("AEM_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "welcome-"+user.ID)
res, err := http.DefaultClient.Do(req)Accepted response
{ "id": "msg_7ca31", "status": "queued" }[ 03 / 04 ]Quickstart
Treat acceptance and delivery as two different outcomes.
Build a bounded request
Pass the caller's context, set a timeout, and read the API key from server configuration.
Check the response class
Separate transport errors, structured API errors, and an accepted queued message.
Correlate the callback
Store the returned identifier and process signed delivery events idempotently.
Production checklist
- Secrets stay server-side
- Timeout and retry policy
- Idempotent webhook handler
- Structured error logging
Questions people ask us
Queue your first email from Go.
Make one bounded request, keep the ID, and handle delivery as a separate event.