Send API and SMTP

SRVO Send is a Resend drop-in for the endpoints listed below. Use https://api.srvo.app as the base URL and a Send key as the bearer token. There is no /api/v1 suffix on the Resend-compatible routes.

First verify a domain and create a Send key. Store the key in SRVO_SEND_KEY in your application’s secrets. Sending keys work with the compatible API and SMTP; they are separate from general SRVO API keys and MCP sign-in.

Use the Resend SDK

Set the Resend SDK’s baseUrl to SRVO. Use a sender on your verified domain and replace the example recipient.

pnpm add resend
import { Resend } from "resend";

const resend = new Resend(process.env.SRVO_SEND_KEY, {
  baseUrl: "https://api.srvo.app",
});

const { data, error } = await resend.emails.send({
  from: "Example <hello@mail.example.com>",
  to: ["recipient@example.com"],
  subject: "Hello",
  html: "<p>Hello from SRVO Send.</p>",
});

if (error) throw new Error(error.message);
console.log(data?.id);

Send with curl

A successful request returns { "id": "…" }. Acceptance means queued, not delivered.

export SRVO_SEND_KEY='your-send-key'
curl --fail-with-body https://api.srvo.app/emails \
  -H "Authorization: Bearer $SRVO_SEND_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: welcome-order-123' \
  -d '{"from":"Example <hello@mail.example.com>","to":["recipient@example.com"],"subject":"Hello","html":"<p>Hello from SRVO Send.</p>"}'

Available endpoints

Method Path Purpose
POST /emails Send one email
POST /emails/batch Send up to 100 messages; no attachments or scheduling
GET /emails, /emails/{id} List emails or get one email
PATCH /emails/{id} Reschedule a scheduled email
POST /emails/{id}/cancel Cancel a scheduled email
GET, POST /domains List or create domains
GET, PATCH, DELETE /domains/{id} Read, update or delete a domain
POST /domains/{id}/verify Check DNS verification
GET /api-keys List Send keys
GET, POST /suppressions List or add suppressed addresses
GET, DELETE /suppressions/{id} Read or remove a suppression
POST /suppressions/batch/add, /suppressions/batch/remove Add or remove up to 1,000 addresses

Only listing keys is available at /api-keys. Create and revoke keys in Send → API keys, or through the native SRVO API with its own authentication. Use a full_access Send key for administration on the compatible API. A sending_access key is for sending, including allowed changes to its own scheduled messages.

Retry safely

Send Idempotency-Key with POST /emails or POST /emails/batch. Use 1–256 characters. SRVO keeps the key for 24 hours. Reuse the same key and payload when retrying one intended send. Use a new key for a different send.

A changed payload with the same key returns 409 invalid_idempotent_request. An overlapping request can return 409 concurrent_idempotent_requests; retry later with the same key.

Attachments and message limits

Send attachments as base64 content or as an HTTPS path URL. Do not include a data-URL prefix in content.

{
  "attachments": [
    { "filename": "hello.txt", "content": "SGVsbG8=" },
    { "filename": "invoice.pdf", "path": "https://example.com/invoice.pdf" }
  ]
}
  • Up to 50 recipients across to, cc and bcc.
  • Up to 50 attachments, including at most 10 URL attachments.
  • Each URL attachment is limited to 8 MiB and must be on a public HTTPS host. The fetch timeout is 10 seconds. Private network addresses are refused.
  • The whole message is limited to 40 MiB, including base64 attachment content. Base64 increases file size by about one third. Each html and text body is limited to 2,097,152 characters.
  • Executables and blocked script file types are refused. Batch sends do not accept attachments or scheduling.

Errors and rate limits

Error responses contain statusCode, name and message:

{ "statusCode": 401, "name": "missing_api_key", "message": "…" }
  • 400: invalid idempotency key.
  • 401: missing, invalid or restricted Send key.
  • 403: unverified domain, forbidden domain or access, or security_error when sending is paused.
  • 404: resource not found.
  • 409: conflict or idempotency error.
  • 422: invalid request fields.
  • 429: rate_limit_exceeded, daily_quota_exceeded or monthly_quota_exceeded.
  • 5xx: temporary server error. Retry with backoff and the same idempotency key.

The compatible API currently allows 10 requests per second per workspace across its routes. Read ratelimit-limit, ratelimit-remaining and ratelimit-reset. When present, follow Retry-After before retrying a 429. A quota error needs quota or warm-up capacity to become available; repeated immediate retries will not help. See sending limits and warm-up.

SMTP relay

Configure your SMTP client with:

  • Host: smtp.srvo.app.
  • Port: 56747.
  • Security: implicit TLS, often called SSL/TLS; secure: true in Nodemailer.
  • Username: resend or srvo.
  • Password: your Send key.

The sender must use a verified domain allowed for that key. The raw message limit is 28 MiB, about 28 MB, including MIME headers and encoded attachments. The combined recipient limit is 50. Use the published port above, rather than assuming port 465 or 587.

Payload CMS

Use @srvosystems/payload-email for Payload CMS v3. It is distributed through GitHub Packages. Add the following to your project’s .npmrc. Supply GITHUB_TOKEN through your environment with read:packages and access to the package. Never commit the token.

@srvosystems:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
pnpm add @srvosystems/payload-email
// payload.config.ts
import { buildConfig } from "payload";
import { srvoSendAdapter } from "@srvosystems/payload-email";

export default buildConfig({
  email: srvoSendAdapter({
    apiKey: process.env.SRVO_SEND_KEY!,
    defaultFromAddress: "hello@mail.example.com",
    defaultFromName: "Example",
  }),
  // Add your collections and other Payload settings here.
});

Replace the sender with an address on your verified domain. The adapter uses https://api.srvo.app by default. Call payload.sendEmail(...) as usual; the returned id identifies the message in Send.

Coming soon

Broadcasts, Audience and contacts, Templates, and automatic DNS setup through Domain Connect are coming soon. This guide covers the available transactional sending routes.