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

# Authentication

> How to authenticate API requests using session cookies and workspace headers.

# Authentication

The Tedro API uses **session-based authentication**. Every API request requires two credentials:

1. A **session cookie** -- proves your identity (set automatically on sign-in)
2. An **`x-workspace-id` header** -- specifies which workspace you are accessing

## Step 1: Sign In

Obtain a session cookie by sending your email and password to the sign-in endpoint:

```bash cURL theme={null}
curl -X POST https://api.tedro.io/api/auth/sign-in/email \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "you@example.com",
    "password": "your-password"
  }'
```

```javascript Node.js theme={null}
const response = await fetch('https://api.tedro.io/api/auth/sign-in/email', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'you@example.com',
    password: 'your-password',
  }),
});

// The response includes a Set-Cookie header with the better-auth.session_token cookie.
// In Node.js, you need to extract and store it for subsequent requests.
const setCookie = response.headers.get('set-cookie');
const sessionToken = setCookie?.match(/better-auth\.session_token=([^;]+)/)?.[1];
```

On success, the response sets a `better-auth.session_token` cookie. The cURL `-c cookies.txt` flag saves this cookie to a file for use in subsequent requests.

## Step 2: Find Your Workspace ID

Your workspace ID is a UUID that identifies which workspace your API calls target. You can find it in the Tedro dashboard URL:

```
https://app.tedro.io/app/[workspaceId]/overview
                              ^^^^^^^^^^^^
                              This is your workspace ID
```

## Organization-Scoped Access

Tedro uses an organization and workspace hierarchy. Your user account belongs to one or more **organizations**, each containing one or more **workspaces**.

* Your session cookie authenticates your **user identity** at the organization level
* The `x-workspace-id` header selects which **workspace** within your organization to access
* You must be a member of the workspace (or an org owner) to access its data

### Roles

Your workspace role determines which API endpoints you can call:

| Role          | Access Level                                                                            |
| ------------- | --------------------------------------------------------------------------------------- |
| **Org Owner** | Full access to all workspaces in the organization                                       |
| **Admin**     | Full access within the workspace -- publish workflows, manage tools, configure channels |
| **Agent**     | Inbox access and view-only for runs -- cannot publish, edit tools, or modify settings   |
| **Viewer**    | Read-only access to all workspace data                                                  |

Attempting an action above your role returns a `403 Forbidden` response.

## Step 3: Make Authenticated Requests

Include both the session cookie and `x-workspace-id` header on every API call:

```bash cURL theme={null}
curl https://api.tedro.io/api/workflows \
  -b cookies.txt \
  -H "x-workspace-id: your-workspace-uuid"
```

```javascript Node.js theme={null}
const response = await fetch('https://api.tedro.io/api/workflows', {
  headers: {
    'Cookie': `better-auth.session_token=${sessionToken}`,
    'x-workspace-id': 'your-workspace-uuid',
  },
});

const data = await response.json();
console.log(data.items);
```

## Session Lifecycle

| Property             | Value                                              |
| -------------------- | -------------------------------------------------- |
| **Session duration** | 7 days (absolute timeout)                          |
| **Sliding renewal**  | Session token refreshes every 24 hours of activity |
| **Cookie name**      | `better-auth.session_token`                        |
| **Cookie flags**     | `httpOnly`, `Secure`, `SameSite=Lax`               |

Sessions expire after 7 days of inactivity. Active sessions are automatically renewed every 24 hours -- you do not need to re-authenticate during normal use.

## Missing or Invalid Credentials

| Scenario                        | Status | Response                    |
| ------------------------------- | ------ | --------------------------- |
| No session cookie               | `401`  | `{"error": "Unauthorized"}` |
| Expired session                 | `401`  | `{"error": "Unauthorized"}` |
| Missing `x-workspace-id` header | `401`  | `{"error": "Unauthorized"}` |
| Invalid workspace UUID          | `403`  | `{"error": "Forbidden"}`    |
| User not a member of workspace  | `403`  | `{"error": "Forbidden"}`    |

## Brute Force Protection

The sign-in endpoint has built-in brute force protection:

* **5 failed attempts** per email+IP combination triggers a lockout
* **Lockout duration**: 15 minutes
* During lockout, the endpoint returns `429 Too Many Requests`
* The counter resets on successful sign-in

## Rate Limits on Auth Endpoints

| Endpoint                         | Limit                     |
| -------------------------------- | ------------------------- |
| `POST /api/auth/sign-in/email`   | 5 requests per 60 seconds |
| `POST /api/auth/sign-up/email`   | 3 requests per 5 minutes  |
| `POST /api/auth/forget-password` | 3 requests per hour       |
| `POST /api/auth/reset-password`  | 3 requests per hour       |
| All other `/api/auth/*`          | 10 requests per minute    |

<Note>
  The API playground in these docs may not work with cookie-based authentication due to cross-domain restrictions. Use cURL or your own code to test API calls.
</Note>
