{
  "swagger": "2.0",
  "info": {
    "title": "Authorization service",
    "version": "0.1507.0",
    "description": "Send your API key as a bearer token: `Authorization: Bearer <api key>`."
  },
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "securityDefinitions": {
    "ApiKey": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization",
      "description": "Your API key as a bearer token: `Authorization: Bearer <api key>`."
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/authorization/v1/authorize": {
      "post": {
        "operationId": "AuthorizationService_authorize",
        "summary": "Authorize",
        "tags": [
          "Authorization Service"
        ],
        "description": "Given a set of resources, returns the set of resources that the user is authorized to access.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/AuthorizationRequest"
            },
            "required": true,
            "x-example": {
              "rids": [
                "<rids>"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "rid"
              },
              "uniqueItems": true
            },
            "x-example": [
              "string"
            ]
          }
        }
      }
    },
    "/authorization/v1/batch-get-workspace-for-resource": {
      "post": {
        "operationId": "AuthorizationService_batchGetWorkspaceForResource",
        "summary": "Batch get workspace for resource",
        "tags": [
          "Authorization Service"
        ],
        "description": "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.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "rid"
              },
              "uniqueItems": true,
              "example": [
                "string"
              ]
            },
            "required": false,
            "x-example": [
              "string"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "string",
                "format": "rid",
                "x-alias": "WorkspaceRid"
              }
            },
            "x-example": {
              "<key>": "<workspace rid>"
            }
          }
        }
      }
    },
    "/authorization/v1/register-in-workspace": {
      "post": {
        "operationId": "AuthorizationService_registerInWorkspace",
        "summary": "Register in workspace",
        "tags": [
          "Authorization Service"
        ],
        "description": "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.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/RegisterInWorkspaceRequest"
            },
            "required": true,
            "x-example": {
              "workspaceRid": "<workspace rid>"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/authorization/v1/checkAdmin": {
      "get": {
        "operationId": "AuthorizationService_checkAdmin",
        "summary": "Check admin",
        "tags": [
          "Authorization Service"
        ],
        "description": "Given an authenticated session, this endpoint returns a HTTP 204 if the authenticated user is an admin and HTTP 403 otherwise.",
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    },
    "/authorization/v1/user-orgs": {
      "post": {
        "operationId": "AuthorizationService_getUserOrgs",
        "summary": "Get user orgs",
        "tags": [
          "Authorization Service"
        ],
        "description": "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.",
        "security": [],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/GetUserOrgsRequest"
            },
            "required": true,
            "x-example": {
              "idToken": "<id token>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/GetUserOrgsResponse"
            },
            "x-example": {
              "orgs": {
                "<key>": "<value>"
              },
              "orgDisplayNames": {
                "<key>": "<value>"
              }
            }
          }
        }
      }
    },
    "/authorization/v1/set-user-org": {
      "post": {
        "operationId": "AuthorizationService_setUserOrg",
        "summary": "Set user org",
        "tags": [
          "Authorization Service"
        ],
        "description": "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.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/SetUserOrgRequest"
            },
            "required": true,
            "x-example": {
              "orgRid": "<org rid>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/GetAccessTokenResponse"
            },
            "x-example": {
              "accessToken": "<access token>",
              "expiresAtSeconds": 1,
              "userUuid": "<user uuid>",
              "orgUuid": "<org uuid>",
              "isGuest": true
            }
          }
        }
      }
    },
    "/authorization/v1/access-token": {
      "post": {
        "operationId": "AuthorizationService_getAccessToken",
        "summary": "Get access token",
        "tags": [
          "Authorization Service"
        ],
        "description": "Provide an OIDC ID token to get a (24h) Nominal access token suitable for making API requests.",
        "security": [],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/GetAccessTokenRequest"
            },
            "required": true,
            "x-example": {
              "idToken": "<id token>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/GetAccessTokenResponse"
            },
            "x-example": {
              "accessToken": "<access token>",
              "expiresAtSeconds": 1,
              "userUuid": "<user uuid>",
              "orgUuid": "<org uuid>",
              "isGuest": true
            }
          }
        }
      }
    },
    "/authorization/v1/refresh-access-token": {
      "post": {
        "operationId": "AuthorizationService_refreshAccessToken",
        "summary": "Refresh access token",
        "tags": [
          "Authorization Service"
        ],
        "description": "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.",
        "security": [],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/RefreshAccessTokenRequest"
            },
            "required": true,
            "x-example": {
              "accessToken": "<access token>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/RefreshAccessTokenResponse"
            },
            "x-example": {
              "accessToken": "<access token>",
              "expiresAtSeconds": 1,
              "userUuid": "<user uuid>",
              "orgUuid": "<org uuid>",
              "isGuest": true
            }
          }
        }
      }
    },
    "/authorization/v1/get-idp-end-session-endpoint": {
      "post": {
        "operationId": "AuthorizationService_getIdpEndSessionEndpoint",
        "summary": "Get idp end session endpoint",
        "tags": [
          "Authorization Service"
        ],
        "description": "Given an IDP issued id token, return the end session endpoint, accessed through the .well-known/openid-configuration endpoint.",
        "security": [],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/GetIdpEndSessionEndpointRequest"
            },
            "required": true,
            "x-example": {
              "idToken": "<id token>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/GetIdpEndSessionEndpointResponse"
            },
            "x-example": {
              "endSessionEndpoint": "<end session endpoint>"
            }
          }
        }
      }
    },
    "/authorization/v1/api-key": {
      "post": {
        "operationId": "AuthorizationService_createApiKey",
        "summary": "Create API key",
        "tags": [
          "Authorization Service"
        ],
        "description": "Provide a long-lived API key for making API requests. The API key is irretrievable after initial creation.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/CreateApiKeyRequest"
            },
            "required": true,
            "x-example": {
              "apiKeyName": "<api key name>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/CreateApiKeyResponse"
            },
            "x-example": {
              "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>"
            }
          }
        }
      }
    },
    "/authorization/v1/api-keys/org": {
      "post": {
        "operationId": "AuthorizationService_listApiKeysInOrg",
        "summary": "List API keys in org",
        "tags": [
          "Authorization Service"
        ],
        "description": "List API keys in the organization. Org admins see all keys in the organization; other members see only keys they created.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/ListApiKeyRequest"
            },
            "required": true,
            "x-example": {
              "includeDeleted": true,
              "includeExpired": true,
              "pageSize": 1,
              "nextPageToken": "<token>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/ListApiKeyResponse"
            },
            "x-example": {
              "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>"
            }
          }
        }
      }
    },
    "/authorization/v1/api-keys/user": {
      "post": {
        "operationId": "AuthorizationService_listUserApiKeys",
        "summary": "List user API keys",
        "tags": [
          "Authorization Service"
        ],
        "description": "List all API keys for the user.",
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/ListApiKeyRequest"
            },
            "required": true,
            "x-example": {
              "includeDeleted": true,
              "includeExpired": true,
              "pageSize": 1,
              "nextPageToken": "<token>"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/ListApiKeyResponse"
            },
            "x-example": {
              "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>"
            }
          }
        }
      }
    },
    "/authorization/v1/api-key/{rid}/delete": {
      "put": {
        "operationId": "AuthorizationService_revokeApiKey",
        "summary": "Revoke API key",
        "tags": [
          "Authorization Service"
        ],
        "description": "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.",
        "parameters": [
          {
            "name": "rid",
            "in": "path",
            "type": "string",
            "format": "rid",
            "x-alias": "ApiKeyRid",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          }
        }
      }
    }
  },
  "definitions": {
    "ApiKey": {
      "type": "object",
      "properties": {
        "rid": {
          "type": "string",
          "format": "rid",
          "x-alias": "ApiKeyRid"
        },
        "apiKeyName": {
          "type": "string"
        },
        "createdBy": {
          "type": "string",
          "format": "rid"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "expiresAt": {
          "type": "string",
          "format": "date-time"
        },
        "isDeleted": {
          "type": "boolean"
        }
      },
      "required": [
        "rid",
        "apiKeyName",
        "createdBy",
        "createdAt",
        "isDeleted"
      ]
    },
    "AuthorizationRequest": {
      "type": "object",
      "properties": {
        "rids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "rid"
          },
          "uniqueItems": true
        }
      },
      "example": {
        "rids": [
          "<rids>"
        ]
      }
    },
    "CreateApiKeyRequest": {
      "type": "object",
      "properties": {
        "apiKeyName": {
          "type": "string",
          "description": "The name of the API key to create."
        },
        "expiresAfterDays": {
          "type": "integer",
          "format": "int64",
          "description": "The number of days after which the API key will expire. If omitted, the API key will not expire."
        }
      },
      "required": [
        "apiKeyName"
      ],
      "example": {
        "apiKeyName": "<api key name>"
      }
    },
    "CreateApiKeyResponse": {
      "type": "object",
      "properties": {
        "apiKeyMetadata": {
          "$ref": "#/definitions/ApiKey"
        },
        "apiKeyValue": {
          "type": "string"
        }
      },
      "required": [
        "apiKeyMetadata",
        "apiKeyValue"
      ]
    },
    "GetAccessTokenRequest": {
      "description": "We accept an OIDC ID token issued by a trusted identity provider as proof of authentication. The ID token is validated and exchanged for a Nominal access token with a 24h expiry. This ID token should generally be short lived since it is fungible with a Nominal access token via this endpoint. An access token, if provided, is used to get user information from the OIDC userinfo endpoint. A workspace rid or an org rid should be provided if the user is a guest or a member of multiple orgs. These will be resolved to determine what org the Nominal token should be minted for.",
      "type": "object",
      "properties": {
        "idToken": {
          "type": "string"
        },
        "accessToken": {
          "type": "string"
        },
        "orgRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "OrgRid"
        },
        "workspaceRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "WorkspaceRid"
        }
      },
      "required": [
        "idToken"
      ],
      "example": {
        "idToken": "<id token>"
      }
    },
    "GetAccessTokenResponse": {
      "type": "object",
      "properties": {
        "accessToken": {
          "type": "string"
        },
        "expiresAtSeconds": {
          "type": "integer",
          "format": "int64"
        },
        "userUuid": {
          "type": "string",
          "format": "uuid"
        },
        "orgUuid": {
          "type": "string",
          "format": "uuid"
        },
        "isGuest": {
          "type": "boolean",
          "description": "True if the user reaches the token's org as a guest rather than a member. Populated by all endpoints; optional for version compatibility."
        }
      },
      "required": [
        "accessToken",
        "expiresAtSeconds",
        "userUuid",
        "orgUuid"
      ]
    },
    "GetIdpEndSessionEndpointRequest": {
      "description": "We use an OIDC id token issued by a trusted identity provider to access the end session endpoint. This is only used to get the issuer",
      "type": "object",
      "properties": {
        "idToken": {
          "type": "string"
        }
      },
      "required": [
        "idToken"
      ],
      "example": {
        "idToken": "<id token>"
      }
    },
    "GetIdpEndSessionEndpointResponse": {
      "type": "object",
      "properties": {
        "endSessionEndpoint": {
          "type": "string"
        }
      }
    },
    "GetUserOrgsRequest": {
      "description": "We use the claims in the id + access token to determine which orgs the user belongs to.",
      "type": "object",
      "properties": {
        "idToken": {
          "type": "string"
        },
        "accessToken": {
          "type": "string"
        }
      },
      "required": [
        "idToken"
      ],
      "example": {
        "idToken": "<id token>"
      }
    },
    "GetUserOrgsResponse": {
      "type": "object",
      "properties": {
        "orgs": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "The configured name of each organization the user belongs to, keyed by organization UUID."
        },
        "orgDisplayNames": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "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."
        }
      }
    },
    "ListApiKeyRequest": {
      "type": "object",
      "properties": {
        "includeDeleted": {
          "type": "boolean",
          "description": "If true, include deleted API keys in the response. Defaults to false."
        },
        "includeExpired": {
          "type": "boolean",
          "description": "If true, include expired API keys in the response. Defaults to false."
        },
        "pageSize": {
          "type": "integer",
          "format": "int32",
          "description": "The maximum number of API keys to return. Defaults to 100."
        },
        "nextPageToken": {
          "type": "string",
          "x-alias": "Token"
        }
      },
      "example": {
        "includeDeleted": true,
        "includeExpired": true,
        "pageSize": 1,
        "nextPageToken": "<token>"
      }
    },
    "ListApiKeyResponse": {
      "type": "object",
      "properties": {
        "apiKeys": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/ApiKey"
          },
          "uniqueItems": true
        },
        "nextPageToken": {
          "type": "string",
          "x-alias": "Token"
        }
      }
    },
    "RefreshAccessTokenRequest": {
      "description": "We accept an OIDC access token issued by a trusted identity provider to refresh a Nominal access token. The access token is validated and exchanged for a Nominal access token. To be used in this endpoint, the OIDC access token must contain an email claim. The org rid from the expiring session should be provided. It is required for guest users and multi-org users to determine what org the Nominal token should be minted for.",
      "type": "object",
      "properties": {
        "accessToken": {
          "type": "string"
        },
        "orgRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "OrgRid"
        }
      },
      "required": [
        "accessToken"
      ],
      "example": {
        "accessToken": "<access token>"
      }
    },
    "RefreshAccessTokenResponse": {
      "type": "object",
      "properties": {
        "accessToken": {
          "type": "string"
        },
        "expiresAtSeconds": {
          "type": "integer",
          "format": "int64"
        },
        "userUuid": {
          "type": "string",
          "format": "uuid"
        },
        "orgUuid": {
          "type": "string",
          "format": "uuid"
        },
        "isGuest": {
          "type": "boolean",
          "description": "True if the user reaches the token's org as a guest rather than a member. Populated by all endpoints; optional for version compatibility."
        }
      },
      "required": [
        "accessToken",
        "expiresAtSeconds",
        "userUuid",
        "orgUuid"
      ]
    },
    "RegisterInWorkspaceRequest": {
      "type": "object",
      "properties": {
        "resourceRids": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "rid"
          },
          "uniqueItems": true
        },
        "workspaceRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "WorkspaceRid"
        }
      },
      "required": [
        "workspaceRid"
      ],
      "example": {
        "workspaceRid": "<workspace rid>"
      }
    },
    "SetUserOrgRequest": {
      "description": "Switch the authenticated session to the provided org rid. The user must belong to that org. Returns a new Nominal access token scoped to the org, with expiry bounded by the current token's remaining lifetime (capped at 24h).",
      "type": "object",
      "properties": {
        "orgRid": {
          "type": "string",
          "format": "rid",
          "x-alias": "OrgRid"
        }
      },
      "required": [
        "orgRid"
      ],
      "example": {
        "orgRid": "<org rid>"
      }
    }
  },
  "tags": [
    {
      "name": "Authorization Service",
      "x-displayName": "Authorization service",
      "description": "Authorization service manages the permissions for a user to access resources.",
      "x-errors": [
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:InvalidJwtAudience"
        },
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:InvalidJwtExpired"
        },
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:InvalidJwtFormat"
        },
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:InvalidJwtIssuer"
        },
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:NoMembership"
        },
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:NotAuthorized"
        },
        {
          "status": 403,
          "errorCode": "PERMISSION_DENIED",
          "errorName": "Authorization:NotAuthorizedAdmin"
        },
        {
          "status": 409,
          "errorCode": "CONFLICT",
          "errorName": "Authorization:RegisterResourceConflict",
          "description": "The resource has already been registered with a different workspace."
        },
        {
          "status": 404,
          "errorCode": "NOT_FOUND",
          "errorName": "Authorization:WorkspaceNotFound"
        },
        {
          "status": 400,
          "errorCode": "INVALID_ARGUMENT",
          "errorName": "Authorization:MissingClaims"
        },
        {
          "status": 404,
          "errorCode": "NOT_FOUND",
          "errorName": "Authorization:ApiKeyNotFound"
        }
      ]
    }
  ]
}
