> ## Documentation Index
> Fetch the complete documentation index at: https://docs.photon.codes/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Use Stable documentation by default. Honor an explicit Beta request or a URL under /docs/beta/. If the requested version conflicts with the installed CLI package or API origin, clarify the target before writing integration code.
> Pages under /docs/beta/ document Beta; other product pages document Stable. Keep the CLI package, commands, API origin, and credentials within the selected version. State the documentation version in your answer.
> For MCP search, always pass version: Stable or version: Beta. Unfiltered search mixes both versions. For filesystem reads, keep Beta queries under /beta/ and exclude /beta/ from Stable queries; discover paths before reading them.
> The public docs base is https://photon.codes/docs. Convert MCP page paths to public URLs under that base, preserving /beta/ when present. Read https://photon.codes/docs/skill.md for version selection and https://photon.codes/docs/llms.txt for the version indexes.

# Projects

> Select the project each folder acts on and manage its resources and settings.

A project is the unit that owns your Photon resources — phone numbers, email
domains, API keys, webhooks, and billing. Every project belongs to an
[organization](https://docs.photon.codes/docs/beta/cli/organizations.md), which also holds its members.
`photon project` manages projects and everything inside them.

```sh theme={null}
photon project list
photon project create --name "Support line" --slug support-line --link
photon project current
```

## Command overview

```text theme={null}
photon link --project <project-id>
photon unlink
photon project
├── list [--search] [--created-after] [--created-before]
│          [--limit 30] [--page-token <token>]
├── count [--search] [--created-after] [--created-before]
├── create --name <name> --slug <slug> [--link] [--idempotency-key <key>]
├── view
├── edit --name <name> [--idempotency-key <key>]
├── delete <project-id> [--yes]
├── current
├── agent-profile ...        # see Agent profile
├── api-key ...              # see API keys
├── billing ...              # see Billing
├── platform ...             # see Platform resources
└── webhook ...              # see Webhooks
```

Every node generates its own help and shell completion. Run any of them with
`--help`, such as `photon project create --help`.

> [card] [Platform resources](https://docs.photon.codes/docs/beta/cli/projects/platform.md)
>
> Phone numbers, email domains, and voice routing.

> [card] [API keys](https://docs.photon.codes/docs/beta/cli/projects/api-keys.md)
>
> Issue and revoke project API keys.

> [card] [Webhooks](https://docs.photon.codes/docs/beta/cli/projects/webhooks.md)
>
> Subscribe endpoints to project events.

> [card] [Agent profile](https://docs.photon.codes/docs/beta/cli/projects/agent-profile.md)
>
> The name and avatar your project presents.

> [card] [Billing](https://docs.photon.codes/docs/beta/cli/projects/billing.md)
>
> Plans, subscriptions, and invoices.

## Projects in an organization

`project list`, `project count`, and `project create` work in the
[selected organization](https://docs.photon.codes/docs/beta/cli/organizations.md#select-an-organization): `--org`,
`PHOTON_ORGANIZATION_ID`, the organization of the folder's project, the one
`org use` saved, or your only organization.

```sh theme={null}
photon project list
photon project create --name "Support line" --slug support-line --org pho_org_01k9yq3m7d2c8x4v6b5n0p1r2s
```

Project resources include `organizationId`. The project membership `role` is
gone, and so is the `--role` filter: access comes from your organization role.

> [!NOTE]
>
> `photon project member`, `project invitation`, and `project leave` moved to
> [`photon org`](https://docs.photon.codes/docs/beta/cli/organizations#moved-commands). The old names only print
> the replacement and exit with code `2`.

## Select an active project

Most commands are project-scoped. They resolve the project in this order:

1. The global `--project <project-id>` flag, for that invocation only.
2. A non-empty `PHOTON_PROJECT_ID` environment variable.
3. The `.photon/project.json` that `photon link` saved in the current
   folder, or in the nearest folder above it.

There is no account-wide default. Each folder remembers its own project, so
running `photon link` in one repository never changes the project another
repository acts on.

```sh theme={null}
photon link --project pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s  # save it for this folder and below
photon project current                                    # show it and where it came from
photon --project pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2t project view
PHOTON_PROJECT_ID=pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2v photon project view
photon unlink                                             # remove the nearest .photon/project.json
```

> [!NOTE]
>
> Agents and scripts should pass `--project <project-id>` or set
> `PHOTON_PROJECT_ID` on every command, rather than rely on the folder they
> happen to run in.

With none of the three, a command that needs a project fails with
`PROJECT_NOT_SELECTED` and exits `2`, as a missing required flag does. If
you aren't signed in at all, the sign-in error comes first.

`photon project current` reports the source as `flag`, `environment`, or
`folder`, with the file's `path` for `folder`. An empty `PHOTON_PROJECT_ID`
is ignored rather than treated as a selection.

Before a command changes anything in a project you didn't name with
`--project`, it names the project and where it came from on stderr, for
example `Project: pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2v, from PHOTON_PROJECT_ID` or
`Project: pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s, from /srv/support-bot/.photon/project.json`.
When the command has already read the project, the line also gives the
project's name and organization. A command that asks for confirmation prints
the line before its question, `--project` included. The line costs no extra
request, and with `--json` it is still text on stderr, so stdout does not
change.

### The folder's project file

`photon link` takes the project as `--project`, as `vercel link` and
`railway link` do; `PHOTON_PROJECT_ID` doesn't stand in for it. It fetches
the project before saving it, so you can never save an inaccessible ID. It
writes `.photon/project.json` in the current folder, with the project and its
organization:

```json theme={null}
{
  "apiOrigin": "https://api.photon.codes",
  "organizationId": "pho_org_01k9yq3m7d2c8x4v6b5n0p1r2s",
  "projectId": "pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s",
  "schemaVersion": 1
}
```

It also adds `.photon/` to the `.gitignore` in that folder, creating the file
if there is none, and never adds the line twice, as `vercel link` does with
`.vercel`. The file is your checkout's choice, not the repository's.

The organization it saves is always the project's own. If you also pass
`--org` and it names another organization, `photon link` refuses: it exits
`2` with `ORGANIZATION_MISMATCH`, names the project and both organizations,
and writes nothing. Its `next` gives the same command without `--org`, and
with the project's organization. Only `--org` is checked:
`PHOTON_ORGANIZATION_ID` and the organization `photon org use` stored don't
stop a link.

```console theme={null}
$ photon link --project pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s --org pho_org_01k9yq3m7d2c8x4v6b5n0p1r2t
Error: Project Support line (pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s) belongs to organization pho_org_01k9yq3m7d2c8x4v6b5n0p1r2s, not pho_org_01k9yq3m7d2c8x4v6b5n0p1r2t. (ORGANIZATION_MISMATCH)
Next:
  1. Run it without --org: photon link --project pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s
  2. Run it with the project's organization: photon link --project pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s --org pho_org_01k9yq3m7d2c8x4v6b5n0p1r2s
Docs: https://photon.codes/docs/cli/output#errors
```

`project create --link` saves the project it just created the same way.
Replaying a `project create --link` with `photon operation replay` saves no
file, because the operation journal doesn't record the folder; it prints the
`photon link` step to run instead. `photon unlink` removes the nearest
file, and warns you if `PHOTON_PROJECT_ID` or a file in a folder above still
selects a project. Deleting a project removes the file only when it names that
project.

The file records the API it was saved against. A CLI that talks to another API
passes over it and uses the nearest file above that it saved itself, so the
production and staging builds keep separate projects. `photon link` replaces
whatever file is in the current folder, including one the other build saved.

With `--json`, `photon link` and `project create --link` add the file's
`path`, `source: "folder"`, and `gitignore`: `added`, `listed` (the
`.gitignore` already had it), or `failed` (with a warning on stderr). When
`project create --link` can't save the file, because of a folder error or a
project or organization ID that isn't canonical, it prints
`{"project": {...}}` alone, with a warning on stderr; the project is created
either way.
`photon unlink` returns `cleared`, the removed file's `path`, and, when
`PHOTON_PROJECT_ID` or a file above still selects a project, `active` with
that project's `projectId`, `source`, and `path` for a file.

## Pagination and filters

Paginated list commands default to `--limit 30`. The CLI follows page tokens
for you until it has that many records or reaches the last page, preserving the
order the API returned.

When more records remain, JSON output includes `nextPageToken`. `billing invoice
list` keeps the API's `nextCursor` instead, which is `null` on the last page.
Pass the token back with `--page-token` to continue:

```sh theme={null}
photon project list \
  --search support \
  --created-after 2026-07-01T00:00:00Z \
  --limit 100 \
  --json
```

Text output ends with one stderr line that is the same command with the
organization or project written in and the next page's token, for example
`More results: photon project list --search support --org pho_org_01k9yq3m7d2c8x4v6b5n0p1r2s --page-token <token>`.

Timestamps accept RFC 3339 input and are normalized to UTC; `--created-after`
cannot be later than `--created-before`.

> [!NOTE]
>
> `api-key list` is not paginated — the SDK returns every live key, newest
> first.

## JSON contracts

Global `--json` prints one object on stdout, the result or the
[error](https://docs.photon.codes/docs/beta/cli/output.md#errors), and sends warnings to stderr. Collections use a
named envelope:

```json theme={null}
{"projects":[],"nextPageToken":"opaque-token"}
{"assignments":[]}
{"resources":[],"provisioning":[],"nextPageToken":"opaque-resource-token"}
{"invoices":[],"nextCursor":null}
{"apiKeys":[]}
{"destinations":[],"nextPageToken":"opaque-token"}
{"apiVersions":[],"contractNamespace":"@photon-hq/contracts","packageVersion":"1.0.0"}
```

A single item is the bare object, as Photon sends it. The documents the CLI
defines, listed under [Envelopes](https://docs.photon.codes/docs/beta/cli/output.md#envelopes) on the JSON output
page, put the API's object under a name of their own, such as `project` or
`operation`, or add keys beside the API's response, such as `provisioning`.

`project list`, `count`, `create`, `view`, `edit` and `delete`, the
`project agent-profile`, `project api-key` and `project webhook` commands, and
the `project platform` commands that read one response (`list`,
`operation cancel`, `email dns`, `imessage view`,
`imessage assignment create`, `list`, `view` and `release`, `telegram view`,
and `whatsapp-business number list` and `number view`) and the ones that start
an operation and wait for it (`sms purchase` and `delete`, `imessage purchase`,
`email connect` and `disconnect`, `telegram connect` and `disconnect`, and
`whatsapp-business number add --waba-id` and `number delete`), and
`billing invoice list`, `billing operation view` and
`billing plan purchase` print the API's response as Photon sends it: a list
keeps the API's envelope, such as `{"projects": [...], "nextPageToken": "..."}`
or `{"platforms": [...]}`, a single item is the bare object, a deletion or
revocation prints the API's response with no `deleted` or `revoked` boolean,
and a field the API adds shows up in the JSON. `project delete` prints the
project with `deletedAt` set. See [API keys](https://docs.photon.codes/docs/beta/cli/projects/api-keys.md),
[Agent profile](https://docs.photon.codes/docs/beta/cli/projects/agent-profile.md),
[Webhooks](https://docs.photon.codes/docs/beta/cli/projects/webhooks.md#json-output),
[Platform resources](https://docs.photon.codes/docs/beta/cli/projects/platform.md) and
[Billing](https://docs.photon.codes/docs/beta/cli/projects/billing.md), which also describes the documents
`billing overview`, `billing subscription cancel` and `resume` print. The
`email`, `imessage`, `sms` and `telegram` `list` commands print Photon's page
of resources as it sends it, with the provisioning operations still in
progress under `provisioning`. `whatsapp-business account list` prints the
project's one account as Photon sends it in `{"accounts": [...]}`, which is
empty when none is connected, and `whatsapp-business number add` with
`--source byon` or `--new-waba` prints a `handoff` to the dashboard.

`project current`, `project create --link` and `photon link` print a
document of their own that holds the API's project,
`{"project": {...}, "source": "..."}`. For `project current`, `source` is
`flag`, `environment` or `folder`, with the file's `path` for `folder`.
`project create --link` and `photon link` add the file they saved:

```json theme={null}
{"project":{"agentProfile":{"avatarUrl":"https://images.example.com/agent.png","firstName":"Photon","lastName":null},"billingInitialization":"completed","createdAt":"2026-08-01T18:00:00.000Z","createdByAccountId":"pho_acc_01k9yq3m7d2c8x4v6b5n0p1r2s","createdByActorId":"pho_acc_01k9yq3m7d2c8x4v6b5n0p1r2s","createdByActorKind":"account","deletedAt":null,"name":"Support line","organizationId":"pho_org_01k9yq3m7d2c8x4v6b5n0p1r2s","projectId":"pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s","slug":"support-line","updatedAt":"2026-08-01T18:00:00.000Z"},"gitignore":"added","path":"/https/photon.codes/srv/support-bot/.photon/project.json","source":"folder"}
```

See [JSON output and exit codes](https://docs.photon.codes/docs/beta/cli/output.md) for the error envelope and
`--debug` traces.

## Confirmations

Destructive commands ask before they act. Interactive input accepts `y` or
`yes`; anything else cancels, prints `Cancelled.` on stderr and exits `1`.
`project delete` takes the ID of the project it deletes, and at a terminal it
asks you to type the project's name. Without a terminal, pass `--yes` (`-y`):
without it the command exits `2` with `CONFIRMATION_REQUIRED` and changes
nothing. See [Prompts and confirmation](https://docs.photon.codes/docs/beta/cli/output.md#prompts-and-confirmation).

```sh theme={null}
photon project delete pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s
photon project delete pho_prj_01k9yq3m7d2c8x4v6b5n0p1r2s --yes --json
```

> [accordion] Commands that require confirmation
>
> * Project deletion
> * API key revocation
> * Agent avatar reset
> * iMessage assignment release
> * Subscription cancellation
> * Plan purchase
> * Email-domain disconnection
> * Telegram connection when the project already has a bot
> * SMS-number purchase
> * SMS-number deletion
> * Voice profile inbound changes that affect assigned lines
> * Voice profile outbound credential rotation and revocation
> * Voice profile assignment changes
> * Voice profile deletion
> * Webhook destination deletion
> * Webhook signing-secret rotation

## Recovery

Most state-changing calls are protected by a local write-ahead journal, so a
mutation whose result you never saw can be replayed rather than guessed at. See
[Recoverable operations](https://docs.photon.codes/docs/beta/cli/operations.md).

Project creation requires a unique `--slug`: 3–63 lowercase letters or digits, with single hyphens between words.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.