Projects API
Projects are keyed by slug, not by UUID, in every project-scoped path. A slug
is 3..50 lowercase letters, digits, or hyphens and must start and end with a
letter or digit. The UUID still exists as project_id in payloads, but the path
parameter and the Z4J agent config both use the slug.
List my projects
Section titled “List my projects”GET /api/v1/projectsReturns projects the authenticated user has a role in. Global brain admins are
the exception: they see every active project regardless of membership, up to
Z4J_ADMIN_PROJECT_LIST_CAP. When the caller uses a project-scoped bearer key,
the response is further filtered to that bound project.
[ { "id": "...", "slug": "billing-prod", "name": "Billing (production)", "description": null, "environment": "production", "timezone": "UTC", "is_active": true, "default_scheduler_owner": "z4j-scheduler", "allowed_schedulers": null, "created_at": "...", "updated_at": "..." }]Get project
Section titled “Get project”GET /api/v1/projects/{slug}Role: viewer. Returns the same ProjectPublic shape.
Create project
Section titled “Create project”POST /api/v1/projectsRole: global brain admin (is_admin=true), not merely project admin.
CSRF-protected. The first admin is created through first-boot setup, not this
endpoint.
{ "slug": "billing-prod", "name": "Billing (production)", "description": null, "environment": "production", "timezone": "UTC", "default_scheduler_owner": "z4j-scheduler", "allowed_schedulers": null}Field rules:
slug: 3..50 lowercase letters / digits / hyphens, starting and ending with a letter or digit.environment: 1..40 chars matching^[a-z][a-z0-9_-]{0,39}$; canonical values areproduction,staging,development,test, but free-form is accepted so values such asstaging-eucontinue to work.default_scheduler_owner: the scheduler that owns new schedules when the caller did not pick one. Free-form (40 char cap, lowercase pattern). Defaultz4j-scheduler.allowed_schedulers: optional allow-list of scheduler names.nullmeans unrestricted; an empty list is rejected. Capped at 32 entries. When set, it must containdefault_scheduler_owner.
Update project
Section titled “Update project”PATCH /api/v1/projects/{slug}Role: global brain admin. CSRF-protected. Any subset of the create fields,
including the slug itself. A slug rename takes effect immediately: saved REST
URLs, bookmarks, CLI --slug values, and schedule-import manifests using the
old slug start returning 404. Running agents and project-scoped API keys remain
bound by project UUID and continue to work.
Delete project
Section titled “Delete project”DELETE /api/v1/projects/{slug}Role: global brain admin. CSRF-protected and requires fresh MFA, so this route
requires a browser session rather than an API key. Delete is a soft archive: it
sets is_active=false and leaves agents, tasks, events, schedules, memberships,
and audit rows intact. The slug remains taken. Archiving the final active
project is refused.