openapi: 3.0.1
info:
  title: Authorization
  description: >
    OAuth 2.0 endpoints used to obtain and refresh the Target-API OAuth Token
    that authorizes every other Canto API request. Every third-party app
    needs an App ID and App Secret, issued by Canto, to use these endpoints.


    **Canto OAuth domain.** Choose the OAuth base URL matching your tenant's
    region: `https://oauth.canto.com`, `https://oauth.canto.global`,
    `https://oauth.canto.de`, or `https://oauth.ca.canto.com`.


    **Getting an authorization code (grant_type=authorization_code).** Open
    `{oauthBaseUrl}/oauth/api/oauth2/authorize?response_type=code&app_id={appId}&redirect_uri={redirectUri}&state={state}`
    in a browser. Enter your Canto account URL, then your username and
    password. Canto then asks whether to authorize the app; on agreeing,
    Canto redirects to `redirect_uri` with a `code` query parameter (valid
    for 1 hour) and the original `state` value, which the caller must
    validate matches before exchanging the code for a token.
  version: 1.0.0
servers:
  - url: "https://oauth.{region}"
    variables:
      region:
        default: canto.com
        enum:
          - canto.com
          - canto.global
          - canto.de
          - au.canto.com
          - ca.canto.com
tags:
  - name: Authorization
    description: Obtain and refresh OAuth 2.0 access tokens.
paths:
  /oauth/api/oauth2/compatible/token:
    post:
      tags:
        - Authorization
      summary: Obtain Access Token / Refresh Token
      operationId: post_oauth_api_oauth2_compatible_token
      description: >
        Exchanges an App ID/App Secret pair -- together with an
        authorization code, a refresh token, or nothing else (for
        `client_credentials`) -- for an access token. This is the current,
        RFC-conformant response shape (snake_case field names); see also the
        deprecated `/oauth/api/oauth2/token` operation, which returns the
        same data in an older, non-RFC field-naming convention.


        The returned access token is valid for 30 days. A refresh token is
        valid for 365 days; using it returns a new refresh token and
        invalidates the old one. `client_credentials` grants never return a
        refresh token -- request a new access token the same way once the
        current one expires.
      parameters:
        - name: app_id
          in: query
          required: true
          description: Your App identifier, issued by Canto.
          schema:
            type: string
        - name: app_secret
          in: query
          required: true
          description: Your App Secret, issued by Canto.
          schema:
            type: string
        - name: grant_type
          in: query
          required: true
          description: >
            The OAuth grant type. `client_credentials` never returns a
            refresh token; if the token expires, request a new one the same
            way. `authorization_code` and `refresh_token` each require the
            corresponding `code` or `refresh_token` parameter below.
          schema:
            type: string
            enum:
              - authorization_code
              - client_credentials
              - refresh_token
        - name: redirect_uri
          in: query
          required: false
          description: >
            The third-party redirect URL. If omitted, Canto uses the value
            from the app's own settings; if present, it must match the
            app's configured redirect URI exactly.
          schema:
            type: string
        - name: code
          in: query
          required: false
          description: >
            Required when grant_type is authorization_code. The
            authorization code obtained from the Canto OAuth page (see the
            Authorization description).
          schema:
            type: string
        - name: refresh_token
          in: query
          required: false
          description: >
            Required when grant_type is refresh_token. The refresh token
            returned by a previous call to this operation. Valid for 365
            days; using it invalidates the previous refresh token.
          schema:
            type: string
        - name: scope
          in: query
          required: false
          description: >
            Only supported in client_credentials mode. The scope of the
            user to log in as. At least one user must exist in the given
            scope, or login fails; cannot be combined with user_id. When
            used, the first user (alphabetically) in that scope is
            logged in -- using user_id instead is recommended.
          schema:
            type: string
            enum:
              - admin
              - contributor
              - consumer
            default: admin
        - name: user_id
          in: query
          required: false
          description: The user ID of the user to log in as.
          schema:
            type: string
      responses:
        "200":
          description: >
            Access token issued. `refresh_token` is null for a
            client_credentials grant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/access_token"
              examples:
                client_credentials:
                  summary: client_credentials grant (no refresh token)
                  value:
                    access_token: "<access-token>"
                    expires_in: "2592000"
                    token_type: Bearer
                    refresh_token: null
                authorization_code:
                  summary: authorization_code grant
                  value:
                    access_token: "<access-token>"
                    expires_in: "2592000"
                    token_type: Bearer
                    refresh_token: "<refresh-token>"
                refresh_token:
                  summary: refresh_token grant
                  value:
                    access_token: "<access-token>"
                    expires_in: "2592000"
                    token_type: Bearer
                    refresh_token: "<new-refresh-token>"
        "400":
          description: The request was invalid, e.g. an unsupported grant_type or refresh_token value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauth_error"
              examples:
                wrongGrantType:
                  summary: Wrong grant_type value
                  value:
                    error_description: Wrong grant_type value
                    error: invalid_request
                wrongRefreshToken:
                  summary: Wrong refresh token value
                  value:
                    error_description: Wrong refresh token value
                    error: invalid_request
        "401":
          description: The supplied authorization code was invalid or expired.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauth_error"
              example:
                error_description: Invalid authentication code
                error: authentication_fail
  /oauth/api/oauth2/token:
    post:
      tags:
        - Authorization
      summary: Obtain Access Token / Refresh Token (deprecated, non-RFC field names)
      operationId: post_oauth_api_oauth2_token
      description: >
        Deprecated predecessor to `/oauth/api/oauth2/compatible/token`. Same
        grants and parameters, but the response uses non-RFC-conformant
        camelCase field names (`accessToken`, `tokenType`, `refreshToken`,
        `expiresIn`) instead of the standard snake_case ones. Prefer
        `/oauth/api/oauth2/compatible/token` for new integrations.
      parameters:
        - name: app_id
          in: query
          required: true
          description: Your App identifier, issued by Canto.
          schema:
            type: string
        - name: app_secret
          in: query
          required: true
          description: Your App Secret, issued by Canto.
          schema:
            type: string
        - name: grant_type
          in: query
          required: true
          description: See the corresponding parameter on `/oauth/api/oauth2/compatible/token`.
          schema:
            type: string
            enum:
              - authorization_code
              - client_credentials
              - refresh_token
        - name: redirect_uri
          in: query
          required: false
          description: See the corresponding parameter on `/oauth/api/oauth2/compatible/token`.
          schema:
            type: string
        - name: code
          in: query
          required: false
          description: Required when grant_type is authorization_code.
          schema:
            type: string
        - name: refresh_token
          in: query
          required: false
          description: Required when grant_type is refresh_token.
          schema:
            type: string
        - name: scope
          in: query
          required: false
          description: See the corresponding parameter on `/oauth/api/oauth2/compatible/token`.
          schema:
            type: string
            enum:
              - admin
              - contributor
              - consumer
            default: admin
        - name: user_id
          in: query
          required: false
          description: The user ID of the user to log in as.
          schema:
            type: string
      responses:
        "200":
          description: Access token issued, in the deprecated camelCase field-naming convention.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/access_token_legacy"
              examples:
                client_credentials:
                  summary: client_credentials grant (no refresh token)
                  value:
                    accessToken: "<access-token>"
                    expiresIn: "2592000"
                    tokenType: Bearer
                    refreshToken: null
                authorization_code:
                  summary: authorization_code grant
                  value:
                    accessToken: "<access-token>"
                    expiresIn: "2592000"
                    tokenType: Bearer
                    refreshToken: "<refresh-token>"
                refresh_token:
                  summary: refresh_token grant
                  value:
                    accessToken: "<access-token>"
                    expiresIn: "2592000"
                    tokenType: Bearer
                    refreshToken: "<new-refresh-token>"
        "400":
          description: The request was invalid, e.g. an unsupported grant_type or refresh_token value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauth_error"
              examples:
                wrongGrantType:
                  summary: Wrong grant_type value
                  value:
                    error_description: Wrong grant_type value
                    error: invalid_request
                wrongRefreshToken:
                  summary: Wrong refresh token value
                  value:
                    error_description: Wrong refresh token value
                    error: invalid_request
        "401":
          description: The supplied authorization code was invalid or expired.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauth_error"
              example:
                error_description: Invalid authentication code
                error: authentication_fail
  /oauth/api/oauth/tenant/{refreshToken}:
    get:
      tags:
        - Authorization
      summary: Get Canto Account Name
      operationId: get_oauth_api_oauth_tenant_refreshToken
      description: >
        Returns the Canto account (tenant) name that a given refresh token
        is connected to -- useful when an integration holds a refresh token
        but needs to confirm which account it belongs to.


        Note: this operation's own recorded example responses reference an
        older path, `/api/oauth/tenant/{refreshToken}` (missing the
        `oauth/` prefix present on the currently configured request path
        used here). This is a real inconsistency in Canto's own published
        collection, not a transcription error introduced during this
        conversion; the path documented here is the current one.
      parameters:
        - name: refreshToken
          in: path
          required: true
          description: A valid refresh token.
          schema:
            type: string
      responses:
        "200":
          description: The Canto account (tenant) name, as plain text.
          content:
            text/plain:
              schema:
                type: string
              example: "<account-name>"
        "401":
          description: The supplied refresh token was invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/oauth_error"
              example:
                error_description: Invalid refresh token
                error: authentication_fail
components:
  schemas:
    access_token:
      type: object
      properties:
        access_token:
          type: string
        expires_in:
          type: string
          description: Token lifetime in seconds, as a string.
        token_type:
          type: string
          example: Bearer
        refresh_token:
          type: string
          nullable: true
          description: Null for a client_credentials grant.
    access_token_legacy:
      type: object
      description: Deprecated camelCase equivalent of access_token, returned by /oauth/api/oauth2/token.
      properties:
        accessToken:
          type: string
        expiresIn:
          type: string
          description: Token lifetime in seconds, as a string.
        tokenType:
          type: string
          example: Bearer
        refreshToken:
          type: string
          nullable: true
          description: Null for a client_credentials grant.
    oauth_error:
      type: object
      properties:
        error:
          type: string
        error_description:
          type: string
