# Create workspace invitation

Create an invitation by email with an optional bundle of project grants. Idempotent: returns `200 OK` if a pending invitation for the same recipient already exists.

Endpoint: POST /workspaces/{workspace_id}/invitations
Version: 0.27.5
Security: Auth

## Path parameters:

  - `workspace_id` (string, required)
    Unique identifier (UUID) of the workspace.

## Request fields (application/json):

  - `email` (string, required)
    Email address.
    Example: user@example.com

  - `workspace_role` (string, required)
    Subset of `WorkspaceRole` that can be assigned to a member: `admin` or `member`. `owner` is excluded; it's set when a workspace is created and can't be granted afterwards. Used for invitations and member role changes.
    Enum: "admin", "member"

  - `project_grants` (array)
    Optional project grants to apply when the invitation is accepted.

  - `project_grants.project_id` (string, required)
    Unique identifier (UUID v4).
    Example: 550e8400-e29b-41d4-a716-446655440000

  - `project_grants.role` (string, required)
    Project-level role for a workspace member.
    Enum: "editor", "viewer"

## Response 200 fields (application/json):

  - `item` (object, required)
    A pending offer to join a workspace. An invitation can optionally bundle project grants. The invitee is identified by email because they may not have a Kratos account yet at the time the invitation is created.
    Example: {"id":"0193d4a1-7e02-7d29-a2b3-4c5d6e7f8901","workspace":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Acme Inc","created_at":"2024-01-15T10:30:00Z"},"email":"user@example.com","workspace_role"…

  - `item.id` (string, required)
    Unique identifier (UUID v4).
    Example: 550e8400-e29b-41d4-a716-446655440000

  - `item.workspace` (object, required)
    Basic workspace info used when referencing a workspace from another resource.
    Example: {"id":"550e8400-e29b-41d4-a716-446655440000","name":"Acme Inc","created_at":"2024-01-15T10:30:00Z"}

  - `item.workspace.name` (string, required)
    Human-readable workspace name.
    Example: My Workspace

  - `item.workspace.created_at` (string, required)
    Timestamp when the resource was created. RFC 3339 / ISO 8601, UTC.
    Example: 2024-01-15T10:30:00Z

  - `item.email` (string, required)
    Email address.
    Example: user@example.com

  - `item.workspace_role` (string, required)
    Subset of `WorkspaceRole` that can be assigned to a member: `admin` or `member`. `owner` is excluded; it's set when a workspace is created and can't be granted afterwards. Used for invitations and member role changes.
    Enum: "admin", "member"

  - `item.status` (string, required)
    Current invitation lifecycle status.
    Enum: "pending", "accepted", "declined", "revoked", "expired"

  - `item.expires_at` (string, required)
    Timestamp when the resource expires. RFC 3339 / ISO 8601, UTC. Absent if the resource never expires.
    Example: 2025-01-15T10:30:00Z

  - `item.project_grants` (array, required)
    Project grants to apply when the invitation is accepted. Empty for admins, who receive implicit access to every project.

  - `item.project_grants.project` (object, required)
    Basic project info used when referencing a project from another resource.
    Example: {"id":"0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12","name":"Production","created_at":"2024-01-15T10:30:00Z"}

  - `item.project_grants.project.name` (string, required)
    Human-readable project name.
    Example: Production

  - `item.project_grants.role` (string, required)
    Project-level role for a workspace member.
    Enum: "editor", "viewer"

## Response 201 fields (application/json):

  - `item` (object, required)
    A pending offer to join a workspace. An invitation can optionally bundle project grants. The invitee is identified by email because they may not have a Kratos account yet at the time the invitation is created.
    Example: {"id":"0193d4a1-7e02-7d29-a2b3-4c5d6e7f8901","workspace":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Acme Inc","created_at":"2024-01-15T10:30:00Z"},"email":"user@example.com","workspace_role"…

  - `item.id` (string, required)
    Unique identifier (UUID v4).
    Example: 550e8400-e29b-41d4-a716-446655440000

  - `item.workspace` (object, required)
    Basic workspace info used when referencing a workspace from another resource.
    Example: {"id":"550e8400-e29b-41d4-a716-446655440000","name":"Acme Inc","created_at":"2024-01-15T10:30:00Z"}

  - `item.workspace.name` (string, required)
    Human-readable workspace name.
    Example: My Workspace

  - `item.workspace.created_at` (string, required)
    Timestamp when the resource was created. RFC 3339 / ISO 8601, UTC.
    Example: 2024-01-15T10:30:00Z

  - `item.email` (string, required)
    Email address.
    Example: user@example.com

  - `item.workspace_role` (string, required)
    Subset of `WorkspaceRole` that can be assigned to a member: `admin` or `member`. `owner` is excluded; it's set when a workspace is created and can't be granted afterwards. Used for invitations and member role changes.
    Enum: "admin", "member"

  - `item.status` (string, required)
    Current invitation lifecycle status.
    Enum: "pending", "accepted", "declined", "revoked", "expired"

  - `item.expires_at` (string, required)
    Timestamp when the resource expires. RFC 3339 / ISO 8601, UTC. Absent if the resource never expires.
    Example: 2025-01-15T10:30:00Z

  - `item.project_grants` (array, required)
    Project grants to apply when the invitation is accepted. Empty for admins, who receive implicit access to every project.

  - `item.project_grants.project` (object, required)
    Basic project info used when referencing a project from another resource.
    Example: {"id":"0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12","name":"Production","created_at":"2024-01-15T10:30:00Z"}

  - `item.project_grants.project.name` (string, required)
    Human-readable project name.
    Example: Production

  - `item.project_grants.role` (string, required)
    Project-level role for a workspace member.
    Enum: "editor", "viewer"

## Response 400 fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

  - `fields` (array)
    List of invalid fields in the request

  - `fields.name` (string, required)
    The name of the invalid field
    Example: meta

  - `fields.reason` (string, required)
    Why this field is invalid
    Example: Exceeded maximum data size — must not exceed 1000 characters

## Response 401 fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

## Response 403 fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

## Response 404 fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

## Response 409 fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

## Response 422 fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

  - `fields` (array)
    List of fields that failed precondition validation

  - `fields.name` (string, required)
    The name of the field that failed validation
    Example: status

  - `fields.reason` (string, required)
    Why the precondition failed for this field
    Example: Cannot transition from archived to active state

## Response default fields (application/problem+json):

  - `type` (string, required)
    A URI that identifies the error type.
Open it in a browser to read about this category of error.
    Example: https://docs.vilna.io/apis/problems/internal-error

  - `title` (string, required)
    A short summary of the error type.
Use `detail` for information specific to this occurrence.
    Example: Bad Request

  - `status` (integer, required)
    The HTTP status code for this error.
Matches the status code of the HTTP response.
    Example: 400

  - `detail` (string)
    A human-readable explanation of what went wrong in this specific case.
May be localized.
    Example: The address is already assigned to another invoice

  - `instance` (string)
    A URI that identifies this specific error occurrence.
Include this value when contacting support.
    Example: /errors?id=XXXXXX-xxxxx

  - `code` (string, required)
    Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.
    Example: resource.not_found

