Projects & forms

Read-only discovery. Find the project handle your capture calls need and the forms they can target, without leaving code.

Updated ·3 min read
GET/v1/projects

Read-only discovery. These are how a key finds the prj_ handle every capture call names, and the frm_ handles a call can target with form. Everything here is managed in the dashboard; the API only reads it.

Requires the projects:read scope, which also grants /v1/workspace.

Projects#

GET /v1/projects
GET /v1/projects/{project}
Field Description
object Always project.
id The prj_ handle, which is what POST /v1/contacts references as project.
name The project's display name.
slug Its public slug, or null if it has no public page.
status Its lifecycle status: building, ready, launched or post_launch.
archived true once the project is archived: closed to signups and mail, read-only to the API.
page_url The hosted launch page, or null when there is no public page.
created_at ISO 8601.
url This project's path on the API, for convenience.

A key pinned to one project lists exactly that project: the pin is a boundary, not a default. An unpinned key lists every project in its workspace.

Forms#

GET /v1/forms
GET /v1/forms/{form}
Field Description
object Always form.
id The frm_ handle, which is what POST /v1/contacts references as form.
name The form's display name.
type The form kind: waitlist, survey or marketing.
status Its lifecycle status: draft, active or archived.
project The prj_ handle it belongs to.
submit_url The public submit endpoint, for callers using the embed contract directly.
fields Only on GET /v1/forms/{form}: the inputs you can send, in the order the form shows them. Each has key, label, type, required and is_identity, plus options for a type that has a list of choices (and options_preset when a preset such as countries supplies it).
created_at ISO 8601.
url This form's path on the API, for convenience.

GET /v1/forms lists every form the key can see. Add ?project=prj_7Qk2mN4pR8 to narrow to one project. A pinned key is always narrowed to its own.

Paging through both#

Both lists use the same cursor pagination as the rest of the API (pagination): limit (1 to 100, default 25), plus starting_after or ending_before taking an object handle. Every response carries has_more. Most workspaces have few enough projects and forms that one page is the whole answer.

Next#

Common questions

Which scope do these need?

projects:read, which is present in both dashboard key presets. The same scope grants GET /v1/workspace.

How do I find the frm_ handle for POST /v1/contacts?

List the project's forms with GET /v1/forms?project=prj_7Qk2mN4pR8 and read the id off the form you want. Omitting form on a capture call uses the project's oldest active waitlist form.

My key is pinned to one project. What do these return?

Exactly that project and its forms. A pinned key lists one project, never the whole workspace. The pin is a boundary, not a default.

Was this page helpful?
curl "https://api.getlaunchlist.com/v1/projects" \
  -H "Authorization: Bearer llk_live_8xKq3Rp9Wm2Nz7Vt6yL1cG5dH0jA4sE8uNqB2fXk"
{
  "object": "list",
  "url": "/v1/projects",
  "has_more": false,
  "data": [
    {
      "object": "project",
      "id": "prj_7Qk2mN4pR8",
      "name": "Acme Labs",
      "slug": "acme",
      "status": "launched",
      "archived": false,
      "page_url": "https://acme.launchlist.page",
      "created_at": "2026-07-14T09:02:41+00:00",
      "url": "/v1/projects/prj_7Qk2mN4pR8"
    }
  ]
}