# Projects & forms > Read-only discovery. Find the project handle your capture calls need and the forms they can target, without leaving code. Source: https://getlaunchlist.com/help/docs/api/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`](/help/docs/api/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. > [!TIP] You rarely need the form handle > Omit `form` on a capture call and the signup uses the project's oldest active waitlist form. Name a > `frm_` handle only when a project runs more than one form and you need a specific one. ## Paging through both Both lists use the same cursor pagination as the rest of the API ([pagination](/help/docs/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 - [Create a contact](/help/docs/api/contacts-create): the call these handles feed - [Retrieve the workspace](/help/docs/api/workspace): the same scope, for plan and usage ## 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.