Documentation Index
Fetch the complete documentation index at: https://orbit-docs.devotel.io/llms.txt
Use this file to discover all available pages before exploring further.
Email attachments
Email sends through POST /v1/messages/email accept up to 20 attachments per email, totalling 25 MB across all attachments (RFC 5322 ceiling), with a per-file cap of 10 MB. Each attachment is referenced either by url (preferred — pre-uploaded to your file store or to Orbit’s /v1/files) or as inline base64 content.
URL-based attachments are fetched server-side, base64-encoded, and forwarded to the upstream provider. Orbit applies an SSRF allowlist so an attacker who controls a url field can’t pivot Orbit’s outbound network into your private network.
Limits
| Constraint | Value |
|---|
| Per-attachment size | 10 MB |
| Total per-email size | 25 MB (across all attachments combined) |
| Max attachments per email | 20 |
MIME allowlist
The content_type field must be one of:
application/pdf
application/msword
application/vnd.openxmlformats-officedocument.wordprocessingml.document (.docx)
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (.xlsx)
application/vnd.ms-powerpoint
application/vnd.openxmlformats-officedocument.presentationml.presentation (.pptx)
text/csv
text/plain
application/zip
image/jpeg
image/png
image/gif
image/webp
image/svg+xml
Anything else is rejected with 422 VALIDATION_ERROR. We block executables and unknown types so a customer can’t accidentally hand their domain reputation to a malware payload.
Filename rules
- Required, max 255 chars.
- May not contain
/, \\, or .. — guards against path traversal in downstream tools that re-emit the filename.
- The filename surfaces verbatim in the recipient’s mail client.
URL vs content
| Approach | When to use |
|---|
url | Files already hosted on your CDN, S3, or /v1/files. Preferred — keeps the request small and lets the platform stream the bytes server-side. |
content | Small files generated inline (signed PDFs, dynamic CSVs) where the round-trip to upload first isn’t worth it. Always base64-encoded. |
Each attachment object MUST include either url or content — not both, not neither.
Send with curl
URL-based attachment
curl -X POST https://orbit-api.devotel.io/api/v1/messages/email \
-H "X-API-Key: dv_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"from": "billing@yourdomain.com",
"subject": "Your invoice for May 2026",
"html": "<p>Your invoice is attached.</p>",
"attachments": [
{
"filename": "invoice-may-2026.pdf",
"content_type": "application/pdf",
"url": "https://files.yourdomain.com/invoices/may-2026.pdf",
"size": 348112
}
]
}'
Inline base64 attachment
curl -X POST https://orbit-api.devotel.io/api/v1/messages/email \
-H "X-API-Key: dv_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"from": "billing@yourdomain.com",
"subject": "Receipt",
"html": "<p>Receipt attached.</p>",
"attachments": [
{
"filename": "receipt.pdf",
"content_type": "application/pdf",
"content": "JVBERi0xLjQKJeLjz9MK..."
}
]
}'
Send with the Node.js SDK
import { Devotel } from "@devotel/orbit-sdk";
import { readFileSync } from "node:fs";
const orbit = new Devotel({ apiKey: process.env.ORBIT_API_KEY! });
await orbit.messages.send({
channel: "email",
to: "user@example.com",
from: "billing@yourdomain.com",
subject: "Your invoice for May 2026",
html: "<p>Your invoice is attached.</p>",
attachments: [
{
filename: "invoice-may-2026.pdf",
content_type: "application/pdf",
content: readFileSync("./invoice-may-2026.pdf").toString("base64"),
},
],
});
Send with the Python SDK
import base64
from orbit import Orbit
orbit = Orbit(api_key="dv_live_sk_...")
with open("invoice-may-2026.pdf", "rb") as f:
payload = base64.b64encode(f.read()).decode("ascii")
orbit.messages.send(
channel="email",
to="user@example.com",
from_address="billing@yourdomain.com",
subject="Your invoice for May 2026",
html="<p>Your invoice is attached.</p>",
attachments=[
{
"filename": "invoice-may-2026.pdf",
"content_type": "application/pdf",
"content": payload,
}
],
)
Send with the Go SDK
package main
import (
"encoding/base64"
"os"
orbit "github.com/devotel/orbit-go"
)
func main() {
client := orbit.NewClient("dv_live_sk_...")
pdf, _ := os.ReadFile("invoice-may-2026.pdf")
b64 := base64.StdEncoding.EncodeToString(pdf)
client.Messages.Send(orbit.SendMessageRequest{
Channel: "email",
To: "user@example.com",
From: "billing@yourdomain.com",
Subject: "Your invoice for May 2026",
HTML: "<p>Your invoice is attached.</p>",
Attachments: []orbit.EmailAttachment{
{
Filename: "invoice-may-2026.pdf",
ContentType: "application/pdf",
Content: b64,
},
},
})
}
Send with the Java SDK
import io.devotel.orbit.Orbit;
import io.devotel.orbit.models.EmailAttachment;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
Orbit orbit = new Orbit("dv_live_sk_...");
byte[] pdf = Files.readAllBytes(Path.of("invoice-may-2026.pdf"));
String b64 = Base64.getEncoder().encodeToString(pdf);
orbit.messages().sendEmail(
"user@example.com",
"billing@yourdomain.com",
"Your invoice for May 2026",
"<p>Your invoice is attached.</p>",
new EmailAttachment("invoice-may-2026.pdf", "application/pdf", b64)
);
Send with the PHP SDK
<?php
use Devotel\Orbit\OrbitClient;
$orbit = new OrbitClient("dv_live_sk_...");
$pdf = file_get_contents("invoice-may-2026.pdf");
$b64 = base64_encode($pdf);
$orbit->messages->send([
"channel" => "email",
"to" => "user@example.com",
"from" => "billing@yourdomain.com",
"subject" => "Your invoice for May 2026",
"html" => "<p>Your invoice is attached.</p>",
"attachments" => [[
"filename" => "invoice-may-2026.pdf",
"content_type" => "application/pdf",
"content" => $b64,
]],
]);
Send with the Ruby SDK
require "orbit"
require "base64"
orbit = Orbit::Client.new(api_key: "dv_live_sk_...")
pdf = File.binread("invoice-may-2026.pdf")
b64 = Base64.strict_encode64(pdf)
orbit.messages.send(
channel: "email",
to: "user@example.com",
from: "billing@yourdomain.com",
subject: "Your invoice for May 2026",
html: "<p>Your invoice is attached.</p>",
attachments: [
{
filename: "invoice-may-2026.pdf",
content_type: "application/pdf",
content: b64
}
]
)
Send with the C# SDK
using Devotel.Orbit;
var client = new OrbitClient("dv_live_sk_...");
var pdf = File.ReadAllBytes("invoice-may-2026.pdf");
var b64 = Convert.ToBase64String(pdf);
await client.Messages.SendAsync(new SendEmailRequest
{
To = "user@example.com",
From = "billing@yourdomain.com",
Subject = "Your invoice for May 2026",
Html = "<p>Your invoice is attached.</p>",
Attachments = new[]
{
new EmailAttachment
{
Filename = "invoice-may-2026.pdf",
ContentType = "application/pdf",
Content = b64,
},
},
});
Validation errors
| Code | HTTP | Cause |
|---|
VALIDATION_ERROR | 422 | Filename contains /, \\, or ..; MIME type not on the allowlist; total size exceeds 25 MB; more than 20 attachments; neither url nor content supplied. |
EMAIL_ATTACHMENT_FETCH_FAILED | 422 | Orbit could not fetch a url-style attachment (timeout, 404, host outside the SSRF allowlist). Re-host the file or use the /v1/files upload endpoint. |
EMAIL_ATTACHMENT_TOO_LARGE | 413 | The fetched bytes exceed the per-file 10 MB cap. |
See also