Manage your API keys
An API key lets you interact with nullplatform programmatically and is ideal for automation and system tasks. For machine users like CI workflows, create API keys with specific roles to control access and permissions.
Keep in mind: API keys are sensitive, so handle them carefully to prevent unauthorized access.
You can create and manage API keys through the UI, CLI, or API.
How API keys fit into authorization
API keys act as machine users, and each API key has one or more grants.
Grants
Grants define the API key's access: where it applies and what the key may do there.
- Resource: The resource where permissions apply, for example account: main.
- Permissions: What the key may do at that resource. Usually one or more roles, for example Agent. You can also start from roles and adjust single permissions, or hand-pick them one by one as Custom permissions.
ℹ️ Note: You can add multiple grants, including several on the same resource.
Whichever way you define the permissions, each grant resolves to one set of actions the key may perform on that resource:
- Roles: the key holds exactly what the roles grant. The Role field lists them, for example Ops, Developer.
- Roles, adjusted by hand: you start from roles and tick or untick single permissions in Customize permissions.
- Hand-picked permissions: you tick the permissions one by one with no role selected. The Role field shows Custom.
You can only hand out what you could grant yourself on that resource: the permissions you hold there, plus the ones carried by roles you may assign to an API key.
For more details on grants and roles, see Roles and Grants and permissions.
Using the UI
Go to Platform settings > API keys and click Create API key. Walk through the form below:
The API key is displayed only once, right after you generate it. Copy it and store it in a secure location, as it cannot be retrieved later.
To edit or delete a key later, open its ⋮ menu in the list and click View or edit or Delete.
Using the CLI or API
Create an API key
Send a POST request to create an API key.
Here's an example request:
- CLI
- cURL
np api-key create \
--body '{
"name": "my-machine-process-that-will-access-nullplatform",
"grants": [
{
"nrn": "organization=1:account=2:namespace=3:application=4",
"role_slug": "admin" // Alternatively, use "role_id". For example: "696188987"
}
],
"tags": [
{
"key": "CI",
"value": "main"
}
]
}'
curl -L -X POST 'https://api.nullplatform.com/api_key' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"name": "my-machine-process-that-will-access-nullplatform",
"grants": [
{
"nrn": "organization=1:account=2:namespace=3:application=4",
"role_slug": "admin" // Alternatively, use "role_id". For example: "696188987"
}
],
"tags": [
{
"key": "CI",
"value": "main"
}
]
}'
Where:
grantsdefines the access permissions for the API key.nrnis where the API key's role is assigned.role_slugis the slug of the role assigned to the API key for the specified NRN. You can also provide therole_idinstead ofrole_slug.
Example response
You'll receive a 2XX response like this:
{
"id": "123",
"name": "my-machine-process-that-will-access-nullplatform",
"api_key": "AAAA.1234567890abcdef1234567890abcdefPTs=", // Your new API key.
"masked_api_key": "AAAA.xxxxxxxxxxxxxxxxxxxxxPTs=",
"tags": [
{
"key": "CI",
"value": "main"
}
],
"grants": [
{
"nrn": "organization=1:account=2:namespace=3:application=4",
"role_slug": "admin",
"role_id": 696188987
}
],
"owner_id": 1595,
"last_used_at": null,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
Where:
api_key is your newly created API key.
The API key is displayed only once. Make sure to store it in a secure location, as it cannot be retrieved later.
Grant access to API keys
In the UI, a grant is one row of the form: the resource, the roles, and whatever you changed in Customize permissions. Through the API, that same grant is an item of the grants field, in one of three shapes:
- Roles only:
role_slugorrole_id, one item per role. - Roles adjusted in Customize permissions:
inherits, plusactions.addandactions.remove. - Custom permissions, ticked with no role selected:
actions.
To grant a role, include the following in your request to create or update an API key:
nrnspecifies the resource where the API key's role will be assigned.role_slugis the slug of the role you want to assign to the API key for the specified NRN. You can also provide therole_idinstead ofrole_slug.
"grants": [
{
"nrn": "organization=1:account=2:namespace=3:application=4",
"role_slug": "admin" // Alternatively, use "role_id": "696188987"
}
]
In this example, the admin role is assigned to the NRN organization=1:account=2:namespace=3:application=4. This allows the API key to handle tasks like creating, modifying, and deleting applications and their scopes for the resource.
To grant several roles on the same resource, repeat the item:
"grants": [
{ "nrn": "organization=1:account=2", "role_slug": "ops" },
{ "nrn": "organization=1:account=2", "role_slug": "developer" }
]
Use role_id in every grant of a key, or role_slug in every grant, never one in some and the other in others. Every grant of a key is resolved the same way, so a mixed request fails.
Grant custom permissions
When no existing role is the right size, a grant can name actions directly, which is what the UI shows as Custom in the Role field. Instead of role_slug, list them in actions:
"grants": [
{
"nrn": "organization=1:account=2:namespace=3",
"actions": ["application:read", "deployment:create"]
}
]
This key can read applications and create deployments in that namespace, and nothing else. Nullplatform creates a role private to the key to hold those actions. You don't manage it, it never appears among your roles, and it's deleted with the key.
At a given resource, that's the actions you hold there plus the ones carried by roles you may assign to an API key there. To see that ceiling for an NRN, list your roles with include=actions.
Inherit existing roles and adjust them
A grant can also start from roles that already exist and change the result. Use inherits for the roles, then actions.add and actions.remove:
"grants": [
{
"nrn": "organization=1:account=2",
"inherits": ["ops", "developer"],
"actions": {
"add": ["application:delete"],
"remove": ["deployment:create"]
}
}
]
This key gets everything ops and developer grant, plus application:delete, minus deployment:create.
Listing two roles in one inherits is not the same as granting them as two items. Two items give the key two independent roles, and there's nothing to subtract from. One inherits produces a single role, and that role is what actions.remove acts on.
An inherited grant follows its roles. If one of them later gains an action, the key gains it too, unless it's in actions.remove. That's the difference from a literal actions list, which never changes on its own.
A few rules apply. You need to be allowed to assign each inherited role to an API key at that resource, the same check a grant by role_slug passes. What you add by hand is measured against what you can hand out there, while removing never is. actions.remove can only name actions the inherited roles carry, an action can't be in both lists, and the grant can't end up empty. You can inherit by role ID instead of slug, but a role private to another API key can't be inherited.
What the API returns for these grants
A grant you wrote with actions or inherits doesn't come back in the shape you sent. The response reports what the grant resolved to. This example is an inherited grant, which carries the most fields:
"grants": [
{
"nrn": "organization=1:account=2",
"role_id": 841203556,
"role_slug": "apikey:123:0",
"actions": ["application:read", "application:delete"],
"inherits": [
{ "id": 708509758, "slug": "ops", "organization_id": null },
{ "id": 700317756, "slug": "developer", "organization_id": null }
],
"added": ["application:delete"],
"removed": ["deployment:create"]
}
]
Where:
actionsis the effective set: everything the grant authorizes, after inheritance and removals.inheritsnames the roles that were merged.organization_idisnullfor a platform role, and your organization's ID for a role of your own or your override of a platform one.addedandremovedreport the adjustment you sent.role_idandrole_slugname the private role holding all this. It's an implementation detail: nullplatform recreates it whenever you replace the key's grants, so don't store it or reference it anywhere.
A grant you wrote with actions returns nrn, actions, role_id and role_slug only: there's nothing inherited to report, so inherits, added and removed are absent. A grant naming an existing role returns just nrn, role_id and role_slug.
Some actions have an alias, a second name they're exposed under. Such an action is listed by its alias, not by the name it's stored as.
Generate an access token
Use your new API key to create an access token, which allows you to authenticate and make API calls with nullplatform.
These instructions are for API keys and machine users. If you're a human user, check the Authorization article.
Send a POST request to get your token. You can use either:
- your API key, or
- your username and password
Here are examples:
- CLI
- cURL
curl -L -X POST 'https://api.nullplatform.com/token' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"api_key": "AAAA.1234567890abcdef1234567890abcdefPTs="
}'
np token create \
--body '{
"api_key": "AAAA.1234567890abcdef1234567890abcdefPTs="
}'
Instead of an API key, you can send the username, password, and organization ID. Like this:
{
"username": "alex.doe@email.com",
"password": "your_password",
"organization_id": "1234"
}
Response
You'll receive a 2XX response like this:
{
"refresh_token": "epJjdHky...", // A long-lived token used to obtain new access tokens.
"access_token": "epJraWQy...", // A short-lived bearer token for making API calls.
"organization_id": 123245, // The unique ID of the organization.
"token_expires_at": 1700000000000
}
Renew an access token
When your access token expires, you can make a POST request to create a new one. You'll need your refresh_token and organization_id for the request.
Example request:
- CLI
- cURL
np token create \
--body '{
"refresh_token": "epJjdHky...",
"organization_id": "123245"
}'
curl -L -X POST 'https://api.nullplatform.com/token' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"refresh_token": "epJjdHky...",
"organization_id": "123245"
}'
Example response:
{
"access_token": "eyJra3JQb...", // Your renewed access_token for making API calls.
"organization_id": 123245
}
Update your API key
To update an existing API key, send a PATCH request with the details you want to change. If you include grants, the list you send replaces the key's grants. Only what changes is measured against what you can hand out, so a grant you send back unchanged is kept even if it holds permissions you don't.
id for this request.To get the API key ID, send a GET request to list all the API keys.
Here's an example request to update the API key name and tags:
- CLI
- cURL
np api-key patch \
--id 123 \
--body '{
"name": "updated-machine-process",
"tags": [
{
"key": "CI",
"value": "updated"
}
]
}'
curl -L -X PATCH 'https://api.nullplatform.com/api_key/123' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"name": "updated-machine-process",
"tags": [
{
"key": "CI",
"value": "updated"
}
]
}'
Where:
id: The unique ID of the API key you want to update (e.g.,123).name: The updated name for the API key.tags: The updated tags for the API key.
Example response:
{
"id": "123",
"name": "updated-machine-process",
"masked_api_key": "AAAA.xxxxxxxxxxxxxxxxxxxxxPTs=",
"tags": [
{
"key": "CI",
"value": "updated"
}
],
"grants": [
{
"nrn": "organization=1:account=2:namespace=3:application=4",
"role_id": 696188987,
"role_slug": "admin"
}
],
"owner_id": 1595,
"last_used_at": "2025-01-10T00:00:00Z",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2025-01-10T00:00:00Z"
}
Where:
name: The updated name for the API key.tags: The updated tags for the API key.updated_at: The time when the API key was last updated.
Delete your API key
To permanently remove an API key, send a DELETE request.
id for this request.To get the API key ID, send a GET request to list all the API keys.
Here's an example request:
- CLI
- cURL
np api-key delete \
--id 123 \
--auth "Bearer {{access_token}}"
curl -L -X DELETE 'https://api.nullplatform.com/api_key/:id' \
-H 'Authorization: Bearer <token>'
You'll receive a 204 response, confirming your API key has been removed successfully.