Documentation menu

Projects & API Keys

Create and list projects within an org, and manage the API keys used to authenticate against them.

Projects

GET /api/orgs/:orgSlug/projects

List all projects in an org.

Auth: session cookie

Response 200

{
  "projects": [
    { "id": "proj_01abc", "org_id": "org_01xyz", "name": "Default", "slug": "default", "created_at": 1720392000000 }
  ]
}

Ordered by created_at ascending. No pagination.

Errors:

  • 404{ "error": "Organization not found" }
  • 403{ "error": "Not a member" } — authenticated user isn’t a member of this org

POST /api/orgs/:orgSlug/projects

Create a project in an org.

Auth: session cookie · requires admin or owner role

Request body

fieldtyperequireddescription
namestringyesProject name. Its slug is derived automatically (slugify(name)) — not settable directly

Response 201

{ "id": "proj_01new", "name": "Payments", "slug": "payments" }

Errors:

  • 404{ "error": "Organization not found" }
  • 403{ "error": "Insufficient permissions" } — the member role cannot create projects
  • 400{ "error": "Name is required" }
  • 402{ "error": "usage_limit_exceeded", "message": "Project limit reached. Upgrade your plan." } — org is at its plan’s project cap. This check is best-effort: a billing-DB error is swallowed and does not block creation

Common responses (401) apply — see Authentication. 429 doesn’t apply to this endpoint.

API keys

Keys are project-scoped (created against whichever project the request resolves to) and returned in full exactly once, at creation. GET/POST/DELETE below are mounted at both the plain path and /api/orgs/:orgSlug/projects/:projectSlug/settings/api-keysuse the org-scoped path. At the plain path, GET /api/settings/api-keys always returns 403 (its admin-role check depends on org context that only the org-scoped mount resolves), and POST/DELETE there only work correctly when authenticated with a project API key rather than a session cookie (a session cookie at the plain path doesn’t resolve an org/project, and a key created that way ends up with an empty org_id/project_id).

GET /api/orgs/:orgSlug/projects/:projectSlug/settings/api-keys

List API keys for the resolved project.

Auth: session cookie · requires admin or owner role

Response 200

{
  "keys": [
    { "id": "key_01abc", "name": "CI", "key_prefix": "lm_ak_3f9a2b1c...", "last_used_at": 1720392000000, "created_at": 1720000000000 }
  ]
}

The key material itself (hash) is never returned; key_prefix is the first 12 characters of the raw key plus ..., for identifying a key in a list. last_used_at is null until the key is first used.

POST /api/orgs/:orgSlug/projects/:projectSlug/settings/api-keys

Create an API key for the resolved project.

Auth: session cookie (no role restriction beyond being a member — any role can create a key)

Request body

fieldtyperequireddescription
namestringyesLabel for the key

Response 201

{ "id": "key_01new", "key": "lm_ak_3f9a2b1c8d7e6f5a4b3c2d1e0f9a8b7c", "name": "CI" }

key is the plaintext key — it is generated with a lm_ak_ prefix, only ever returned in this response, and cannot be retrieved again (only its key_prefix shows up in GET).

Errors: 400{ "error": "Name is required" }

DELETE /api/orgs/:orgSlug/projects/:projectSlug/settings/api-keys/:id

Revoke an API key.

Auth: session cookie (no role restriction beyond being a member)

Response 200

{ "ok": true }

Errors: 404{ "error": "Not found" } — no key with that ID in this project


Common responses (401; 402 and 429 don’t apply) — see Authentication.