---
title: "Invite a user to a project by email"
method: POST
path: "/projects/{project_id}/invites"
---

# Invite a user to a project by email

`POST /projects/{project_id}/invites`

## Request

- Base URL: `https://api.ionworks.com`
- URL: `https://api.ionworks.com/projects/{project_id}/invites`
- Auth: none declared

Invite someone to a project by email, whatever their organization status.

Unlike ``POST /{project_id}/members``, the invitee need not already belong to
the organization: an unregistered email is invited, and a non-member is granted
``Member``. An existing member keeps the organization role they already hold.

Requires ``role:assign``, not merely ``project:manage_members`` — minting an
organization membership is an org-level grant however project-shaped the
request looks.

Returns
-------
AddUserByEmailResult
    The invitee's user id, and ``invite_sent`` — ``False`` when the address
    already belonged to a registered account, so no email was dispatched.

## Path parameters

- `project_id` string, uuid, required

## Request body

- InviteProjectMemberBody
  - `email` string, required: Email address of the person to invite.
  - `project_role_id` string, required: ID of the project role to assign.

## Response `201`

Successful Response

- AddUserByEmailResult: Result of adding a user to an organization by email. Returned by the service and used verbatim as the route's response model.
  - `user_id` string, required: ID of the (invited or pre-existing) user that was added.
  - `invite_sent` boolean, required: True when the email was not registered yet and an invitation email was dispatched. False when the email already belonged to a registered user, in which case the existing account was linked and no email was sent.
  - `already_member` boolean: True when the user already belonged to the organization. Their membership, including its role, was left unchanged.
  - `role_name` string, nullable: Organization role the user holds after the request, when the endpoint reports it.

## Other responses

- `422`: Validation Error

## Changes

- **2026-09-30** `ea3d377fec1a`: 1 breaking, 2 info
  - for the `path` request parameter `project_id`, the format changed from no format to `uuid`
  - added the optional property `already_member` to the response with the `201` status
  - added the optional property `role_name` to the response with the `201` status
- **2026-09-16** `6ee5ca7926de`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ionworks/apis/ionworks-api/changes/projects/:project_id/invites/post.md)

---

[API](https://skmtc.dev/ionworks/apis/ionworks-api.md) - [All operations](https://skmtc.dev/ionworks/apis/ionworks-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ionworks/apis/ionworks-api/revisions/abebbbc5f60a?raw)
