Projects Endpoints
All project endpoints are under /projects.
Create Project
POST /projects/Authentication: Required
Request Body:
{
"name": "My App",
"description": "My awesome application",
"is_public": true
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name |
description | string | No | Project description |
is_public | boolean | No | Public or private (default: false) |
INFO
The slug is always auto-generated from the project name and cannot be specified in the request body.
Response 201:
{
"id": "uuid",
"name": "My App",
"slug": "my-app",
"description": "My awesome application",
"is_public": true,
"owner_id": "user-uuid",
"created_at": "2024-01-01T00:00:00.000Z"
}List Projects
GET /projects/Authentication: Required
Returns all projects the user is a member of.
Get Project
GET /projects/:slugAuthentication: Required
Update Project
PATCH /projects/:slugAuthentication: Required (owner or admin)
Request Body (all optional):
{
"name": "Updated Name",
"description": "Updated description",
"is_public": false
}Delete Project
DELETE /projects/:slugAuthentication: Required (owner only)
Join Project
Join a public project.
POST /projects/:slug/joinAuthentication: Required
INFO
Only works for public projects. For private projects, use invites.
Leave Project
DELETE /projects/:slug/leaveAuthentication: Required
WARNING
The project owner cannot leave. Transfer ownership first.
List Members
GET /projects/:slug/membersAuthentication: Required (project member)
Response 200:
[
{
"id": "member-uuid",
"user_id": "user-uuid",
"role": "owner",
"user": {
"id": "user-uuid",
"email": "owner@example.com",
"display_name": "Project Owner"
},
"permissions": [],
"created_at": "2024-01-01T00:00:00.000Z"
}
]Add Member
POST /projects/:slug/membersAuthentication: Required (owner or admin)
Request Body:
{
"email": "user@example.com",
"role": "member",
"permissions": ["can_deploy"]
}| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email of the user to add |
role | "admin" | "member" | No | Role (default: member) |
permissions | string[] | No | Array of permission keys |
Update Member
PATCH /projects/:slug/members/:memberIdAuthentication: Required (owner or admin)
Request Body:
{
"role": "admin",
"permissions": ["can_deploy", "can_edit"]
}INFO
Permissions use string keys (e.g., "can_deploy", "editor"), not UUIDs.
Remove Member
DELETE /projects/:slug/members/:memberIdAuthentication: Required (owner or admin)
Transfer Ownership
POST /projects/:slug/transfer-ownershipAuthentication: Required (owner only)
Request Body:
{
"new_owner_id": "new-owner-uuid"
}The current owner becomes an admin after transfer.
Permissions
List Permissions
GET /projects/:slug/permissionsCreate Permission
POST /projects/:slug/permissionsRequest Body:
{
"key": "can_deploy",
"display_name": "Can Deploy",
"description": "Allow deployment to production",
"is_default": false
}| Field | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Unique permission identifier |
display_name | string | Yes | Human-readable name |
description | string | No | Permission description |
is_default | boolean | No | Whether assigned to new members by default (default: false) |
Update Permission
PATCH /projects/:slug/permissions/:permissionIdDelete Permission
DELETE /projects/:slug/permissions/:permissionIdProject OAuth Clients
Create Client
POST /projects/:slug/clientsRequest Body:
{
"name": "My App OAuth Client",
"redirect_uri": "https://myapp.com/callback"
}List Clients
GET /projects/:slug/clientsProject Invites
List Invites
GET /projects/:slug/invitesCreate Invite
POST /projects/:slug/invitesRequest Body:
{
"email": "user@example.com",
"role": "member",
"redirect_url": "https://myapp.com/welcome"
}| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email of the user to invite |
role | "admin" | "member" | No | Role (default: member) |
redirect_url | string | No | URL to redirect after accepting |
INFO
Invites expire after 7 days.
Cancel Invite
DELETE /projects/:slug/invites/:inviteId