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.