Sending Email with SendNeo
Sending email with SendNeo
SendNeo's email API is compatible with the common Resend request shape. All endpoints use https://sendneo.yorkermedia.com/api and a bearer key.
Authorization: Bearer sn_live_...
Content-Type: application/json
POST /emails
| Field | Type | Required | Notes |
|---|---|---|---|
from |
string | yes | A verified sender, optionally with a display name. |
to |
string or array | yes | One or more recipients. |
subject |
string | yes | Subject line. |
html |
string | no | HTML body. Supply text too for a plain-text alternative. |
text |
string | no | Plain-text body. |
cc |
string or array | no | Carbon-copy recipients. |
bcc |
string or array | no | Blind-copy recipients. |
reply_to |
string or array | no | Reply address or addresses. |
headers |
object | no | Additional message headers. |
tags |
array | no | Application labels for filtering and reporting. |
scheduled_at |
ISO 8601 string | no | Deliver at a future time. |
attachments |
array | no | Base64 file content plus a filename. |
A minimal request looks like this:
curl https://sendneo.yorkermedia.com/api/emails \
-X POST \
-H "Authorization: Bearer $SENDNEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <hello@mail.example.com>",
"to": "person@example.net",
"subject": "Receipt",
"html": "<p>Thanks for your order.</p>",
"text": "Thanks for your order."
}'
The response is an object containing the message ID:
{"id":"email_01J..."}
Use GET /emails/{id} to read the current status.
Batch sends
POST /emails/batch accepts up to 100 email objects in one request. Each object uses the same fields as POST /emails. Keep each recipient's message separate when personalization or privacy matters.
curl https://sendneo.yorkermedia.com/api/emails/batch \
-X POST \
-H "Authorization: Bearer $SENDNEO_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{"from":"Acme <hello@mail.example.com>","to":"a@example.net","subject":"Hi A","text":"Hello A"},
{"from":"Acme <hello@mail.example.com>","to":"b@example.net","subject":"Hi B","text":"Hello B"}
]'
Scheduling and canceling
Add scheduled_at to an email request with an ISO 8601 timestamp. Store the returned ID. Before delivery, cancel it with:
curl https://sendneo.yorkermedia.com/api/emails/email_01J.../cancel \
-X POST \
-H "Authorization: Bearer $SENDNEO_API_KEY"
A message that has already been delivered cannot be canceled. Check GET /emails/{id} if a cancellation races with delivery.
Idempotency
Send the Idempotency-Key header when a timeout or network retry could submit the same message twice. Keys are retained for 24 hours. Reusing a key with the same request lets your retry receive the original result; changing the request under an existing key is an error.
Idempotency-Key: order-8472-confirmation
Use an application-level unique value such as an order ID plus message purpose. Do not use one constant key for all mail.
Tags
Tags are application labels, for example:
{"tags":[{"name":"order_id","value":"8472"},{"name":"stream","value":"receipts"}]}
Keep values free of secrets. Tags help you group your own messages; they do not replace a recipient list or audience.
Attachments
Each attachment contains base64 content and a filename. The combined attachment size for one message is limited to 7 MB.
{
"attachments": [
{
"filename": "receipt.pdf",
"content": "JVBERi0xLjQK..."
}
]
}
Base64 increases the wire size, so check the decoded files before building the request. Use a short, safe filename and do not place credentials in an attachment.
Errors and HTTP codes
Errors use one consistent shape:
{"error":{"type":"invalid_request","message":"The from address is not verified"}}
| Code | Meaning |
|---|---|
400 |
Malformed JSON or an invalid combination of fields. |
401 |
Missing, malformed, or invalid bearer key. |
403 |
The key is valid but the action is not allowed, such as live delivery during review. |
404 |
The message, domain, or other resource does not exist. |
409 |
A conflicting operation, including an idempotency conflict. |
413 |
Request or attachment size is too large. |
422 |
The fields parse but fail validation, such as an unverified sender. |
429 |
The key exceeded 10 requests per second. Honor Retry-After before retrying. |
500 |
A temporary server error. Retry safely with the same idempotency key. |
A retry loop should retry 429 and suitable 5xx responses, respect Retry-After, and preserve the original idempotency key. Do not blindly retry a 4xx validation error.
For newsletters, use the audiences and broadcasts API described in Newsletters. For delivery events, configure webhooks.