openapi: 3.0.1
info:
  title: User
  description: >
    Manage users, custom roles, groups, and self-registration custom
    fields for a Canto account.
  version: 1.0.0
servers:
  - url: "https://{tenantSubdomain}.{region}/api"
    variables:
      tenantSubdomain:
        default: demo
      region:
        default: canto.com
        enum:
          - canto.com
          - canto.global
          - canto.de
          - au.canto.com
          - ca.canto.com
security:
  - cantoOAuth2: []
  - bearerAuth: []
tags:
  - name: User
    description: Manage users, roles, groups, and self-registration fields.
paths:
  /v1/user:
    get:
      tags:
        - User
      summary: Get current user info
      operationId: get_v1_user
      description: Returns the current user's info -- the user the access token represents.
      responses:
        "200":
          description: The current user's info.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/current_user"
    post:
      tags:
        - User
      summary: Add new user
      operationId: post_v1_user
      description: >
        Adds a new user. Admin only. `roles` accepts admin, contributor,
        consumer, or customRole; `customRoleId` is only used when `roles`
        includes customRole. `allowAccessIndesign` is deprecated in favor
        of `allowAccessAdobeConnector`.


        The new user needs somewhere to go: creating one with no `groups`,
        `allowAccessMainTenant`, or other Portal/Workspace/Style Guide
        access returns a 500 (see below). In practice, always set
        `allowAccessMainTenant: true` unless assigning the user to a
        group or other access explicitly.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [userId, firstName, lastName, roles]
              properties:
                userId:
                  type: string
                  description: The new user's id. Should be their email address.
                firstName:
                  type: string
                lastName:
                  type: string
                roles:
                  type: array
                  items:
                    type: string
                    enum: [admin, contributor, consumer, customRole]
                customRoleId:
                  type: string
                  description: The id of a custom role. Use only when roles includes customRole.
                groups:
                  type: array
                  description: >
                    Optional. Groups the user should be assigned to. See
                    this operation's description for why this (or another
                    source of Portal/Workspace/Style Guide access) is
                    effectively required.
                  items:
                    type: string
                properties:
                  type: object
                  description: Optional. Custom field values, keyed by custom field id.
                  additionalProperties: true
                allowAccessMainTenant:
                  type: boolean
                  description: Whether the user may access the main tenant (as opposed to only a Portal/Workspace/Style Guide they're granted access to).
                allowAccessAdobeConnector:
                  type: boolean
                  default: false
                allowAccessIndesign:
                  type: boolean
                  default: false
                  deprecated: true
                  description: Deprecated old name for allowAccessAdobeConnector.
      responses:
        "200":
          description: The user was created.
        "500":
          description: >
            The request otherwise looked valid but the user could not be
            created -- returned when `groups` is omitted and the account
            grants the new user no other Portal/Workspace/Style Guide
            access.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/error"
              example:
                code: 3217
                message: Please select at least one Portal, Workspace or Style Guide.
    put:
      tags:
        - User
      summary: Update user info
      operationId: put_v1_user
      description: >
        Updates an existing user. Admin only. `email` is required.
        `customRoleId` must only be used when `roles` is customRole.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [userId, email]
              properties:
                userId:
                  type: string
                  description: The id of the user to update.
                firstName:
                  type: string
                lastName:
                  type: string
                email:
                  type: string
                roles:
                  type: array
                  items:
                    type: string
                    enum: [admin, contributor, consumer, customRole]
                customRoleId:
                  type: string
                groups:
                  type: array
                  description: Optional.
                  items:
                    type: string
                properties:
                  type: object
                  description: Optional. Custom field values, keyed by custom field id.
                  additionalProperties: true
                allowAccessMainTenant:
                  type: boolean
                  description: Whether the user may access the main tenant (as opposed to only a Portal/Workspace/Style Guide they're granted access to).
                allowAccessAdobeConnector:
                  type: boolean
                  default: false
                allowAccessIndesign:
                  type: boolean
                  default: false
                  deprecated: true
      responses:
        "200":
          description: The user was updated.
        "404":
          description: No user exists with the given `userId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/error"
              example:
                code: 2301
                message: The user "someone@example.com" does not exist.
  /v1/roles:
    get:
      tags:
        - User
      summary: Get custom roles
      operationId: get_v1_roles
      description: Returns the account's custom roles.
      responses:
        "200":
          description: The account's custom roles.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/named_ref"
              example:
                - id: <role-id>
                  name: Role A
                - id: <role-id>
                  name: Role B
  /v1/users/fields:
    get:
      tags:
        - User
      summary: Get user custom fields
      operationId: get_v1_users_fields
      description: >
        Returns the custom fields used in self-registration, configured in
        the Canto UI under Settings > Users & Groups > Self Registration >
        Form.
      responses:
        "200":
          description: The self-registration custom fields.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/user_custom_field"
  /v1/user/accounts:
    get:
      tags:
        - User
      summary: Get user list
      operationId: get_v1_user_accounts
      description: >
        Returns a paginated list of users in the account. For more
        detailed user information, use Get user list (with extended
        information) instead.
      parameters:
        - name: name
          in: query
          required: false
          description: Find users whose first or last name starts with this value.
          schema:
            type: string
        - name: include-group
          in: query
          required: false
          description: If true, includes each user's groups.
          schema:
            type: boolean
            default: false
        - name: page-size
          in: query
          required: false
          schema:
            type: integer
            default: 100
        - name: page
          in: query
          required: false
          schema:
            type: integer
            default: 1
      responses:
        "200":
          description: A page of users.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/user_accounts_page"
  /v1/users:
    get:
      tags:
        - User
      summary: Get user list (with extended information)
      operationId: get_v1_users
      description: >
        Returns a paginated list of users in the account, with extended
        detail (role, groups, granted portal/workspace/style-guide info,
        and custom field values) beyond what Get user list returns.
      parameters:
        - name: role
          in: query
          required: false
          description: >
            0 all roles, 1 admin, 2 contributor, 3 consumer, 4 admin and
            contributor, 5 contributor and consumer.
          schema:
            type: integer
            enum: [0, 1, 2, 3, 4, 5]
            default: 0
        - name: name
          in: query
          required: false
          description: Find users whose first name, last name, or email starts with this value.
          schema:
            type: string
        - name: include-group
          in: query
          required: false
          schema:
            type: boolean
            default: false
        - name: include-portal
          in: query
          required: false
          description: If true, includes each user's granted portal/workspace/style guide info.
          schema:
            type: boolean
            default: false
        - name: page-size
          in: query
          required: false
          schema:
            type: integer
            default: 100
        - name: page
          in: query
          required: false
          schema:
            type: integer
            default: 1
        - name: customfield
          in: query
          required: false
          description: >
            Whether to query by custom field, used together with the name
            parameter.
          schema:
            type: boolean
      responses:
        "200":
          description: A page of users with extended detail.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/users_extended_page"
  /v1/user/{userId}:
    delete:
      tags:
        - User
      summary: Delete a user
      operationId: delete_v1_user_userId
      description: Deletes an existing user. Admin only.
      parameters:
        - name: userId
          in: path
          required: true
          description: The id of the user to delete.
          schema:
            type: string
      responses:
        "200":
          description: The user was deleted.
        "404":
          description: No user exists with the given `userId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/error"
              example:
                code: 2301
                message: The user "someone@example.com" does not exist.
  /v1/groups:
    get:
      tags:
        - User
      summary: Get groups
      operationId: get_v1_groups
      description: Returns a list of all groups.
      responses:
        "200":
          description: The account's groups.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/named_ref"
              example:
                - id: <group-id>
                  name: Group A
                - id: <group-id>
                  name: Group B
    post:
      tags:
        - User
      summary: Add group
      operationId: post_v1_groups
      description: Creates a new group.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name:
                  type: string
                userIds:
                  type: array
                  items:
                    type: string
                description:
                  type: string
      responses:
        "201":
          description: The group was created.
  /v1/groups/{groupId}:
    get:
      tags:
        - User
      summary: Get group info with users
      operationId: get_v1_groups_groupId
      description: Returns a group's info along with its member user ids.
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The group's info and members.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/group_with_users_response"
    put:
      tags:
        - User
      summary: Update group
      operationId: put_v1_groups_groupId
      description: Updates an existing group.
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [id, name]
              properties:
                id:
                  type: string
                name:
                  type: string
                description:
                  type: string
      responses:
        "200":
          description: The group was updated.
    delete:
      tags:
        - User
      summary: Delete group
      operationId: delete_v1_groups_groupId
      description: Deletes an existing group.
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The group was deleted.
  /v1/groups/{groupId}/users:
    post:
      tags:
        - User
      summary: Add users to group
      operationId: post_v1_groups_groupId_users
      description: Adds users to a group.
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
              description: User ids (emails) to add.
      responses:
        "200":
          description: The literal text "success" on completion.
          content:
            text/plain:
              schema:
                type: string
              example: success
        "404":
          description: A referenced user does not exist.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/error"
              example:
                code: 2301
                message: The user "<user-id>" does not exist.
    delete:
      tags:
        - User
      summary: Delete users from group
      operationId: delete_v1_groups_groupId_users
      description: Removes users from a group.
      parameters:
        - name: groupId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
              description: User ids (emails) to remove.
      responses:
        "200":
          description: The users were removed.
  /v2/users/$query:
    post:
      tags:
        - User
      summary: Get Users
      operationId: post_v2_users_query
      description: >
        Returns users matching the given user ids, using an OData `$filter`
        expression in the request body (e.g. `$filter=userId in
        ('a@example.com','b@example.com')`). Max 100 user ids per request.
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
              example: "$filter=userId in ('a@example.com','b@example.com')"
      responses:
        "200":
          description: The matching users, in OData response format.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/odata_users_response"
        "400":
          description: The number of user ids was outside the allowed 1-100 range.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/odata_error"
              example:
                error:
                  code: null
                  message: The number of parameter userId ranges from 1 to 100
        "405":
          description: The $filter expression was empty.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/odata_error"
              example:
                error:
                  code: null
                  message: Filter is not allowed to be empty
components:
  securitySchemes:
    cantoOAuth2:
      type: oauth2
      description: >
        Authorize against your own Canto account. Choose the tenant and its
        region in the portal first; the portal fills in the application
        identifier for that region and pre-fills your account name on
        Canto's sign-in page. This is a public-client PKCE flow: no client
        secret is used, and none is held by the portal.
      flows:
        authorizationCode:
          authorizationUrl: https://oauth.canto.com/oauth/api/oauth2/universal2/authorize
          tokenUrl: https://oauth.canto.com/oauth/api/oauth2/universal2/token
          scopes: {}
          x-usePkce: plain
          x-tokenName: accessToken
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: AccessToken
      description: >
        Paste a Target-API OAuth Token obtained out-of-band. Use the
        Authorize button instead to obtain one interactively.
  schemas:
    named_ref:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
    current_user:
      type: object
      properties:
        permissions:
          type: array
          items:
            type: string
        userId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        lastAccessVersion:
          type: string
        name:
          type: string
        allowAccessAdobeConnector:
          type: boolean
    user_custom_field:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        type:
          type: string
          enum: [TEXT, NUMBER, CHOICE, MULTICHOICE, DATETIME]
        options:
          type: array
          items:
            type: string
        required:
          type: boolean
    user_account:
      type: object
      properties:
        userId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        displayName:
          type: string
        groups:
          type: array
          items:
            $ref: "#/components/schemas/named_ref"
    user_accounts_page:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/user_account"
        currentPage:
          type: integer
        pageSize:
          type: integer
        totalCount:
          type: integer
    user_extended:
      type: object
      properties:
        role:
          type: string
          enum: [Admin, Contributor, Consumer]
        userId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        allowAccessMainLibrary:
          type: boolean
        groups:
          type: array
          items:
            $ref: "#/components/schemas/named_ref"
        properties:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              value:
                description: A string, or an array of strings for MULTICHOICE fields.
    users_extended_page:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/user_extended"
    group_with_users:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        userids:
          type: array
          items:
            type: string
    group_with_users_response:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
        data:
          $ref: "#/components/schemas/group_with_users"
    odata_user:
      type: object
      properties:
        userId:
          type: string
        name:
          type: string
    odata_users_response:
      type: object
      properties:
        "@odata.context":
          type: string
        value:
          type: array
          items:
            $ref: "#/components/schemas/odata_user"
    odata_error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              nullable: true
            message:
              type: string
