Access Scopes - API Reference

Complete reference for all Access Scope REST API endpoints.

All endpoints use the base path:
https://api.nolag.app/v1/organizations/:orgId/projects/:projectId/scopes

Authentication is required via Authorization: Bearer <api-key> header.

Create Scope

POST /v1/organizations/:orgId/projects/:projectId/scopes

Request Body

FieldTypeRequiredDescription
slugstringYesURL-safe identifier. Used in topic namespacing. Immutable after creation.
namestringNoHuman-readable display name.

Response: 201 Created

const response = await fetch(
  `https://api.nolag.app/v1/organizations/${orgId}/projects/${projectId}/scopes`,
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      slug: "client-acme",
      name: "Acme Corporation",
    }),
  }
);

// Response: 201 Created
// {
//   "accessScopeId": "01HZ...",
//   "slug": "client-acme",
//   "name": "Acme Corporation",
//   "createdAt": "2026-05-20T10:00:00.000Z",
//   "updatedAt": "2026-05-20T10:00:00.000Z"
// }

List Scopes

GET /v1/organizations/:orgId/projects/:projectId/scopes

Query Parameters

ParameterTypeDefaultDescription
pagenumber1Page number for pagination.
limitnumber10Number of results per page (max 100).
orderBystringcreatedAt:DESCSort order. Example: slug:ASC

Response: 200 OK

const response = await fetch(
  `https://api.nolag.app/v1/organizations/${orgId}/projects/${projectId}/scopes?page=1&limit=10`,
  {
    headers: {
      "Authorization": `Bearer ${apiKey}`,
    },
  }
);

// Response: 200 OK
// {
//   "data": [
//     { "accessScopeId": "01HZ...", "slug": "client-acme", "name": "Acme Corporation", ... },
//     { "accessScopeId": "01HZ...", "slug": "client-beta", "name": "Beta Corp", ... }
//   ],
//   "meta": { "page": 1, "limit": 10, "total": 2, "totalPages": 1 }
// }

Get Scope

GET /v1/organizations/:orgId/projects/:projectId/scopes/:scopeId

Path Parameters

ParameterTypeDescription
scopeIdUUIDThe Access Scope ID.

Response: 200 OK

const response = await fetch(
  `https://api.nolag.app/v1/organizations/${orgId}/projects/${projectId}/scopes/${scopeId}`,
  {
    headers: {
      "Authorization": `Bearer ${apiKey}`,
    },
  }
);

// Response: 200 OK
// {
//   "accessScopeId": "01HZ...",
//   "slug": "client-acme",
//   "name": "Acme Corporation",
//   "createdAt": "2026-05-20T10:00:00.000Z",
//   "updatedAt": "2026-05-20T10:00:00.000Z"
// }

Update Scope

PATCH /v1/organizations/:orgId/projects/:projectId/scopes/:scopeId

Request Body

FieldTypeRequiredDescription
namestringNoUpdated display name. The slug field cannot be updated.

Response: 200 OK

const response = await fetch(
  `https://api.nolag.app/v1/organizations/${orgId}/projects/${projectId}/scopes/${scopeId}`,
  {
    method: "PATCH",
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Acme Corp (Renamed)",
      // Note: slug CANNOT be updated after creation
    }),
  }
);

// Response: 200 OK
// {
//   "accessScopeId": "01HZ...",
//   "slug": "client-acme",
//   "name": "Acme Corp (Renamed)",
//   "createdAt": "2026-05-20T10:00:00.000Z",
//   "updatedAt": "2026-05-20T12:00:00.000Z"
// }

Delete Scope

DELETE /v1/organizations/:orgId/projects/:projectId/scopes/:scopeId

Deleting a scope will remove the scope assignment from all actors currently assigned to it. Those actors will become unscoped and revert to the default topic namespace.

Response: 204 No Content

const response = await fetch(
  `https://api.nolag.app/v1/organizations/${orgId}/projects/${projectId}/scopes/${scopeId}`,
  {
    method: "DELETE",
    headers: {
      "Authorization": `Bearer ${apiKey}`,
    },
  }
);

// Response: 204 No Content
// All actors previously assigned to this scope will have their
// accessScopeId set to null (unscoped).

List Actors in Scope

GET /v1/organizations/:orgId/projects/:projectId/scopes/:scopeId/actors

Returns all actors currently assigned to this scope. Supports pagination.

Query Parameters

ParameterTypeDefaultDescription
pagenumber1Page number for pagination.
limitnumber10Number of results per page (max 100).

Response: 200 OK

const response = await fetch(
  `https://api.nolag.app/v1/organizations/${orgId}/projects/${projectId}/scopes/${scopeId}/actors?page=1&limit=10`,
  {
    headers: {
      "Authorization": `Bearer ${apiKey}`,
    },
  }
);

// Response: 200 OK
// {
//   "data": [
//     { "actorId": "01HZ...", "name": "user-alice", "accessScopeId": "01HZ...", ... },
//     { "actorId": "01HZ...", "name": "user-bob", "accessScopeId": "01HZ...", ... }
//   ],
//   "meta": { "page": 1, "limit": 10, "total": 2, "totalPages": 1 }
// }

Response Schemas

AccessScope

FieldTypeDescription
accessScopeIdUUIDUnique identifier for the scope.
slugstringURL-safe identifier used in topic namespacing. Immutable.
namestring | nullHuman-readable display name.
createdAtISO 8601Timestamp when the scope was created.
updatedAtISO 8601Timestamp of the last update.

Error Responses

StatusDescription
400Invalid request body or parameters (e.g., missing slug, invalid UUID).
401Missing or invalid authentication.
404Scope, project, or organization not found.
409Slug already exists within this project.

Next Steps