Authorization service#

Authorization service manages the permissions for a user to access resources.

OpenAPI file: AuthorizationService.json

Endpoints#

Authorize#

POST /authorization/v1/authorize

Given a set of resources, returns the set of resources that the user is authorized to access.

Body

rids array of string (RID)

​

Response

The body is an array of string (RID).

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/authorize" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "rids": [
    "<rids>"
  ]
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/authorize",
    headers={"Authorization": "Bearer <api key>"},
    json={"rids": ["<rids>"]},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/authorize",
    headers={"Authorization": "Bearer <api key>"},
    json={"rids": ["<rids>"]},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/authorize",
            headers={"Authorization": "Bearer <api key>"},
            json={"rids": ["<rids>"]},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

[
  "string"
]

Batch get workspace for resource#

POST /authorization/v1/batch-get-workspace-for-resource

Given a set of resources, returns the workspace that each resource belongs to. Omits any resource the caller cannot view: notebooks, runs, assets and data sources need their own view action, and every other resource needs workspace:view on its workspace. A returned entry is not authorization to change the resource. New callers should read the workspace from the resource’s own record instead; this endpoint is slated for deprecation.

Body

The body is an array of string (RID).

Response

The body is a map of string to string (RID).

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/batch-get-workspace-for-resource" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '[
  "string"
]'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/batch-get-workspace-for-resource",
    headers={"Authorization": "Bearer <api key>"},
    json=["string"],
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/batch-get-workspace-for-resource",
    headers={"Authorization": "Bearer <api key>"},
    json=["string"],
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/batch-get-workspace-for-resource",
            headers={"Authorization": "Bearer <api key>"},
            json=["string"],
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "<key>": "<workspace rid>"
}

Register in workspace#

POST /authorization/v1/register-in-workspace

Marks a set of resources as belonging to a workspace. Either all resources are registered or none are. If the user is not in the workspace, this will throw. If a resource already belongs to a different workspace, this will throw. If a resource already belongs to this workspace, this is a no-op.

Body

resourceRids array of string (RID)

​

workspaceRid string (RID) required

​

Response

No content (HTTP 204).

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/register-in-workspace" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "workspaceRid": "<workspace rid>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/register-in-workspace",
    headers={"Authorization": "Bearer <api key>"},
    json={"workspaceRid": "<workspace rid>"},
)
response.raise_for_status()
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/register-in-workspace",
    headers={"Authorization": "Bearer <api key>"},
    json={"workspaceRid": "<workspace rid>"},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/register-in-workspace",
            headers={"Authorization": "Bearer <api key>"},
            json={"workspaceRid": "<workspace rid>"},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Check admin#

GET /authorization/v1/checkAdmin

Given an authenticated session, this endpoint returns a HTTP 204 if the authenticated user is an admin and HTTP 403 otherwise.

Request

No parameters and no body.

Response

No content (HTTP 204).

Request

curl "https://api.gov.nominal.io/api/authorization/v1/checkAdmin" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/authorization/v1/checkAdmin",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/authorization/v1/checkAdmin",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/authorization/v1/checkAdmin",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Get user orgs#

POST /authorization/v1/user-orgs

Provides an OIDC ID token to get the orgs that the user is a member of. Throws NotAuthorized if the ID token is invalid or if the OIDC provider is not known.

No API key needed.

Body

idToken string required

​

accessToken string

​

Response

orgs map of string to string

The configured name of each organization the user belongs to, keyed by organization UUID.

orgDisplayNames map of string to string

The display name of each organization in orgs that has one, keyed by organization UUID. An organization without a display name is absent; show its name from orgs instead.

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/user-orgs" \
  -H "Content-Type: application/json" \
  --data '{
  "idToken": "<id token>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/user-orgs",
    json={"idToken": "<id token>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/user-orgs",
    json={"idToken": "<id token>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/user-orgs",
            json={"idToken": "<id token>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "orgs": {
    "<key>": "<value>"
  },
  "orgDisplayNames": {
    "<key>": "<value>"
  }
}

Set user org#

POST /authorization/v1/set-user-org

Switch the authenticated session to the provided org rid. Throws NotAuthorized if the session is invalid or the user is not a member of the org.

Body

orgRid string (RID) required

​

Response

accessToken string

​

expiresAtSeconds integer (int64)

​

userUuid string (UUID)

​

orgUuid string (UUID)

​

isGuest boolean

True if the user reaches the token’s org as a guest rather than a member. Populated by all endpoints; optional for version compatibility.

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/set-user-org" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "orgRid": "<org rid>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/set-user-org",
    headers={"Authorization": "Bearer <api key>"},
    json={"orgRid": "<org rid>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/set-user-org",
    headers={"Authorization": "Bearer <api key>"},
    json={"orgRid": "<org rid>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/set-user-org",
            headers={"Authorization": "Bearer <api key>"},
            json={"orgRid": "<org rid>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "accessToken": "<access token>",
  "expiresAtSeconds": 1,
  "userUuid": "<user uuid>",
  "orgUuid": "<org uuid>",
  "isGuest": true
}

Get access token#

POST /authorization/v1/access-token

Provide an OIDC ID token to get a (24h) Nominal access token suitable for making API requests.

No API key needed.

Body

idToken string required

​

accessToken string

​

orgRid string (RID)

​

workspaceRid string (RID)

​

Response

accessToken string

​

expiresAtSeconds integer (int64)

​

userUuid string (UUID)

​

orgUuid string (UUID)

​

isGuest boolean

True if the user reaches the token’s org as a guest rather than a member. Populated by all endpoints; optional for version compatibility.

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/access-token" \
  -H "Content-Type: application/json" \
  --data '{
  "idToken": "<id token>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/access-token",
    json={"idToken": "<id token>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/access-token",
    json={"idToken": "<id token>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/access-token",
            json={"idToken": "<id token>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "accessToken": "<access token>",
  "expiresAtSeconds": 1,
  "userUuid": "<user uuid>",
  "orgUuid": "<org uuid>",
  "isGuest": true
}

Refresh access token#

POST /authorization/v1/refresh-access-token

Given an authenticated session, provide an OIDC access token to get a Nominal access token suitable for making API requests. Its expiry will match that of the input access token, capped at 24h. Throws NotAuthorized if the access token is invalid or if the OIDC provider is not known.

No API key needed.

Body

accessToken string required

​

orgRid string (RID)

​

Response

accessToken string

​

expiresAtSeconds integer (int64)

​

userUuid string (UUID)

​

orgUuid string (UUID)

​

isGuest boolean

True if the user reaches the token’s org as a guest rather than a member. Populated by all endpoints; optional for version compatibility.

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/refresh-access-token" \
  -H "Content-Type: application/json" \
  --data '{
  "accessToken": "<access token>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/refresh-access-token",
    json={"accessToken": "<access token>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/refresh-access-token",
    json={"accessToken": "<access token>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/refresh-access-token",
            json={"accessToken": "<access token>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "accessToken": "<access token>",
  "expiresAtSeconds": 1,
  "userUuid": "<user uuid>",
  "orgUuid": "<org uuid>",
  "isGuest": true
}

Get idp end session endpoint#

POST /authorization/v1/get-idp-end-session-endpoint

Given an IDP issued id token, return the end session endpoint, accessed through the .well-known/openid-configuration endpoint.

No API key needed.

Body

idToken string required

​

Response

endSessionEndpoint string

​

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/get-idp-end-session-endpoint" \
  -H "Content-Type: application/json" \
  --data '{
  "idToken": "<id token>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/get-idp-end-session-endpoint",
    json={"idToken": "<id token>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/get-idp-end-session-endpoint",
    json={"idToken": "<id token>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/get-idp-end-session-endpoint",
            json={"idToken": "<id token>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "endSessionEndpoint": "<end session endpoint>"
}

Create API key#

POST /authorization/v1/api-key

Provide a long-lived API key for making API requests. The API key is irretrievable after initial creation.

Body

apiKeyName string required

The name of the API key to create.

expiresAfterDays integer (int64)

The number of days after which the API key will expire. If omitted, the API key will not expire.

Response

apiKeyMetadata ApiKey

​

Fields of ApiKey
rid string (RID)

​

apiKeyName string

​

createdBy string (RID)

​

createdAt string (date-time)

​

expiresAt string (date-time)

​

isDeleted boolean

​

apiKeyValue string

​

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/api-key" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "apiKeyName": "<api key name>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/api-key",
    headers={"Authorization": "Bearer <api key>"},
    json={"apiKeyName": "<api key name>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/api-key",
    headers={"Authorization": "Bearer <api key>"},
    json={"apiKeyName": "<api key name>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/api-key",
            headers={"Authorization": "Bearer <api key>"},
            json={"apiKeyName": "<api key name>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "apiKeyMetadata": {
    "rid": "<api key rid>",
    "apiKeyName": "<api key name>",
    "createdBy": "<created by>",
    "createdAt": "2026-01-01T00:00:00Z",
    "expiresAt": "2026-01-01T00:00:00Z",
    "isDeleted": true
  },
  "apiKeyValue": "<api key value>"
}

List API keys in org#

POST /authorization/v1/api-keys/org

List API keys in the organization. Org admins see all keys in the organization; other members see only keys they created.

Body

includeDeleted boolean

If true, include deleted API keys in the response. Defaults to false.

includeExpired boolean

If true, include expired API keys in the response. Defaults to false.

pageSize integer

The maximum number of API keys to return. Defaults to 100.

nextPageToken string

​

Response

apiKeys array of ApiKey

​

Fields of ApiKey
rid string (RID)

​

apiKeyName string

​

createdBy string (RID)

​

createdAt string (date-time)

​

expiresAt string (date-time)

​

isDeleted boolean

​

nextPageToken string

​

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/api-keys/org" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "includeDeleted": true,
  "includeExpired": true,
  "pageSize": 1,
  "nextPageToken": "<token>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/api-keys/org",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "includeDeleted": True,
        "includeExpired": True,
        "pageSize": 1,
        "nextPageToken": "<token>",
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/api-keys/org",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "includeDeleted": True,
        "includeExpired": True,
        "pageSize": 1,
        "nextPageToken": "<token>",
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/api-keys/org",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "includeDeleted": True,
                "includeExpired": True,
                "pageSize": 1,
                "nextPageToken": "<token>",
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "apiKeys": [
    {
      "rid": "<api key rid>",
      "apiKeyName": "<api key name>",
      "createdBy": "<created by>",
      "createdAt": "2026-01-01T00:00:00Z",
      "expiresAt": "2026-01-01T00:00:00Z",
      "isDeleted": true
    }
  ],
  "nextPageToken": "<token>"
}

List user API keys#

POST /authorization/v1/api-keys/user

List all API keys for the user.

Body

includeDeleted boolean

If true, include deleted API keys in the response. Defaults to false.

includeExpired boolean

If true, include expired API keys in the response. Defaults to false.

pageSize integer

The maximum number of API keys to return. Defaults to 100.

nextPageToken string

​

Response

apiKeys array of ApiKey

​

Fields of ApiKey
rid string (RID)

​

apiKeyName string

​

createdBy string (RID)

​

createdAt string (date-time)

​

expiresAt string (date-time)

​

isDeleted boolean

​

nextPageToken string

​

Request

curl -X POST "https://api.gov.nominal.io/api/authorization/v1/api-keys/user" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "includeDeleted": true,
  "includeExpired": true,
  "pageSize": 1,
  "nextPageToken": "<token>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/authorization/v1/api-keys/user",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "includeDeleted": True,
        "includeExpired": True,
        "pageSize": 1,
        "nextPageToken": "<token>",
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/authorization/v1/api-keys/user",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "includeDeleted": True,
        "includeExpired": True,
        "pageSize": 1,
        "nextPageToken": "<token>",
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/authorization/v1/api-keys/user",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "includeDeleted": True,
                "includeExpired": True,
                "pageSize": 1,
                "nextPageToken": "<token>",
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "apiKeys": [
    {
      "rid": "<api key rid>",
      "apiKeyName": "<api key name>",
      "createdBy": "<created by>",
      "createdAt": "2026-01-01T00:00:00Z",
      "expiresAt": "2026-01-01T00:00:00Z",
      "isDeleted": true
    }
  ],
  "nextPageToken": "<token>"
}

Revoke API key#

PUT /authorization/v1/api-key/{rid}/delete

Delete an API key. The caller may always revoke a key they created; revoking another user’s key requires the caller to be an org admin of the session org. A non-admin caller revoking another user’s key receives NotAuthorizedAdmin. A key in a different org than the session, or an unknown key, yields ApiKeyNotFound.

Path parameters

rid string (RID) required

​

Response

No content (HTTP 204).

Request

curl -X PUT "https://api.gov.nominal.io/api/authorization/v1/api-key/<rid>/delete" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/authorization/v1/api-key/<rid>/delete",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/authorization/v1/api-key/<rid>/delete",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/authorization/v1/api-key/<rid>/delete",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Errors#

Errors shows how these errors are sent.

Each error’s errorName is Authorization: followed by its name below.

Status

Name

Notes

400

MissingClaims

403

InvalidJwtAudience

403

InvalidJwtExpired

403

InvalidJwtFormat

403

InvalidJwtIssuer

403

NoMembership

403

NotAuthorized

403

NotAuthorizedAdmin

404

ApiKeyNotFound

404

WorkspaceNotFound

409

RegisterResourceConflict

The resource has already been registered with a different workspace.

Types#

ApiKey#

rid string (RID) required

​

apiKeyName string required

​

createdBy string (RID) required

​

createdAt string (date-time) required

​

expiresAt string (date-time)

​

isDeleted boolean required

​

Page design based on Scalar, MIT License.