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

# Projects

> Isolate ingest, dashboards, and AI features within an org using first-class projects.

Projects let you split a single Raindrop org into isolated workspaces, for example one per product, environment, or team. Each project keeps its own events, dashboards, signals, and AI features separate from the others.

<Info>
  If you've never created a project, you're already using one: every org has a built-in **Production** project (slug `default`). Existing data and SDK calls belong to it automatically, so you don't need to change anything unless you want multiple projects.
</Info>

## What a project is

A project is a named, isolated slice of your org. Everything you send to Raindrop is recorded against exactly one project, and the dashboard, signals, and AI features only ever read from one project at a time.

Each project has two identifiers:

| Field                 | Mutable?                | Used for                                                  |
| --------------------- | ----------------------- | --------------------------------------------------------- |
| **Slug** (project ID) | No (frozen at creation) | The `X-Raindrop-Project-Id` header, SDK options, and URLs |
| **Display name**      | Yes                     | What you see in the dashboard                             |

The slug is a short identifier of up to 63 characters using lowercase letters, digits, and hyphens, and it must start and end with a letter or digit (for example, `support-prod`). It is chosen when the project is created and never changes. Renaming a project changes only its display name; the slug stays the same, so any header, SDK option, or saved URL referencing it keeps working.

## The default "Production" project

Every org starts with one reserved project:

* Its slug is `default` and cannot be changed or reused.
* Its display name is **Production** (you can rename the display name, but not the slug).
* It is the implicit project: any request that doesn't specify a project resolves to `default`.

This is what keeps single-project orgs working without any changes; see [Backward compatibility](#backward-compatibility).

## Isolation

Projects are isolated end to end:

* **Ingest:** events, traces, and signals are stored against the project they were sent to.
* **Dashboards and analytics:** the dashboard scopes everything (events, conversations, issues, stumbles) to the selected project.
* **AI features:** topic classification, signals, Tiny Models, and the Triage Agent operate per project, so a model trained in one project doesn't leak into another.

There is no cross-project read: switching projects in the dashboard switches the entire data scope.

## Archival

Projects can be **archived** when you no longer need them. There is no hard delete yet.

* Archiving hides a project from the dashboard and stops it from accepting new data.
* Archived slugs are **not reusable**: you can't create a new project that reuses an archived project's slug.
* Data sent to an archived project is rejected with a `403`. See [Behavior](#behavior).
* The `default` project cannot be archived.

## Permissions

Creating, renaming, and archiving projects is restricted to **Owner** and **Admin** roles. Members can send data to and view existing projects, but cannot manage the project list.

## Setting the project from an SDK

You select a project per request by sending its slug. The canonical contract is the `X-Raindrop-Project-Id` HTTP header; each SDK also exposes an option that sets this header for you.

<Info>
  When the slug is omitted, empty, or `default`, the request resolves to the **Production** (`default`) project, identical to not specifying a project at all.
</Info>

### HTTP header (canonical)

Send the project slug in the `X-Raindrop-Project-Id` header alongside your write key:

```bash theme={null}
curl https://api.raindrop.ai/v1/events/track \
  -H "Authorization: Bearer YOUR_WRITE_KEY" \
  -H "X-Raindrop-Project-Id: support-prod" \
  -H "Content-Type: application/json" \
  -d '[{ "user_id": "user_123", "event": "chat_message" }]'
```

See the [HTTP API reference](/sdk/http-api) for the full request shape.

### TypeScript / JavaScript

Pass `projectId` when constructing the client; every event from that client is scoped to the project:

```typescript theme={null}
import { Raindrop } from "raindrop-ai";

const raindrop = new Raindrop({
  writeKey: RAINDROP_API_KEY,
  projectId: "support-prod",
});
```

The browser SDK (`@raindrop-ai/browser-sdk`) accepts the same `projectId` option.

### Python

Pass `project_id` to `raindrop.init(...)`:

```python theme={null}
import raindrop.analytics as raindrop

raindrop.init("YOUR_WRITE_KEY", project_id="support-prod")
```

## Behavior

The table below describes what happens to data you send on ingest:

| Project sent on ingest                                           | Result                                                                                                                                                                                |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Unset, empty, or `default`                                       | Resolves to the **Production** (`default`) project (backward compatible)                                                                                                              |
| An active project slug in your org                               | Accepted and scoped to that project                                                                                                                                                   |
| A new slug your org hasn't created yet, within the per-org limit | Accepted; the data is stored and the slug appears in **Settings -> Projects** to be created (see [Discovering projects from ingested data](#discovering-projects-from-ingested-data)) |
| An archived project slug                                         | Request rejected with `403`                                                                                                                                                           |
| A new slug beyond the per-org limit                              | Request rejected with `403`                                                                                                                                                           |
| A malformed slug                                                 | Request rejected with `400`                                                                                                                                                           |

Reads are stricter than writes: the dashboard and [Query API](/query-api/api-reference) only return data for a project that exists and is active, so an unknown or archived slug returns a `403` on read.

<Note>
  Event views are finalized-only, so events sent via `trackAiPartial` / `track_partial` appear once they finalize, not while still pending. This is independent of projects. See [Core Concepts](/core-concepts).
</Note>

## Discovering projects from ingested data

You don't have to create a project before you send data to it. When you send events with a new slug your org hasn't used yet, Raindrop accepts them and stores the data under that slug, up to a per-org limit on slugs that don't yet have a project.

Each such slug then appears in **Settings -> Projects** under "Projects with data, not yet created", along with how many events it has received and when it was last seen. An Owner or Admin can select **Create project** there to create it. The data only becomes visible in the dashboard and the Query API once the project has been created.

This lets you start sending from a new slug in your code first and create the project in the dashboard afterward, without losing the data sent in between. Once your org reaches the limit, further new slugs are rejected with a `403` until you create some of the pending ones.

## Backward compatibility

Projects are fully backward compatible. Orgs that never set a project keep sending to the `default` project, and every existing query, dashboard, and SDK call behaves exactly as before. You only opt in to multi-project behavior by creating additional projects and sending their slugs.
