Change a member's role or notifications
const url = 'https://api.nsin.cloud/domains/example.com/members/1';const options = { method: 'PATCH', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"role":"admin","notify_domain":true,"notify_uptime":true,"notify_ssl":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://api.nsin.cloud/domains/example.com/members/1 \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "role": "admin", "notify_domain": true, "notify_uptime": true, "notify_ssl": true }'Partial update. Changing role requires members.manage; a member may
change their own notification preferences without it.
The owner’s role cannot be changed, and the owner always receives every notification category.
One member is not editable here at all: the domain’s service provider,
which appears in the member list with role provider. That row is a
projection of the account the provider manages, not a grant someone
made, so a role change on it is refused with 409 and a reconciliation
pass would undo it anyway; its notification preferences may be changed
only by the provider himself, and anyone else gets 403.
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.comThe member’s user id, from the member list.
Request Body required
Section titled “Request Body required ”Partial patch — send only what you want to change. At least one field is required.
object
A role that may be assigned to a member or invitation. owner is not
grantable — it always follows domain ownership.
Responses
Section titled “ Responses ”The stored membership row — not the enriched shape that
GET /domains/{domain}/members returns. It carries id,
domain_id, user_id, role, the three notify_* flags,
invited_by, created_at and updated_at, and it does NOT carry
email, name, is_owner, is_self or joined_at. Re-list the
members if you need those.
The stored membership row, as written. This is what
PATCH /domains/{domain}/members/{userId} returns — the member LIST is
a different, enriched shape (Member), joined against the user account.
Nothing here identifies the user beyond user_id.
object
Membership row id
The stored role — admin, editor or viewer for a granted
member, or provider on the row that projects the domain’s service
provider. provider is not grantable and cannot be set here.
User who granted the access; 0 when unknown.
Example generated
{ "id": 1, "domain_id": 1, "user_id": 1, "role": "example", "notify_domain": true, "notify_uptime": true, "notify_ssl": true, "invited_by": 1, "created_at": "2026-04-15T12:00:00Z", "updated_at": "2026-04-15T12:00:00Z"}Invalid user id or body, nothing to update, an invalid role, or an attempt to change the owner’s role or notifications.
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
Human-readable description of what went wrong.
Stable machine-readable reason. Present on some failures only; the
wording of error may change, this will not.
account_suspended—403. 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_disabled—409, not403. 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_reseller—403. 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_mismatch—403fromPOST /invites/{token}/accept. The invitation was addressed to a different email; the body also carriesinvited_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.
Example
{ "error": "read-only API key"}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.
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
Human-readable description of what went wrong.
Stable machine-readable reason. Present on some failures only; the
wording of error may change, this will not.
account_suspended—403. 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_disabled—409, not403. 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_reseller—403. 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_mismatch—403fromPOST /invites/{token}/accept. The invitation was addressed to a different email; the body also carriesinvited_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.
Examples
{ "error": "invalid API key"}The key is read-only, your role on the domain lacks the required
permission, the domain’s plan does not include the feature, or the
account that owns the key has been deactivated — that last one carries
code: account_suspended and can arrive on any endpoint, including ones
that document no 403 of their own.
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
Human-readable description of what went wrong.
Stable machine-readable reason. Present on some failures only; the
wording of error may change, this will not.
account_suspended—403. 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_disabled—409, not403. 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_reseller—403. 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_mismatch—403fromPOST /invites/{token}/accept. The invitation was addressed to a different email; the body also carriesinvited_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.
Example
{ "error": "read-only API key"}Domain or member not found.
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
Human-readable description of what went wrong.
Stable machine-readable reason. Present on some failures only; the
wording of error may change, this will not.
account_suspended—403. 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_disabled—409, not403. 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_reseller—403. 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_mismatch—403fromPOST /invites/{token}/accept. The invitation was addressed to a different email; the body also carriesinvited_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.
Example
{ "error": "read-only API key"}The target is the domain’s service provider and the body changes
role. Provider access follows the managed account, not a
membership, so it cannot be re-roled from here.
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
Human-readable description of what went wrong.
Stable machine-readable reason. Present on some failures only; the
wording of error may change, this will not.
account_suspended—403. 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_disabled—409, not403. 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_reseller—403. 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_mismatch—403fromPOST /invites/{token}/accept. The invitation was addressed to a different email; the body also carriesinvited_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.
Example
{ "error": "read-only API key"}The key exceeded its request budget (300 requests per minute by default).
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
Human-readable description of what went wrong.
Stable machine-readable reason. Present on some failures only; the
wording of error may change, this will not.
account_suspended—403. 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_disabled—409, not403. 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_reseller—403. 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_mismatch—403fromPOST /invites/{token}/accept. The invitation was addressed to a different email; the body also carriesinvited_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.
Examples
{ "error": "rate limit exceeded"}