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

# Invites

> List and send contractor/client invites

<Note>
  All invite endpoints here require `Authorization: Bearer <jwt>` — see [Authentication](/v1-legacy/authentication).
</Note>

## List invites

**GET** `/v1/invites`

<ParamField query="company_riseid" type="string">V1/V2 RiseID of the company/team.</ParamField>
<ParamField query="company_id" type="number | string">Legacy numeric id, V1/V2 RiseID, or nanoid of the company/team (alternative to `company_riseid`).</ParamField>

<Note>
  At least one of `company_riseid` or `company_id` is required. Unlike other endpoints here, invites don't resolve a RiseAccount address — use the RiseID or nanoid instead (see [Identifier formats](/v1-legacy/overview#identifier-formats)).
</Note>

<RequestExample>
  ```bash theme={null}
  curl -X GET "https://b2b-api.riseworks.io/v1/invites?company_riseid=te-abc123def456" \
    -H "Authorization: Bearer <jwt>"
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "data": [
      {
        "invite_id": "in-abc123def456",
        "email": "newcontractor@example.com",
        "alias": null,
        "invite_alternate_value": "newcontractor@example.com",
        "converted": false,
        "role": "contractor",
        "anonymous": false,
        "uuid": "in-abc123def456",
        "avatar": null,
        "status": "pending"
      }
    ]
  }
  ```
</ResponseExample>

`status` is one of `pending`, `awaiting_invite_acceptance`, `onboard_compliance_pending`, or `onboard_started`.

<Note>
  `converted` is always `false` in the current implementation — it doesn't yet reflect actual invite-acceptance state, regardless of `status`. `uuid` is always identical to `invite_id` (the same value under two keys, kept for V1 response-shape parity).
</Note>

**SDK:**

```javascript theme={null}
const invites = await client.v1Legacy.listInvites({ company_riseid: 'te-abc123def456' });
```

## Send invites

**POST** `/v1/invites`

<ParamField body="inviteList" type="array" required>
  Emails to invite — either bare strings or `{ email, external_reference_id? }` objects.
</ParamField>

<ParamField body="anonymous" type="boolean">Defaults to `false`. Not allowed for `role: "client"`.</ParamField>
<ParamField body="company_riseid" type="string">V1/V2 RiseID of the company/team.</ParamField>
<ParamField body="company_id" type="number | string">Legacy numeric id, V1/V2 RiseID, or nanoid of the company/team (alternative to `company_riseid`).</ParamField>

<ParamField body="role" type="string" default="contractor">
  One of `contractor`, `client`, `aor_contractor`, `team_employee`.
</ParamField>

<RequestExample>
  ```bash theme={null}
  curl -X POST "https://b2b-api.riseworks.io/v1/invites" \
    -H "Authorization: Bearer <jwt>" \
    -H "Content-Type: application/json" \
    -d '{
      "company_riseid": "te-abc123def456",
      "role": "contractor",
      "inviteList": [
        "newcontractor@example.com",
        { "email": "another@example.com", "external_reference_id": "emp-123" }
      ]
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "data": {
      "failed": [],
      "countAdded": 2,
      "invited": ["newcontractor@example.com", "another@example.com"]
    }
  }
  ```
</ResponseExample>

Already-pending invites are re-counted as `invited` (re-sent), not created again — matching V1's original behavior. Invalid or already-in-company emails show up in `failed` instead, as `{ "invite": "<email>", "error": "<reason>" }` objects — not plain strings. `countAdded` equals `invited.length`, including re-sends, despite the name suggesting only newly-created invites.

**SDK:**

```javascript theme={null}
const result = await client.v1Legacy.sendInvites({
  company_riseid: 'te-abc123def456',
  role: 'contractor',
  inviteList: ['newcontractor@example.com'],
});
```

## Send warmed (pre-filled) invites

**POST** `/v1/invites/warmed`

Sends invites pre-filled with contractor details, skipping manual data entry during onboarding. Supports a `light` mode (name + email only) and a full mode (address, DOB, company data). Unlike [Send invites](#send-invites), there's no `anonymous` option here — warmed invites are always non-anonymous.

<ParamField body="light" type="boolean" default="false">Light mode only requires name and email.</ParamField>

<ParamField body="users" type="array" required>
  Array of users to invite — see shape below.
</ParamField>

<ParamField body="company_riseid" type="string">V1/V2 RiseID of the company/team.</ParamField>
<ParamField body="company_id" type="number | string">Legacy numeric id, V1/V2 RiseID, or nanoid of the company/team (alternative to `company_riseid`).</ParamField>

<ParamField body="role" type="string" default="contractor">
  One of `contractor`, `team_employee`, `aor_contractor`. Can be overridden per-user.
</ParamField>

Each item in `users`:

```json theme={null}
{
  "role": "contractor",
  "sumsub_sharetoken": null,
  "details": {
    "email": "newcontractor@example.com",
    "firstname": "Jane",
    "lastname": "Doe",
    "middlename": "A",
    "dob": "1990-01-01",
    "external_reference_id": "emp-123"
  },
  "address": {
    "country": "US",
    "city": "Austin",
    "state": "TX",
    "address_line1": "123 Main St",
    "zip": "78701"
  }
}
```

* `sumsub_sharetoken` (string, optional) — a Sumsub applicant share token. When present, `details.firstname`/`lastname`/`address` are no longer required (Sumsub already has them) — everything else in this section assumes it's omitted.
* `details.firstname`/`lastname` are required unless `sumsub_sharetoken` is set.
* `details.dob`, if present, must parse as a valid date.
* `details.external_reference_id`, if present, must be 1–255 characters.
* `address.country` must be a 2-letter uppercase code (e.g. `US`, `GB`) — anything else is rejected.
* `address` is required in full mode (omitted when `light: true` or when `sumsub_sharetoken` is provided); `address_line1`/`address_line2`/`zip`/`timezone` are capped at 255 characters.
* `role` here accepts `contractor`, `team_employee`, or `aor_contractor` only — unlike [Send invites](#send-invites), there's no `client` option.

<RequestExample>
  ```bash theme={null}
  curl -X POST "https://b2b-api.riseworks.io/v1/invites/warmed" \
    -H "Authorization: Bearer <jwt>" \
    -H "Content-Type: application/json" \
    -d '{
      "light": true,
      "company_riseid": "te-abc123def456",
      "users": [
        {
          "details": { "email": "newcontractor@example.com", "firstname": "Jane", "lastname": "Doe" }
        }
      ]
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "data": {
      "failed": [],
      "countAdded": 1,
      "invited": ["newcontractor@example.com"]
    }
  }
  ```
</ResponseExample>

Same response shape as [Send invites](#send-invites) — `failed` items are `{ invite, error }` objects.

**SDK:**

```javascript theme={null}
const result = await client.v1Legacy.sendWarmedInvites({
  light: true,
  company_riseid: 'te-abc123def456',
  users: [{ details: { email: 'newcontractor@example.com', firstname: 'Jane', lastname: 'Doe' } }],
});
```

## Errors

| Status | Cause                                                                                                  |
| ------ | ------------------------------------------------------------------------------------------------------ |
| `400`  | Missing/invalid parameters, self-invite attempt, or inviting into a V2-only company (no default team). |
| `401`  | Missing or expired JWT.                                                                                |
| `403`  | Caller lacks invite permission on the company/team.                                                    |
| `404`  | Company or team not found.                                                                             |

Still stuck? See [Troubleshooting](/v1-legacy/troubleshooting).
