# Projects

Source: https://solidhooks.com/docs/projects

> How projects divide an organisation's sources, destinations and events, and how the X-Project-Id header and project-bound API keys select one.

A project is a namespace inside an organisation. Every source, destination, connection, event and delivery lives in exactly one project. Use projects to keep things like production and staging apart.

The organisation is the billing and tenancy boundary, and API keys belong to it. Connectors are also organisation-level, so one connector can serve destinations in any project.

Signup creates a project called "Default Project", so a new account works without any project setup.

## Choose a project per request

Project-scoped endpoints (`/v1/sources`, `/v1/destinations`, `/v1/connections`, `/v1/events`, `/v1/deliveries`, `/v1/stats/*`) accept an optional `X-Project-Id` header.

| Header                                                      | What the request targets                                         |
| ----------------------------------------------------------- | ---------------------------------------------------------------- |
| Omitted                                                     | The organisation's oldest project, normally the Default Project. |
| A project id in your organisation                           | That project.                                                    |
| An id from another organisation, or one that does not exist | `404`.                                                           |

```bash
curl -s "$API/v1/sources" \
  -H "authorization: Bearer $SDHK_KEY" \
  -H 'x-project-id: proj_...'
```

The `404` is deliberate. The API does not say whether a project exists elsewhere.

> **Agents**
>
> `X-Project-Id` belongs to the API-key surface. Agents using delegated identity pick a project with the `account.select_project` capability instead. See [Agent Auth](https://solidhooks.com/docs/agent-auth).

## Manage projects

`/v1/projects` is organisation-level and does not need the header.

```bash
# List
curl -s "$API/v1/projects" -H "authorization: Bearer $SDHK_KEY"

# Create
curl -s "$API/v1/projects" \
  -H "authorization: Bearer $SDHK_KEY" \
  -H 'content-type: application/json' \
  -d '{ "name": "Staging", "slug": "staging" }'

# Update
curl -s -X PATCH "$API/v1/projects/proj_..." \
  -H "authorization: Bearer $SDHK_KEY" \
  -H 'content-type: application/json' \
  -d '{ "data": { "name": "Staging (EU)" } }'

# Delete
curl -s -X DELETE "$API/v1/projects/proj_..." \
  -H "authorization: Bearer $SDHK_KEY"
```

| Field  | Rules                                                                                |
| ------ | ------------------------------------------------------------------------------------ |
| `name` | 1 to 100 characters. Required on create and on update.                               |
| `slug` | Lowercase letters, numbers and hyphens only. Required on create, optional on update. |

In the dashboard, use the project switcher and choose **Create project**.

Deleting a project deletes everything in it: sources, destinations, events and deliveries. You cannot delete the only project in an organisation; the API returns `400`.

## Project-bound API keys

When someone creates an API key they choose **Project access**: every project, or exactly one. A key bound to one project only ever sees that project.

* On data endpoints, no header targets the bound project. Any other `X-Project-Id` returns `404`.
* On `/v1/projects`, list returns only the bound project. Get, update and delete of any other project return `404`.
* Creating a project returns `403`, because project management is an organisation-level concern. Use a key with access to every project.

The binding is fixed for the life of the key. To reach a different project, ask the owner for a new key. `GET /v1/projects` tells you which project a key can see.

## Permissions

Keys can be scoped per resource. Reading projects needs `project: read`; create, update and delete need `project: read & write`. An unscoped key can read, create and update projects but gets `403 INSUFFICIENT_API_KEY_PERMISSIONS` on delete. See [API keys](https://solidhooks.com/docs/api-keys).

## Next steps

* [API keys](https://solidhooks.com/docs/api-keys) — scope a key to one project or one resource
* [Quickstart](https://solidhooks.com/docs/quickstart) — send a first webhook in the Default Project
* [How SolidHooks works](https://solidhooks.com/docs/how-it-works) — where projects sit in the object model