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

# Invite user to the company

> The API does not create users directly. People join the company by invitation, because they
set their own password. The membership starts as pending (`approved: false`) and becomes active
when the person accepts the invitation by email.

If the email already has an account in the system, the invitation only links that account to the company.

The token needs the `users: POST` permission. The invitation is recorded in the name of the
admin who created the token.

Available only on self-service installations. On other installations, the response is
`403 ERR_SELF_SERVICE_DISABLED`.



## OpenAPI

````yaml /api-reference/openapi.en.yaml post /users/invites
openapi: 3.0.3
info:
  title: Connecta DESK Public API
  version: 1.0.0
  description: >-
    Public API of Connecta DESK, available at `/api/v1`. Access uses a token
    generated in the tokens module. Each token has permissions per **module ×
    method**, and every list read is paginated.


    ## Authentication


    ```

    Authorization: Bearer sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

    ```


    The token belongs to a **company**, not to a user. The company used is
    always the token's company, so sending `companyId` in the body has no
    effect. A missing, invalid, revoked or expired token gets the same `401`
    response.


    ## Order of checks


    1. **token** → `401`

    2. **active company** → `403`

    3. **API enabled on the plan** → `403 ERR_API_NOT_ENABLED` (does not apply
    to on-premise)

    4. **company rate limit** → `429`

    5. **token permission** → `403 ERR_API_FORBIDDEN_SCOPE`


    ## User ids


    Every user id in the API is the user's id **in this company**, the same one
    `GET /users` returns. This applies to what the API returns (`user.id`,
    `assignedTo.id`, `userCreated.id`) and to what it accepts (`userId`,
    `userIds`, `assignedToUserId` and the `{id}` in user routes).


    The same person can work in several companies, with a different name and
    profile in each one, and has a different id in each company.


    An id that does not belong to this company returns `404`, with the same
    message as an id that does not exist.


    ## Pagination


    Every list `GET` is paginated. The `meta` contains only `page`, `perPage`
    and `hasMore`, without the total number of records. To go through
    everything, keep advancing `page` while `hasMore` is `true`.


    ## Idempotency


    Optional on `POST`/`PUT`, through the `Idempotency-Key` header. If you
    repeat the call with the same key and the same body, you get the stored
    response (with `Idempotent-Replay: true`). With the same key and a different
    body, the response is `409`.
servers:
  - url: https://api.connectadesk.com/api/v1
    description: Production
security:
  - apiToken: []
tags:
  - name: contacts
    description: Contact records, extra fields and marketing source.
  - name: tickets
    x-displayName: Tickets
    description: Opening, transferring, closing and wrap-up of tickets.
  - name: messages
    description: Asynchronous sending and reading of messages.
  - name: tags
    description: Tags and their link to tickets.
  - name: queues
    description: Service queues and their agents.
  - name: wrapups
    description: Wrap-up types.
  - name: users
    description: Agents and administrators.
  - name: schedules
    description: Scheduled messages.
  - name: quick-messages
    description: Quick replies.
  - name: campaigns
    description: Bulk sending.
  - name: crm
    description: Boards, stages, cards and metrics.
  - name: channels
    description: Channels (read only).
  - name: reports
    description: Reports and dashboards.
  - name: products
    description: Product catalog, categories and sales performance.
  - name: custom-fields
    description: Custom fields for contacts and cards, plus company-wide global variables.
  - name: profiles
    description: Company permission profiles (read only).
  - name: webchat
    description: >-
      Native webchat from your own system: open a visitor session, send and read
      messages. The token needs the `webchat` scope (GET and POST).
paths:
  /users/invites:
    post:
      tags:
        - users
      summary: Invite user to the company
      description: >-
        The API does not create users directly. People join the company by
        invitation, because they

        set their own password. The membership starts as pending (`approved:
        false`) and becomes active

        when the person accepts the invitation by email.


        If the email already has an account in the system, the invitation only
        links that account to the company.


        The token needs the `users: POST` permission. The invitation is recorded
        in the name of the

        admin who created the token.


        Available only on self-service installations. On other installations,
        the response is

        `403 ERR_SELF_SERVICE_DISABLED`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                  description: Email of the person who will receive the invitation.
                  example: marina@exemplo.com.br
                profileId:
                  type: integer
                  description: >-
                    Permission profile of this person in this company. Use the
                    `id` from `GET /profiles`.


                    An id that does not belong to this company returns `422
                    ERR_API_PROFILE_NOT_FOUND`.
                  example: 21
                profile:
                  type: string
                  enum:
                    - admin
                    - user
                  deprecated: true
                  description: >-
                    Legacy way to choose the profile, kept for integrations that
                    already use it. Prefer `profileId`.


                    | value | meaning |

                    | --- | --- |

                    | `admin` | The company's default **Admin** profile. |

                    | `user` | The company's default **Agent** profile. |


                    If `profileId` is also sent, `profileId` wins. With neither,
                    the person joins as **Agent**.
                name:
                  type: string
                  description: >-
                    Name shown in the company. If not sent, the account name is
                    used.
                  example: Gabriel Goulart
                queueIds:
                  type: array
                  items:
                    type: integer
                  description: Queues the person will work in.
                  example:
                    - 7
                channelsIds:
                  type: array
                  items:
                    type: integer
                  description: Channels the person can see.
                  example:
                    - 4
                maxOpenTickets:
                  type: integer
                  description: >-
                    Maximum number of simultaneous tickets. If not sent, there
                    is no limit.
                  example: 5
                language:
                  type: string
                  enum:
                    - pt-BR
                    - en-US
                  description: |-
                    Language of the invitation email sent to the person:

                    | value | meaning |
                    | --- | --- |
                    | `pt-BR` | Brazilian Portuguese. |
                    | `en-US` | English. |
      responses:
        '201':
          description: >-
            Invitation sent. Returns the newly created membership, in the same
            format as

            `GET /users/{id}`, with `approved: false` until the person accepts
            the invitation by email. The `id`

            returned is already the membership id and can be used in the next
            calls.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/BadRequest'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
components:
  schemas:
    User:
      type: object
      description: >-
        User from the **company's** point of view. The `id` is the user's id in
        this company, and the `email` belongs to the person's account. Name,
        profile, activation, presence and ticket limit are set per company, so
        the same user can have different values in each company.


        Super admin accounts never appear.
      properties:
        id:
          type: integer
          description: >-
            User id in this company. The same person has a different id in each
            company they work in.
        email:
          type: string
          example: marina@exemplo.com.br
        name:
          type: string
          nullable: true
          description: Display name in this company.
        profile:
          type: object
          nullable: true
          description: >-
            Permission profile of this person in this company. What each profile
            allows is in `GET /profiles`.


            It is `null` for the company owner (`isOwner: true`), who has access
            to everything and does not depend on a profile.
          properties:
            id:
              type: integer
              description: Profile id, the same as in `GET /profiles`.
              example: 21
            name:
              type: string
              example: Atendente
        isOwner:
          type: boolean
          description: >-
            `true` for the company owner. The owner has access to everything,
            and the profile does not apply.
        active:
          type: boolean
          description: Access is active in this company.
        online:
          type: boolean
        approved:
          type: boolean
          description: '`false` when the invitation was sent and has not been accepted yet.'
        lastLogin:
          type: string
          format: date-time
          nullable: true
        maxOpenTickets:
          type: integer
          nullable: true
          example: 5
        queues:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
              name:
                type: string
                description: Display name.
          example:
            - 7
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      example:
        id: 3
        email: gabriel@exemplo.com.br
        name: Gabriel Goulart
        profile:
          id: 20
          name: Admin
        isOwner: false
        active: true
        online: true
        approved: true
        maxOpenTickets: 15
        lastLogin: '2026-08-19T08:12:00.000Z'
        queues:
          - id: 13
            name: Comercial
        createdAt: '2026-01-08T12:00:00.000Z'
        updatedAt: '2026-08-19T08:30:00.000Z'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Fixed error code, so your system can handle each case.
              example: ERR_API_FORBIDDEN_SCOPE
            message:
              type: string
            details: {}
  responses:
    BadRequest:
      description: Invalid request body.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ERR_API_VALIDATION
              message: O campo `number` é obrigatório.
    UnprocessableEntity:
      description: >-
        The body is well formed, but a required field is missing or a value is
        not accepted. For example, `application` other than `contact`/`card`, an
        empty `orderedIds` or a blank `name`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ERR_API_VALIDATION
              message: >-
                O parâmetro `application` é obrigatório e aceita "contact" ou
                "card".
  securitySchemes:
    apiToken:
      type: http
      scheme: bearer
      description: API token in the `sk_live_…` format.

````

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