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

# Invite by email

> Owner: invite anyone to a Flow Team seat by email

Reserves a seat and emails the invitee. In one step the server:

* creates a 60db account if the email has none (own workspace + Free plan, no password yet),
* adds the person to the licence workspace as a `member` (Flow works inside the licence's workspace),
* adds a **pending** seat, sends an in-app notification and the email "\<owner> invited you to 60db Flow" with a
  **Set your password** button (account without a password) or an **Open 60db** button.

If any step fails (for example no seat is free), nothing is saved.

## Request

### Headers

<ParamField header="Authorization" type="string" required>
  `Bearer <login token>` of the signed-in 60db user. API keys (`sk_...`) are not accepted for Flow.
</ParamField>

<ParamField header="X-60db-Client" type="string">
  `flow/<app-version>`, e.g. `flow/1.5.0` (send it from the 60db Flow app)
</ParamField>

### Path Parameters

<ParamField path="license_id" type="string" required>
  Licence id (`license_id` from [Get Flow plan](/api-reference/flow/get-plan))
</ParamField>

### Query Parameters

<ParamField query="workspace_id" type="integer">
  The licence's workspace. Seat management is checked against it: send it when the user's current workspace is a different one.
</ParamField>

### Body

<ParamField body="email" type="string" required>
  Email address to invite
</ParamField>

## Response

<ResponseField name="data.user_id" type="integer">Invitee user id (use it to cancel the invite)</ResponseField>
<ResponseField name="data.email" type="string">Invitee email</ResponseField>
<ResponseField name="data.status" type="string">`pending`</ResponseField>
<ResponseField name="data.seats" type="integer">Seats on the licence</ResponseField>
<ResponseField name="data.seats_used" type="integer">Seats taken after this invite</ResponseField>
<ResponseField name="data.account_created" type="boolean">A new 60db account was created for this email</ResponseField>
<ResponseField name="data.joined_workspace" type="boolean">The invitee was added to the licence workspace</ResponseField>
<ResponseField name="data.set_password_sent" type="boolean">The email contains a "Set your password" link</ResponseField>

## Errors

Errors use `{ "success": false, "message": "...", "error_code": "..." }`. Show `message` to the user.

| Status | `error_code` | Meaning |
| - | - | - |
| 400 | `INVALID_EMAIL` | Not a valid email address |
| 400 | `DISPOSABLE_EMAIL` | Disposable email providers are not allowed |
| 400 | `SEAT_LIMIT_REACHED` | All seats are used; remove a seat or cancel an invite first |
| 400 | `LICENSE_INACTIVE` | Licence refunded, revoked or expired |
| 403 | `NOT_LICENSE_OWNER` | Only the buyer can manage seats |
| 404 | `LICENSE_NOT_FOUND` | Unknown licence id |
| 409 | `SEAT_ALREADY_ASSIGNED` | This person already has a seat or a pending invite |
| 429 | `RATE_LIMIT_EXCEEDED` | More than 20 invitations in an hour |

## Example

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.60db.ai/60db/license/LICENSE_ID/seats?workspace_id=WORKSPACE_ID" \
    -H "Authorization: Bearer USER_JWT" \
    -H "X-60db-Client: flow/1.5.0" \
    -H "Content-Type: application/json" \
    -d '{"email":"ravi@acme.com"}'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "license_id": "2f1c9a4e-6b7d-4c1e-9f0a-1d2e3f4a5b6c",
      "user_id": 88,
      "email": "ravi@acme.com",
      "status": "pending",
      "seats": 3,
      "seats_used": 2,
      "account_created": true,
      "joined_workspace": true,
      "set_password_sent": true
    }
  }
  ```
</ResponseExample>


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