curl --request POST \
--url https://api.torpedo.co.mz/api/v1/emails \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"from": "Acme <hello@myapp.com>",
"to": "user@example.com",
"subject": "Welcome to Acme",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
}
'import requests
url = "https://api.torpedo.co.mz/api/v1/emails"
payload = {
"from": "Acme <hello@myapp.com>",
"to": "user@example.com",
"subject": "Welcome to Acme",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
from: 'Acme <hello@myapp.com>',
to: 'user@example.com',
subject: 'Welcome to Acme',
html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>'
})
};
fetch('https://api.torpedo.co.mz/api/v1/emails', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.torpedo.co.mz/api/v1/emails",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'from' => 'Acme <hello@myapp.com>',
'to' => 'user@example.com',
'subject' => 'Welcome to Acme',
'html' => '<h1>Welcome!</h1><p>Thanks for signing up.</p>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.torpedo.co.mz/api/v1/emails"
payload := strings.NewReader("{\n \"from\": \"Acme <hello@myapp.com>\",\n \"to\": \"user@example.com\",\n \"subject\": \"Welcome to Acme\",\n \"html\": \"<h1>Welcome!</h1><p>Thanks for signing up.</p>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.torpedo.co.mz/api/v1/emails")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"from\": \"Acme <hello@myapp.com>\",\n \"to\": \"user@example.com\",\n \"subject\": \"Welcome to Acme\",\n \"html\": \"<h1>Welcome!</h1><p>Thanks for signing up.</p>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.torpedo.co.mz/api/v1/emails")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"from\": \"Acme <hello@myapp.com>\",\n \"to\": \"user@example.com\",\n \"subject\": \"Welcome to Acme\",\n \"html\": \"<h1>Welcome!</h1><p>Thanks for signing up.</p>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued"
}
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}Send email
Queues an email for delivery. Returns 202 Accepted immediately —
delivery is asynchronous. Use webhooks or poll GET /api/v1/emails/{id} for status.
The from address domain must be verified in your workspace.
Provide at least one of html or text. If html is provided without text,
Torpedo generates a plain-text version automatically. To opt out of a text part,
send text as an empty string.
curl --request POST \
--url https://api.torpedo.co.mz/api/v1/emails \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"from": "Acme <hello@myapp.com>",
"to": "user@example.com",
"subject": "Welcome to Acme",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
}
'import requests
url = "https://api.torpedo.co.mz/api/v1/emails"
payload = {
"from": "Acme <hello@myapp.com>",
"to": "user@example.com",
"subject": "Welcome to Acme",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
from: 'Acme <hello@myapp.com>',
to: 'user@example.com',
subject: 'Welcome to Acme',
html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>'
})
};
fetch('https://api.torpedo.co.mz/api/v1/emails', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.torpedo.co.mz/api/v1/emails",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'from' => 'Acme <hello@myapp.com>',
'to' => 'user@example.com',
'subject' => 'Welcome to Acme',
'html' => '<h1>Welcome!</h1><p>Thanks for signing up.</p>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.torpedo.co.mz/api/v1/emails"
payload := strings.NewReader("{\n \"from\": \"Acme <hello@myapp.com>\",\n \"to\": \"user@example.com\",\n \"subject\": \"Welcome to Acme\",\n \"html\": \"<h1>Welcome!</h1><p>Thanks for signing up.</p>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.torpedo.co.mz/api/v1/emails")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"from\": \"Acme <hello@myapp.com>\",\n \"to\": \"user@example.com\",\n \"subject\": \"Welcome to Acme\",\n \"html\": \"<h1>Welcome!</h1><p>Thanks for signing up.</p>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.torpedo.co.mz/api/v1/emails")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"from\": \"Acme <hello@myapp.com>\",\n \"to\": \"user@example.com\",\n \"subject\": \"Welcome to Acme\",\n \"html\": \"<h1>Welcome!</h1><p>Thanks for signing up.</p>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued"
}
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}{
"errors": [
{
"code": "VALIDATION_ERROR",
"message": "Domain not verified",
"field": "from"
}
]
}Authorizations
Prefix tor_ followed by a base64url-encoded random key.
Create and manage API keys from the authenticated Torpedo dashboard.
Headers
Unique key for replaying the original accepted response without sending again. Leading and trailing whitespace is removed; only the first 255 characters are retained.
Body
Provide at least one of html or text.
Sender address. Must use a verified domain. Accepts bare email or display name format.
255"Acme <hello@myapp.com>"
255"user@example.com"
1 - 255"Welcome to Acme"
HTML body of the email. If text is omitted, Torpedo generates plain text from this field.
1000000"<h1>Welcome!</h1><p>Thanks for signing up.</p>"
Optional plain-text body. Set to an empty string to send no text part.
100000"Welcome! Thanks for signing up."
Optional reply-to address
255Response
Email queued for delivery
Show child attributes
Show child attributes