Skip to content

List invoices

GET
/invoices
curl --request GET \
--url https://api.nsin.cloud/invoices \
--header 'Authorization: Bearer <token>'

Scoped to your own user_id: an invoice is raised against the domain’s owner, so a domain shared with you contributes none of them here. Ordered by id descending — issue order — and paginated with limit (default 200, which is also the hard cap) and offset (default 0); an unparseable or out-of-range value falls back to the default instead of erroring. Line items come with every row and domain_name is resolved, except on top-up invoices, which have no domain at all. The kinds you can see are subscription (plan purchase or renewal), period (traffic overage for a closed billing period), topup (wallet credit, the one kind exempt from VAT) and manual (raised by support); the internal per-window traffic invoices are filtered out. Status is paid on everything the system issues — invoices are receipts written after the wallet has already been debited, with paid_at stamped — and cancelled appears only after support cancels one; no current code path issues an unpaid invoice.

Invoices, newest first.

Media type application/json
Array<object>
object
id
integer
number

Human-facing invoice number, sequential per Jalali year.

string
user_id
integer
domain_id
integer
domain_name
string
subscription_id
integer
payment_id
integer
kind
string
Allowed values: subscription topup manual
status
string
Allowed values: paid unpaid cancelled
subtotal_rials
integer
tax_rials
integer
total_rials
integer
issued_at
string format: date-time
paid_at
string format: date-time
notes
string
created_at
string format: date-time
updated_at
string format: date-time
items
Array<object>
object
id
integer
invoice_id
integer
description
string
quantity
integer
unit_price_rials
integer
total_rials
integer
Example
[
{
"kind": "subscription",
"status": "paid"
}
]

Missing, malformed, revoked or expired API key, or a key whose owning user row is gone. A key whose owning account has merely been deactivated is not this: that is 403 with code: account_suspended, because the credential itself is intact and re-issuing it changes nothing.

Media type application/json

The error shape used by every endpoint. error is always present. code is present only on the failures that have one — do not require it, and do not parse error to recover it.

object
error
required

Human-readable description of what went wrong.

string
code

Stable machine-readable reason. Present on some failures only; the wording of error may change, this will not.

  • account_suspended403. The account behind the credential has been switched off, by an admin or by its provider. Every authenticated route answers this, so treat it as terminal rather than retrying.
  • domain_disabled409, not 403. You have every right to the operation; the domain is simply switched off and is not being served, so its configuration cannot change. It stays readable, and writes work again once it is enabled.
  • managed_by_reseller403. The account is a reseller’s client and this surface belongs to its provider. See If your account is managed by a reseller.
  • invite_email_mismatch403 from POST /invites/{token}/accept. The invitation was addressed to a different email; the body also carries invited_email, masked.

A panel session — not an API key — can additionally see session_check_failed on a 503, which means the session could not be verified, not that it is invalid. Retry it; do not discard the token.

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

The key exceeded its request budget (300 requests per minute by default).

Media type application/json

The error shape used by every endpoint. error is always present. code is present only on the failures that have one — do not require it, and do not parse error to recover it.

object
error
required

Human-readable description of what went wrong.

string
code

Stable machine-readable reason. Present on some failures only; the wording of error may change, this will not.

  • account_suspended403. The account behind the credential has been switched off, by an admin or by its provider. Every authenticated route answers this, so treat it as terminal rather than retrying.
  • domain_disabled409, not 403. You have every right to the operation; the domain is simply switched off and is not being served, so its configuration cannot change. It stays readable, and writes work again once it is enabled.
  • managed_by_reseller403. The account is a reseller’s client and this surface belongs to its provider. See If your account is managed by a reseller.
  • invite_email_mismatch403 from POST /invites/{token}/accept. The invitation was addressed to a different email; the body also carries invited_email, masked.

A panel session — not an API key — can additionally see session_check_failed on a 503, which means the session could not be verified, not that it is invalid. Retry it; do not discard the token.

string
Examples
Example limited
{
"error": "rate limit exceeded"
}