Start a record import session
const url = 'https://api.nsin.ir/domains/example.com/records/import-sessions';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"source":"manual_scan"}'};
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/records/import-sessions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "source": "manual_scan" }'Scans the domain’s current nameservers — a zone transfer where they
allow one, otherwise a sweep of common names — into a staging session.
Nothing is written to the zone. Requires records.edit.
The scan runs in the background: the session comes back scanning with
an empty records list, and you poll
GET .../records/import-sessions/current until it turns ready.
Every staged row is proxied: false, apex and www included. Importing
never switches proxying on for you — turn it on per row in the commit
body once you have reviewed what was found.
Idempotent. If the domain already has an open session it comes back
with 200 and no new scan is started, so a double click or a retry
cannot start a second sweep.
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
Section titled “Request Body ”object
Recorded on the session so support can answer “where did
this import come from” months later. An unrecognised value
falls back to manual_scan.
Responses
Section titled “ Responses ”An open session already existed and is returned unchanged. No new scan was started.
One scan-and-review cycle for a domain — the envelope every import-session endpoint returns.
object
scanning — the sweep is running. ready — waiting for a commit or
a discard. committing — a commit is in flight and holds the claim.
auto_committed — nobody answered before auto_commit_at and the
records were written anyway, rather than leaving the zone empty.
superseded — replaced by a rescan.
What started the session. An API key has nowhere to show a review screen, so adding a domain with a key still imports automatically; staged review is the panel path.
Which branch found the records — a full zone transfer, or a resolver sweep of common names. The first support question about a bad import is where the records came from.
The nameservers this scan read. Stored because a rescan has to reuse them: once the domain is delegated to NSIN, resolving it again finds our own — still empty — zone.
Why the scan, or the last commit attempt, failed.
When the scan finished and the session turned ready.
When an unanswered ready session commits itself. Cleared by a
commit, a discard or a rescan.
The header line of a review screen.
object
Rows a mode "all" commit would write.
Rows carrying at least one warning.
Empty while status is scanning.
One record the scan found, with the verdict a reviewer needs.
object
Staging row id. It is not a record id — it exists only until the session is committed or discarded.
Whether this row would be proxied — and, because a mode: "all"
commit (the unattended auto_commit_at one included) writes exactly
this flag, what happens to the row if nobody answers.
It is true for the rows the edge can carry: a proxyable type on a
routable origin. It is false wherever proxying would take a
service away rather than accelerate it — a mail host, the target of
an in-zone MX, an underscored name (_acme-challenge,
selector1._domainkey), or a label that names something that does
not speak HTTP (ssh, vpn, mysql, ns1, …). Those rows carry a
mail_host or non_web_service warning saying so.
An overwrite row mirrors the record it would replace: an import
refreshes content and TTL and never changes an existing record’s
proxy setting.
overwrite means the domain already holds a record with this name
and type and it would be replaced. TXT is never overwrite: many
TXT records share one name.
The record that would be replaced. Set when status is overwrite.
Whether this row could be proxied if you switched it on — a proxyable type pointing at an address the edge will accept.
Whether the row is included when you commit with mode: "all".
Rows carrying an error warning arrive unticked.
One reviewer-facing note on a staged row. code is stable — branch on
it rather than on message, which is prose and may change.
object
Only error rows arrive unticked (preselected: false) — they are
the ones NSIN cannot import at all.
The first warning’s message, kept for clients written against the flat scan preview.
Example
{ "status": "scanning", "source": "manual_scan", "client": "panel", "method": "axfr", "records": [ { "type": "A", "status": "new", "warnings": [ { "code": "unsupported", "severity": "info" } ] } ]}A new session was created and its scan is running. status is
scanning and records stays empty until it finishes.
One scan-and-review cycle for a domain — the envelope every import-session endpoint returns.
object
scanning — the sweep is running. ready — waiting for a commit or
a discard. committing — a commit is in flight and holds the claim.
auto_committed — nobody answered before auto_commit_at and the
records were written anyway, rather than leaving the zone empty.
superseded — replaced by a rescan.
What started the session. An API key has nowhere to show a review screen, so adding a domain with a key still imports automatically; staged review is the panel path.
Which branch found the records — a full zone transfer, or a resolver sweep of common names. The first support question about a bad import is where the records came from.
The nameservers this scan read. Stored because a rescan has to reuse them: once the domain is delegated to NSIN, resolving it again finds our own — still empty — zone.
Why the scan, or the last commit attempt, failed.
When the scan finished and the session turned ready.
When an unanswered ready session commits itself. Cleared by a
commit, a discard or a rescan.
The header line of a review screen.
object
Rows a mode "all" commit would write.
Rows carrying at least one warning.
Empty while status is scanning.
One record the scan found, with the verdict a reviewer needs.
object
Staging row id. It is not a record id — it exists only until the session is committed or discarded.
Whether this row would be proxied — and, because a mode: "all"
commit (the unattended auto_commit_at one included) writes exactly
this flag, what happens to the row if nobody answers.
It is true for the rows the edge can carry: a proxyable type on a
routable origin. It is false wherever proxying would take a
service away rather than accelerate it — a mail host, the target of
an in-zone MX, an underscored name (_acme-challenge,
selector1._domainkey), or a label that names something that does
not speak HTTP (ssh, vpn, mysql, ns1, …). Those rows carry a
mail_host or non_web_service warning saying so.
An overwrite row mirrors the record it would replace: an import
refreshes content and TTL and never changes an existing record’s
proxy setting.
overwrite means the domain already holds a record with this name
and type and it would be replaced. TXT is never overwrite: many
TXT records share one name.
The record that would be replaced. Set when status is overwrite.
Whether this row could be proxied if you switched it on — a proxyable type pointing at an address the edge will accept.
Whether the row is included when you commit with mode: "all".
Rows carrying an error warning arrive unticked.
One reviewer-facing note on a staged row. code is stable — branch on
it rather than on message, which is prose and may change.
object
Only error rows arrive unticked (preselected: false) — they are
the ones NSIN cannot import at all.
The first warning’s message, kept for clients written against the flat scan preview.
Example
{ "status": "scanning", "source": "manual_scan", "client": "panel", "method": "axfr", "records": [ { "type": "A", "status": "new", "warnings": [ { "code": "unsupported", "severity": "info" } ] } ]}Missing, malformed, revoked or expired API key — or the owning account is inactive.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "invalid API key"}The key is read-only, your role on the domain lacks the required permission, or the domain’s plan does not include the feature.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
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.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Example
{ "error": "read-only API key"}The domain is disabled or banned.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "domain is disabled"}A scan for this domain ran less than five minutes ago. One scan is up to
roughly 1100 outbound DNS queries, so it is throttled per domain — this
is separate from, and additional to, the per-key rate limit. Wait
retry_after_seconds and retry.
object
Human-readable description of what went wrong.
Seconds left on this domain’s five-minute scan window.
Examples
{ "error": "a scan for this domain ran a moment ago; please wait before scanning again", "retry_after_seconds": 173}