Set up email routing in one call
const url = 'https://api.nsin.ir/domains/example.com/email-routing/setup';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"local_part":"example","destination_email":"hello@example.com","remove_existing_mx":false,"merge_spf":false}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.nsin.ir/domains/example.com/email-routing/setup \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "local_part": "example", "destination_email": "hello@example.com", "remove_existing_mx": false, "merge_spf": false }'The first-run shortcut: turns routing on (exactly as the enable
endpoint does, with the same remove_existing_mx / merge_spf
answers and the same refusals), adds destination_email to the domain
owner’s account if it is not there yet, and creates
local_part@domain forwarding to it.
The destination gets one verification mail and the address stays
inactive until the link is clicked — unless the destination is the
owner’s own verified account email, which is saved verified and gets
no mail. Everything is checked before anything is written, and the
enable runs first: a refused setup creates nothing. If a later step
fails after the enable (a destination cap, a rule limit) the error body
carries enabled: true. Safe to repeat: an existing destination and an
existing address are kept as they are. Requires domain.settings.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”The domain name (for example example.com) — not a numeric id.
Example
example.comRequest Body required
Section titled “Request Body required ”object
The part before @ of the first address, e.g. info.
The inbox its mail is forwarded to.
Agree to replace the domain’s existing MX records.
Merge NSIN’s include into the domain’s existing SPF record.
Responses
Section titled “ Responses ”Routing is on; the status, the address and the destination.
object
object
Whether Email Routing is switched on for the domain.
unconfigured — not enabled. ready — enabled, and the zone
carries the MX, SPF and DKIM records mail needs. misconfigured —
enabled, but the last DNS check found a record missing or a
foreign one in the way (see dns). unlocked — the managed
records were unlocked for editing (POST .../email-routing/unlock).
suspended — forwarding is paused by NSIN (suspended_reason says
why).
At least one mail host has checked in recently. Enable is refused while false.
The managed records are not editable.
user+tag@ addresses are delivered to the user@ rule. Set with PUT .../email-routing/settings.
Why forwarding is suspended — over_cap when the plan’s daily forward allowance is used up, otherwise NSIN’s note. Empty when not suspended.
object
Whether the catch-all handles mail for addresses you have not created. Off, such mail is refused as an unknown user.
forward to the destination, or drop (accept and discard).
The destination for forward.
That destination’s address.
Whether the destination has confirmed its address.
The DNS records mail needs, and what the last check found.
object
When DNS was last checked; null before the first check.
Every required record was found and nothing conflicting was.
object
Record type.
Relative to the domain; @ is the apex.
The value the record must have.
MX priority.
TTL in seconds.
extra is a foreign MX or a second SPF seen publicly.
The managed record’s id, when the row is ours.
Human-readable findings of the last check.
Only while unconfigured — what enable would have to remove or merge.
object
object
object
Enable removed MX records that disable can restore.
object
Every message except discarded bounces.
Messages delivered to a destination.
Messages accepted and discarded by a drop rule or catch-all.
Messages refused.
Messages temporarily refused (the sender retries), for example over the daily forward cap.
Recipients that mail sent from this domain (the send endpoint) was delivered to. Present on the status counters only.
The plan’s Email Routing allowances and today’s use.
object
Custom addresses the plan allows on this domain. null means unlimited.
Custom addresses the domain holds now.
Messages the plan lets this domain forward per UTC day. null means unlimited.
Messages forwarded so far today (UTC).
Whether this domain may send mail right now, and how much of today’s allowance is used.
object
The plan includes sending (email_sending_enabled).
A send would be accepted now (limits aside).
Why not, when allowed is false: platform_off, plan, not_enabled or suspended. Empty otherwise.
Recipients the plan lets this domain send to per UTC day. null means unlimited.
Recipients queued so far today (UTC)
Recipients allowed in one message.
Largest message text
Longest subject
Always present. Before Email Routing is enabled the selector and name are already known (they come from platform settings) and txt is empty, because the key is generated at enable time.
object
The DKIM selector.
The TXT name relative to the domain.
The DKIM TXT value (v=DKIM1; …). Empty until enabled.
NSIN’s mail platform — what the domain’s records point at.
object
The MX targets published for the domain.
object
The name the domain’s SPF record must include:.
Domain the forwarded mail’s envelope sender is rewritten to (SRS).
object
The part before the @, lowercased.
The full address, local_part@domain.
forward delivers to the destination; drop accepts the mail and discards it.
The destination mail is forwarded to. null for drop.
That destination’s address.
Whether the destination has confirmed its address; unverified destinations receive nothing.
Your switch.
Whether the address is live right now — enabled, routing on for the
domain, and (for forward) the destination verified.
Optional label.
object
Whether the address was confirmed through the emailed link.
When it was confirmed.
When the last verification mail went out.
Seconds until another verification mail may be sent; 0 when allowed now.
Rules and catch-alls pointing at it.
The receiving server’s last refusal, when forwards to it are bouncing.
When last_failure was recorded.
Example
{ "status": { "status": "unconfigured", "catch_all": { "action": "forward" }, "dns": { "records": [ { "type": "MX", "state": "ok" } ] } }, "rule": { "action": "forward" }}Invalid local_part or destination_email (field names which), a destination domain with no mail server (code: no_mx), or a loop (code: loop).
object
Human-readable description of what went wrong.
Machine-readable reason (hosts_not_ready, kek_unset, loop, no_mx, unverified).
The offending body field, when one applies.
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.)
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "invalid API key"}The domain has no active plan. The body carries upgrade_url.
object
Human-readable description of what went wrong.
Examples
{ "error": "This domain does not have an active plan. Purchase a plan for this domain before adding email addresses.", "upgrade_url": "/plans"}The key is read-only, your role lacks the permission, the plan does not
include Email Routing (upgrade_url), or the plan’s max_email_rules
is reached — the body then carries max_rules and upgrade_url.
object
Human-readable description of what went wrong.
Examples
{ "error": "You have reached the maximum number of email addresses for this domain's plan. Upgrade the plan for this domain to add more.", "max_rules": 50, "upgrade_url": "/plans"}No such domain, or it is not visible to this account. Domains you cannot access are reported as not found rather than forbidden.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Example
{ "error": "read-only API key"}Something in the zone has to change first. conflict says what:
mx (existing MX records, listed under records — re-send with
remove_existing_mx: true), spf (an existing SPF record, with the
merged preview — re-send with merge_spf: true), spf_multiple
(two SPF records; keep one), external_dns (the domain does not use
NSIN DNS) or domain_status (the domain is disabled).
object
Human-readable description of what went wrong.
What conflicts (mx, spf, spf_multiple, external_dns, domain_status, not_enabled, local_part, destination).
For mx / spf_multiple — the rows in the way.
object
For spf — the existing SPF row.
For spf — its current value.
For spf — what it becomes with our include merged in.
For destination — the existing row.
object
Whether the address was confirmed through the emailed link.
When it was confirmed.
When the last verification mail went out.
Seconds until another verification mail may be sent; 0 when allowed now.
Rules and catch-alls pointing at it.
The receiving server’s last refusal, when forwards to it are bouncing.
When last_failure was recorded.
Examples
{ "error": "this domain already has MX records; enabling email routing replaces them", "conflict": "mx", "records": [ { "id": 12, "name": "@", "content": "mail.example.ir.", "priority": 10 } ]}The per-key rate limit, a verification mail to this destination less
than a minute ago (cooldownSecondsRemaining), or the account’s or
your address’s hourly send cap.
object
Human-readable description of what went wrong.
Example
{ "error": "read-only API key"}The nameservers could not be updated; nothing was changed. Retry in a moment.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Example
{ "error": "read-only API key"}No mail host has checked in recently (code: hosts_not_ready), or
the platform is missing its key-encryption key (code: kek_unset).
object
Human-readable description of what went wrong.
Machine-readable reason (hosts_not_ready, kek_unset, loop, no_mx, unverified).
The offending body field, when one applies.
Example
{ "error": "read-only API key"}