Account Keys

Account keys

An account key is an API key that belongs to the account, not to a person. It starts with nak_. Use one for CI and other automation: it keeps working when the person who created it leaves the account.

  • One account. The key works only in the account it was created in. It never switches accounts.
  • One role. It can do exactly what the role picked at creation allows (see Roles).
  • Shown once. You see the key when you create it, and never again.

Manage them under Account → Account keys (/account/keys). The page needs your role's Members read permission.

Account key or API key?

Account key API key
Starts withnak_ngk_
Belongs toThe accountYou
Acts inIts own account onlyYour active account, in any of your accounts
Can doWhat its role allowsWhat your role allows
When its creator leaves the accountKeeps workingNo longer reaches that account
Created underAccount → Account keysUser settings → API keys

Creating a key

The account owner can create keys, and so can members whose role has the Members write permission. A member can give a key only a role within their own permissions; the owner can give any role.

  1. Open Account → Account keys and click New account key, or pick Create → Account key in the top bar.
  2. Name it after what uses it, for example GitHub Actions deploy (up to 100 characters).
  3. Pick its Role. No suitable role? Create one under Account → Roles first.
  4. Choose when it Expires and, if you want, the Allowed IPs (see Expiry and allowed IPs).
  5. Click Create key, then Copy the key and store it, for example as a CI secret. The dialog stays open until you click Done; after that the key can't be shown again.

With the API, call POST /v1/account/keys from a dashboard session or with your own API key (ngk_). An account key can't create keys, and neither can an OAuth session such as the MCP server's browser sign-in.

Create a key with the API
curl -X POST "https://api.ngris.com/v1/account/keys" \
  -H "X-API-KEY: $NGRIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "GitHub Actions deploy",
    "role_uuid": "019a3f4c-77ab-7e10-b2d4-6c1e9f0a8d23",
    "expires_in_days": 90
  }'
Response — 201 Created
{
  "account_key": {
    "uuid": "019a4e2f-6c1d-7b3a-9e52-3f8d1c7a2b40",
    "name": "GitHub Actions deploy",
    "role": {
      "uuid": "019a3f4c-77ab-7e10-b2d4-6c1e9f0a8d23",
      "name": "CI deploy"
    },
    "hint": "nak_…7Qx2",
    "created_at": "2026-11-02T14:58:40Z",
    "created_by": {
      "uuid": "019a52c2-ca1e-78ba-ab5c-50362cc29134",
      "name": "Maria Example"
    },
    "last_used_at": null,
    "expires_at": "2027-01-31T14:58:40Z",
    "allowed_ips": "",
    "status": "active"
  },
  "key": "nak_XmCJcYSSlOAdprvxObx4WpVthF2O6Ov1h0oL7Qx2",
  "notice": "Copy this key now. It won't be shown again."
}

Roles

A key does what its role allows, and nothing more. It uses the account's roles, the same ones members hold (see Named-role RBAC).

  • Deploying from CI (the GitHub Action, ngris deploy) needs a role with Endpoints read and write: apps and their deploys use the Endpoints permission.
  • Editing the role changes what the key can do from its next request.
  • A role a key uses can't be deleted. Revoke the key first.
  • A key keeps its role. To give it another one, create a new key with that role, then revoke the old key.
  • Custom roles follow the plan: a key gets a custom role only while the plan includes custom roles, and a key on a custom role has no permissions while it doesn't. Keys on the built-in Admin role aren't affected.

Expiry and allowed IPs

Expiry. In the dashboard a new key expires in 90 days unless you pick Never, In 30 days, In 1 year or On a date… (up to 10 years ahead). With the API, send expires_in_days (1–3650) or expires_at; a key created without either never expires.

An expired key stops working: every request with it answers 401. It stays in the list as Expired until you revoke it, and it no longer counts toward the account's keys.

Allowed IPs. Optional: IPv4 or IPv6 addresses and CIDR ranges, separated by commas or new lines. A request from any other address answers 401. Leave it empty to allow any address.

Both are set when the key is created. To change them, create a new key, then revoke the old one.

A key for one CI network, for a year
curl -X POST "https://api.ngris.com/v1/account/keys" \
  -H "X-API-KEY: $NGRIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Release pipeline",
    "role_uuid": "019a3f4c-77ab-7e10-b2d4-6c1e9f0a8d23",
    "expires_in_days": 365,
    "allowed_ips": "203.0.113.10, 198.51.100.0/24"
  }'
An expired key, or another address — 401 Unauthorized
$ curl "https://api.ngris.com/v1/endpoints" -H "X-API-KEY: $NGRIS_API_KEY"
Invalid API Key

Using a key

Every request made with an account key acts in the key's account.

  • REST API: send the key in the X-API-KEY header.
  • GitHub Actions: store it as the NGRIS_API_KEY repository secret for ngris-edge/deploy-action.
  • CLI: the app commands (ngris deploy, ngris apps, ngris env) take it with --token or the API_TOKEN environment variable (see Application hosting commands).
  • MCP server: send it as the bearer token (see Authentication: OAuth or API key).
  • Tunnels (ngris http, tcp, udp) log in with an agent token, not with an account key.
REST API
curl "https://api.ngris.com/v1/applications" \
  -H "X-API-KEY: $NGRIS_API_KEY"
.github/workflows/ngris.yml
      - uses: ngris-edge/deploy-action@v1
        with:
          # the account key (nak_…), a repository secret
          api-key: ${{ secrets.NGRIS_API_KEY }}
          build-command: npm ci && npm run build
          dir: dist
CLI in a CI job
# The account key from the CI secret store
export API_TOKEN="$NGRIS_API_KEY"
ngris deploy ./dist --app <app_uuid>

What stays with people

Whatever its role allows, an account key can't:

  • use anything personal: a user's profile, email settings, sessions, two-factor sign-in, invitations, the accounts list or switching accounts;
  • open billing: the subscription, invoices, payment methods and coupons, reads included;
  • create, list or revoke credentials: API keys, agent tokens, agent keys or account keys, itself included (endpoint API keys are endpoint settings and follow the key's role);
  • manage who has access: invite, remove or re-role members, revoke invitations, create, edit or delete roles, view or change single sign-on (SSO), upload KYC documents or change Iris autonomy settings;
  • delete or leave the account, or transfer its ownership;
  • link or unlink a GitHub identity or a GitHub App installation;
  • sign in to the dashboard or open support tickets.

These requests answer 403 with the code account_key_not_allowed. Reading the members, invitations and roles works when the key's role allows it.

With the matching role, a key can request, attach and release dedicated IPs, and it can read the account's verification status and the list of requested KYC documents.

Billing with an account key
curl "https://api.ngris.com/v1/billing/subscription" \
  -H "X-API-KEY: $NGRIS_API_KEY"
Error — 403 Forbidden
{
  "code": "account_key_not_allowed",
  "error": "Account keys can't use this endpoint."
}

Revoking a key

On Account → Account keys, open the key's … menu, choose Revoke and type REVOKE to confirm. Anything using the key stops working at once: its next request answers 401.

Anyone whose role has the Members delete permission can revoke any key, whoever created it. A revoked key leaves the list and can't be restored; the audit log keeps its name.

With the API: DELETE /v1/account/keys/{uuid}.

Revoke with the API — 204 No Content
curl -X DELETE "https://api.ngris.com/v1/account/keys/019a4e2f-6c1d-7b3a-9e52-3f8d1c7a2b40" \
  -H "X-API-KEY: $NGRIS_API_KEY"

How many keys

The account's plan sets whether it can have account keys and how many can be active at once. Revoked and expired keys don't count. When the account has as many as the plan allows, New account key is turned off until you revoke a key or upgrade.

If the plan later allows fewer keys than the account has, the newest keys over the count are paused once the grace period ends; if the plan no longer includes account keys, all of them are. A paused key answers 403 with the code account_key_paused. It works again on its own as soon as the account has room: revoke another key, or upgrade. The account owner gets an email when keys are paused and when they resume.

A paused key — 403 Forbidden
{
  "code": "account_key_paused",
  "error": "This account key is paused: the account has more account keys than its plan allows. Revoke a key or upgrade the plan."
}

In the audit log

What a key changes is recorded in the account's audit log under the key's name, with the member who created it: account key GitHub Actions deploy · created by maria@example.com. Once that member's user is deleted, the row reads created by a former member.

Creating and revoking a key are recorded under the person who did it, with the type Account key.

Was this helpful?