Skip to content
nsin docs

Send an email from one of the domain's addresses

POST
/domains/{domain}/email-routing/send
curl --request POST \
--url https://api.nsin.ir/domains/example.com/email-routing/send \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "from_local": "example", "from_name": "example", "to": [ "hello@example.com" ], "subject": "example", "text": "example" }'

Queues a plain-text message FROM an address that exists and is switched on on this domain, TO up to sending.max_recipients recipients. A mail host delivers it a few seconds later, signed with the domain’s DKIM key, so SPF, DKIM and DMARC pass for the domain. Replies go to the sender address and are forwarded like any other mail.

The answer is 202 with one queued row per recipient; read the outcome from the sent list. A soft failure is retried up to five times over about ninety minutes. Each recipient counts once against the plan’s max_email_sends_per_day (UTC day), delivered or not.

Refused when the plan does not include sending (403, code: plan), Email Routing is off (409, conflict: not_enabled), the domain is suspended (403, code: suspended), the daily limit is reached (429, code: daily_cap), the domain is sending too fast (429, code: rate) or too many of today’s messages were refused by the receiving servers (429, code: bounces). No HTML and no attachments. Requires records.edit.

domain
required
string

The domain name (for example example.com) — not a numeric id.

Example
example.com
Media type application/json
object
from_local
required

The part before @ of the sender. Must be an existing, switched-on address on the domain.

string
from_name

Optional display name shown next to the sender address.

string
<= 64 characters
to
required

Recipients. Duplicates are sent once.

Array<string>
>= 1 items
subject
required
string
<= 200 characters
text
required

The message as plain UTF-8 text.

string
Example generated
{
"from_local": "example",
"from_name": "example",
"to": [
"hello@example.com"
],
"subject": "example",
"text": "example"
}

Queued; one row per recipient and the updated sending allowance.

Media type application/json
object
messages
Array<object>

One recipient of one sent message.

object
id
integer
group_id

Shared by the recipients of one send.

string
from

The sender address.

string
from_name
string
to

This row’s recipient.

string
subject
string
status

queued with attempts above 0 is a soft failure waiting for its next try.

string
Allowed values: queued sending sent failed
attempts

Delivery attempts so far.

integer
smtp_code

The receiving server’s last reply code. 0 before the first attempt.

integer
response

The receiving server’s last reply text.

string
tls

TLS version of the last delivery connection

string
created_at
string format: date-time
sent_at
string | null format: date-time
next_try_at

When a soft failure is tried again.

string | null format: date-time
sending

Whether this domain may send mail right now, and how much of today’s allowance is used.

object
plan_enabled

The plan includes sending (email_sending_enabled).

boolean
allowed

A send would be accepted now (limits aside).

boolean
reason

Why not, when allowed is false: platform_off, plan, not_enabled or suspended. Empty otherwise.

string
max_per_day

Recipients the plan lets this domain send to per UTC day. null means unlimited.

integer | null
sent_today

Recipients queued so far today (UTC)

integer
max_recipients

Recipients allowed in one message.

integer
max_text_kb

Largest message text

integer
max_subject

Longest subject

integer
Example
{
"messages": [
{
"status": "queued"
}
]
}

A field is invalid; field is one of from_local, from_name, to, subject, text.

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
code

Machine-readable reason (hosts_not_ready, kek_unset, loop, no_mx, unverified).

string
field

The offending body field, when one applies.

string
Example
{
"error": "read-only API key"
}

Missing, malformed, revoked or expired API key. (A valid key whose account has been deactivated gets 403 account is inactive instead.)

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
Example invalidKey
{
"error": "invalid API key"
}

The domain has no active plan. The body carries upgrade_url.

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
max_rules
integer | null
upgrade_url
string
Examples
Example noPlan
{
"error": "This domain does not have an active plan. Purchase a plan for this domain before adding email addresses.",
"upgrade_url": "/plans"
}

The plan does not include sending (code: plan), or email on the domain is suspended (code: suspended).

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
code

Machine-readable reason (hosts_not_ready, kek_unset, loop, no_mx, unverified).

string
field

The offending body field, when one applies.

string
Example
{
"error": "read-only API key"
}

No such domain, or it is not visible to this account. Domains you cannot access are reported as not found rather than forbidden.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Example
{
"error": "read-only API key"
}

Email Routing is not enabled on the domain (conflict: not_enabled).

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
conflict

What conflicts (mx, spf, spf_multiple, external_dns, domain_status, not_enabled, local_part, destination).

string
records

For mx / spf_multiple — the rows in the way.

Array<object>
object
id
integer
name
string
content
string
priority
integer
record_id

For spf — the existing SPF row.

integer
content

For spf — its current value.

string
merged

For spf — what it becomes with our include merged in.

string
destination

For destination — the existing row.

object
id
integer
email
string
verified

Whether the address was confirmed through the emailed link.

boolean
verified_at

When it was confirmed.

string | null format: date-time
created_at
string format: date-time
last_sent_at

When the last verification mail went out.

string | null format: date-time
resend_cooldown_seconds

Seconds until another verification mail may be sent; 0 when allowed now.

integer
in_use

Rules and catch-alls pointing at it.

integer
last_failure

The receiving server’s last refusal, when forwards to it are bouncing.

string
last_failure_at

When last_failure was recorded.

string | null format: date-time
Example
{
"error": "read-only API key"
}

The text is over sending.max_text_kb.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Example
{
"error": "read-only API key"
}

The daily limit (code: daily_cap), the per-minute limit (code: rate) or today’s refusals (code: bounces).

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
code

Machine-readable reason (hosts_not_ready, kek_unset, loop, no_mx, unverified).

string
field

The offending body field, when one applies.

string
Example
{
"error": "read-only API key"
}

Sending is switched off on the platform (code: platform_off) or no mail host is ready (code: hosts_not_ready).

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
code

Machine-readable reason (hosts_not_ready, kek_unset, loop, no_mx, unverified).

string
field

The offending body field, when one applies.

string
Example
{
"error": "read-only API key"
}