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

# Create and Send a New Agent Invitation in Shilo API

> Invite an agent to join your Shilo organization by email. Returns 201 when a new invitation is created, or 200 if a pending one exists.

Use this endpoint to programmatically invite agents to join your Shilo organization. A successful `201` response indicates the invitation was created and its workflow was queued; it does not confirm that the invitation email has been delivered. Provide your own system's user identifier and, optionally, a role at invite time to maintain consistent identity mapping from day one.

## Endpoint

```text theme={null}
POST https://api.shilo.ai/api/v1/invitations
```

## Authentication

This endpoint requires a **write-enabled** API key:

```text theme={null}
x-api-key: YOUR_API_KEY
```

## Request Body

Send a `CreateInvitationDto` JSON object in the request body.

<ParamField body="email" type="string" required>
  The email address to invite. The invitation workflow will target this address.
</ParamField>

<ParamField body="external_user_id" type="string" required>
  Your system's unique identifier for this user. Stored alongside the Shilo user record for cross-system identity mapping.
</ParamField>

<ParamField body="invited_by_user_id" type="string">
  Shilo UUID of the user sending the invitation. Exactly one of `invited_by_user_id` or `invited_by_email` is required.
</ParamField>

<ParamField body="invited_by_email" type="string">
  Email address of the user sending the invitation. Exactly one of `invited_by_user_id` or `invited_by_email` is required.
</ParamField>

<ParamField body="name" type="string">
  Display name for the agent. Used to personalize the invitation email and pre-populate the agent's profile.
</ParamField>

<ParamField body="first_name" type="string">
  Optional first name for the agent.
</ParamField>

<ParamField body="role" type="string">
  Role to assign to the user upon accepting the invitation. Must be `ADMIN` or `MEMBER`. Defaults to `MEMBER`.
</ParamField>

## Response

### 201 — Created

A new invitation was created and the invitation workflow was queued. Returns the created Invitation object.

<ResponseField name="id" type="string">
  Unique identifier for the new invitation (UUID).
</ResponseField>

<ResponseField name="email" type="string">
  Recipient email address for the invitation.
</ResponseField>

<ResponseField name="external_user_id" type="string">
  Your system's identifier for the invited user.
</ResponseField>

<ResponseField name="name" type="string | null">
  Display name for the invited agent. May be `null` when not provided.
</ResponseField>

<ResponseField name="first_name" type="string | null">
  First name for the invited agent. May be `null` when not provided.
</ResponseField>

<ResponseField name="role" type="string">
  Role assigned on the invitation. `ADMIN` or `MEMBER`.
</ResponseField>

<ResponseField name="status" type="string">
  Invitation status. Will be `PENDING` immediately after creation.
</ResponseField>

<ResponseField name="created_date" type="string">
  ISO-8601 timestamp of when the invitation was created.
</ResponseField>

<ResponseField name="expires_date" type="string">
  ISO-8601 timestamp indicating when this invitation expires.
</ResponseField>

<ResponseField name="invited_by_user_id" type="string">
  Shilo UUID of the user who created the invitation.
</ResponseField>

<ResponseField name="invitation_link" type="string">
  Shareable link the recipient can use to accept the invitation.
</ResponseField>

### 200 — Already Exists

A pending invitation for this email address already exists. The existing Invitation object is returned. **No new email is sent.** Use the [Resend Invitation](/api-reference/invitations/resend-invitation) endpoint if you need to re-trigger the email.

### 400 — Bad Request

The request body is missing required fields or contains invalid values.

### 403 — Forbidden

Your API key does not have write permissions.

### 409 — Conflict

A pending invitation for this email already exists but was created with a different `external_user_id`. Resolve the conflict before retrying.

## Example Request

```bash theme={null}
curl --request POST \
  --url "https://api.shilo.ai/api/v1/invitations" \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "email": "newagent@example.com",
    "external_user_id": "usr_abc123",
    "name": "Jordan Smith",
    "first_name": "Jordan",
    "role": "MEMBER",
    "invited_by_email": "manager@example.com"
  }'
```

## Example Response

```json theme={null}
{
  "id": "ee6f2136-b94a-4438-9335-3acf5b2a0d31",
  "email": "newagent@example.com",
  "external_user_id": "usr_abc123",
  "name": "Jordan Smith",
  "first_name": "Jordan",
  "role": "MEMBER",
  "status": "PENDING",
  "created_date": "2030-09-24T12:34:56Z",
  "expires_date": "2030-10-08T12:34:56Z",
  "invited_by_user_id": "b1f0a4c2-2d3e-4a10-9c66-27c1a8b7f004",
  "invitation_link": "https://app.shilo.ai/invitations/ee6f2136-b94a-4438-9335-3acf5b2a0d31/accept"
}
```

<Note>
  If you receive a **200** response, the existing invitation was returned and no new email was queued. Use the [Resend Invitation](/api-reference/invitations/resend-invitation) endpoint to re-trigger the invitation email.
</Note>
