Send email from your server language. Keep one observable API contract.
Choose a runtime-specific path for transactional email, product events, safe retries, and signed delivery callbacks.
✓Node.js, Python, PHP, Ruby, Go, Java, .NET, Rust, and Elixir.
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 ]Beyond the first request
A send call is the beginning of the integration.
Production email also needs stable identifiers, structured failures, safe retries, webhook verification, and product events that can drive lifecycle flows without duplicating messages.
Send deliberately
Validate the request and keep the returned message identifier for later evidence.
Retry safely
Separate temporary provider failures from invalid recipients and permanent request errors.
Observe outcomes
Verify delivery callbacks and process repeated events without repeating side effects.
[ 02 / 04 ]Choose a language
Use an SDK or the stable HTTP contract.
Node.js
Integrate with npm in TypeScript and JavaScript.
Python
Integrate with pip in sync and async Python services.
PHP
Integrate with Composer in modern PHP applications.
Ruby
Integrate with Bundler in Ruby services and background jobs.
Go
Integrate with Go modules in small, explicit Go services.
Java
Integrate with Maven or Gradle in JVM services.
.NET
Integrate with NuGet in C# services and hosted workers.
Rust
Integrate with Cargo in typed async Rust services.
Elixir
Integrate with Hex in BEAM applications and jobs.
[ 03 / 04 ]Every guide
A production path, not a hello-world dead end.
Install
Use the language package manager or a standard HTTP client.
Send
Keep credentials server-side and retain the message identifier.
Observe
Verify and process delivery events idempotently.
Common contract
- Typed send request
- Product event publishing
- Structured errors
- Verified webhooks
[ 04 / 04 ]Integration choice
Use the thinnest client that keeps the contract obvious.
The API behavior stays the same; only the amount of client-side convenience changes.
Setup
Package-manager install with typed helpers where available
Standard HTTP client with no product-specific dependency
Request shape
Runtime-native types and method names
Exact JSON payload from the API reference
Errors
SDK error wrapper plus response details
Status code and structured error envelope
Best fit
Supported runtimes where convenience reduces integration code
Any server runtime, including languages without a dedicated SDK
Questions people ask us
Find your runtime and queue one real message.
Start with the server language you already run and keep the result traceable.