Laizy CMS
API Reference

Projects API

REST API reference for managing projects in Laizy CMS.

Projects API

Projects are the top-level container for content in Laizy CMS. Each project has its own content models, content entries, and access controls. Projects are scoped to an organization and can be shared with other organizations via role-based access.

Authentication

All project endpoints require an admin-scoped token:

Authorization: Bearer laizy_eyJhbGciOiJI...

The organization context is resolved from the token itself (the orgId claim in the JWT). No x-laizy-project header is needed for project management endpoints -- these operate at the organization level.

EndpointRequired Access
project.createOrg admin
project.listOrg admin
project.getByIdProject admin
project.getBySlugProject admin
project.updateProject admin
project.archiveProject admin
project.restoreProject admin
project.shareProject admin
project.revokeAccessProject admin
project.transferProject admin
project.getAccessProject admin
project.hasAccessProject admin
project.getOrCreateDefaultOrg admin

project.create

Create a new project within the current organization.

Input

{
  slug: string;              // URL-safe identifier (lowercase, numbers, hyphens)
  name: string;              // Display name (1-100 characters)
  description?: string;      // Optional description (max 500 characters)
}

Slug validation rules:

  • 1-63 characters long
  • Only lowercase letters, numbers, and hyphens (^[a-z0-9-]+$)
  • Must be unique within the organization

Response

{
  id: string;
  name: string;
  slug: string;
  description: string | null;
  organizationId: string;
  status: 'active' | 'archived';
  createdByMemberId: string;
  createdAt: Date;
  updatedAt: Date;
}

Example with ManagementClient

const project = await client.createProject({
  name: 'Marketing Website',
  slug: 'marketing-website',
  description: 'Content for the main marketing site',
});

console.log(project.id);   // "proj_abc123"
console.log(project.slug); // "marketing-website"

Errors

CodeCause
BAD_REQUESTInvalid slug format or slug already taken
UNAUTHORIZEDToken does not have org admin access

project.list

List all projects accessible to the current organization.

Input

{
  includeArchived?: boolean;   // Default: false
}

Response

Returns an array of projects. By default, archived projects are filtered out.

[
  {
    id: string;
    name: string;
    slug: string;
    description: string | null;
    organizationId: string;
    status: 'active' | 'archived';
    createdAt: Date;
    updatedAt: Date;
  }
]

Example with ManagementClient

// Active projects only
const projects = await client.listProjects();

// Include archived
const allProjects = await fetch(
  'https://laizycms.com/api/trpc/project.list?input={"includeArchived":true}',
  {
    headers: { 'Authorization': `Bearer ${apiToken}` },
  },
);

project.getById

Fetch a single project by its unique ID.

Input

{
  id: string;    // Project ID
}

Response

Returns the full project object or throws NOT_FOUND.

Example with ManagementClient

const project = await client.getProject('proj_abc123');
console.log(project.name); // "Marketing Website"

Errors

CodeCause
NOT_FOUNDProject does not exist or organization has no access

project.getBySlug

Fetch a project by its slug. Optionally specify a different organization to look up shared projects.

Input

{
  slug: string;
  organizationId?: string;   // Defaults to current org
}

Response

Returns the full project object or throws NOT_FOUND. If looking up a project in another organization, the endpoint verifies that the current organization has been granted access.

Example

const response = await fetch(
  'https://laizycms.com/api/trpc/project.getBySlug?input={"slug":"marketing-website"}',
  {
    headers: { 'Authorization': `Bearer ${apiToken}` },
  },
);

Errors

CodeCause
NOT_FOUNDProject does not exist
FORBIDDENOrganization does not have access to this project

project.update

Update a project's metadata. Supports partial updates -- only include the fields you want to change.

Input

{
  id: string;
  data: {
    name?: string;           // 1-100 characters
    slug?: string;           // URL-safe identifier
    description?: string;    // Max 500 characters
  };
}

Response

Returns the updated project.

Example with ManagementClient

const updated = await client.updateProject('proj_abc123', {
  name: 'Main Marketing Website',
  description: 'Updated description',
});

Errors

CodeCause
NOT_FOUNDProject does not exist
BAD_REQUESTInvalid slug format or slug conflict
FORBIDDENInsufficient permissions

project.archive

Soft-delete a project by setting its status to archived. The project and its content are preserved but hidden from default list queries.

Input

{
  id: string;    // Project ID to archive
}

Response

Returns the archived project with status: 'archived'.

Example

const archived = await fetch(
  'https://laizycms.com/api/trpc/project.archive',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ id: 'proj_abc123' }),
  },
);

Errors

CodeCause
FORBIDDENOnly the owning organization can archive a project

project.restore

Restore an archived project back to active status.

Input

{
  id: string;    // Project ID to restore
}

Response

Returns the restored project with status: 'active'.

Errors

CodeCause
FORBIDDENOnly the owning organization can restore a project

project.share

Share a project with another organization by granting them a role.

Input

{
  projectId: string;
  targetOrgId: string;                                // Organization to share with
  role: 'owner' | 'editor' | 'content_editor';       // Access level to grant
}

Roles

RolePermissions
ownerFull access including delete, share, and transfer
editorManage content models and content data
content_editorCreate and edit content entries only

Response

Returns the created access record:

{
  id: string;
  projectId: string;
  organizationId: string;
  role: string;
  grantedByMemberId: string;
  createdAt: Date;
}

Example

const access = await fetch(
  'https://laizycms.com/api/trpc/project.share',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      projectId: 'proj_abc123',
      targetOrgId: 'org_xyz789',
      role: 'editor',
    }),
  },
);

Errors

CodeCause
FORBIDDENOnly the owning organization can share a project

project.revokeAccess

Remove another organization's access to a project.

Input

{
  projectId: string;
  targetOrgId: string;    // Organization to remove
}

Response

{
  success: boolean;
}

Errors

CodeCause
FORBIDDENOnly the owning organization can revoke access
BAD_REQUESTCannot revoke the owning organization's access

You cannot revoke the owning organization's access to a project. To change ownership, use project.transfer instead.

project.transfer

Transfer project ownership to another organization. The original owner loses their owner role.

Input

{
  projectId: string;
  newOrganizationId: string;    // New owner organization
}

Response

Returns the updated project with the new organizationId.

Errors

CodeCause
FORBIDDENOnly the current owner can transfer ownership

project.getAccess

List all organizations that have access to a project, including their roles.

Input

{
  projectId: string;
}

Response

Returns an array of access records:

[
  {
    organizationId: string;
    role: 'owner' | 'editor' | 'content_editor';
    grantedByMemberId: string;
    createdAt: Date;
  }
]

Errors

CodeCause
FORBIDDENCurrent organization does not have access to this project

project.hasAccess

Check whether the current organization has access to a project, optionally verifying a specific role.

Input

{
  projectId: string;
  requiredRole?: 'owner' | 'editor' | 'content_editor';
}

Response

{
  hasAccess: boolean;
}

project.getOrCreateDefault

Get the default project for the organization, creating one if it does not exist. This is used during onboarding to ensure every organization has at least one project.

Input

No additional input required. The organization is resolved from the token.

Response

Returns the default project (created if necessary).

Next Steps

On this page