openapi: 3.0.0
info:
  version: 1.0.0
  title: Shift72 Users API
servers:
  - url: https://{siteUrl}
    variables:
      siteUrl:
        default: vod.shift72.com
        description: Url to your Shift72 site
tags:
  - name: Auth
    description: |
      APIs for authenticating users
paths:
  /services/users/v2/auth/session:
    get:
      operationId: postAuthSessionV2
      summary: Create Auth Session
      description: |
        Creates an auth session on a user's behalf. This can match, create and
        update the user, similar to the way OAuth signin
        works.

        This is intended for auth integration scenarios where you need to find or
        create users, then issue them a login.

        #### API Key permissions

        Using this API requires a specific limited-permissions key with the
        `users:auth:session` permission. Talk to your account manager about getting
        an API key role set up if you need this API.

        #### Matching users

        This API can be used to sign in a specific Shift72 user, or to match them
        based on an email or external id claim.

        Users can be resolved by:
          - providing a specific user_id. This will prevent any other matching.
          - by external id
          - by email (provided you tell us it's trustworthy)

        To allow matching by email, you need to have verified the user actually owns
        the email address to prevent account takeovers.

        #### Creating users

        This API can be used to create the user if it doesn't exist. If you pass
        `"create_user": true`, and provide an email and name we'll try to create the 
        user if it doesn't exist.

        Required parameters:
          - `email`
          - `name`

        #### Updating users

        If a user is matched, we'll attempt to update their information (name,
        email, birthdate, gender) if that info is provided.

        Fields that may be updated:

          - `email`, if matched by user_id or external_id and the email is verified.
          - `external_id`, if the user's existing external id is blank
          - `name`
          - `gender`
          - `birthdate`

        #### Auth session permissions

        In future, this API may be changed to only issue unprivileged user sessions
        — e.g. an admin user authorized this way would be treated as a normal user.

        #### Error codes

         - `validation_error`: a parameter was not in the required format
         - `missing_parameters`: not enough info was provided to match a user
         - `invalid_parameters`: an invalid combination of parameters was provided.
         - `user_not_found`: a user couldn't be found, and creation was not enabled/possible
         - `user_account_suspended`: the user's status is not set to active
         - `create_user_failed`: there was some issue creating the user
         - `update_user_failed`: there was some issue updating the user details
      tags:
        - Auth
      security:
        - ApiKey:
            - Api Auth Role
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                user_id:
                  type: number
                  nullable: true
                  description: 'The Shift72 user ID. If provided, this will override any matching by external id or email. If provided, it''s invalid to pass `create_user: true`'
                external_id:
                  type: string
                  description: An external ID to try and match the user by.
                email:
                  type: string
                  description: The user's email address.
                  format: email
                email_verified:
                  type: boolean
                  description: Whether you've verified the user actually owns this email. This claim will allow matching by, and updating the user's email address.
                create_user:
                  type: boolean
                  description: If set to true, create the user if a match isn't found.
                  default: false
                expiry:
                  description: How long should this session last? By default, this will be around 4 hours, but may extend if the token is being actively used.
                  oneOf:
                    - type: number
                      description: Length of session in seconds, e.g. 14400 for a 4-hour session
                    - type: string
                      format: date-time
                      description: Expiry of the session, as a future timestamp
                name:
                  type: string
                  description: The user's name
                birthdate:
                  type: string
                  nullable: true
                  description: The user's birthdate. If provided, this will update their date of birth (used for parental controls and demographic reporting)
                  format: date
                gender:
                  type: string
                  nullable: true
                  description: The user's gender. If provided, the user's profile will be updated to match. This is used for demographic reporting.
                  enum:
                    - male
                    - female
                    - other
                    - diverse
            examples:
              Logging in a specific Shift72 User:
                description: This creates a session for a specific Shift72 user, and will not update any details about their account.
                value:
                  user_id: 123456
                  expiry: '2025-09-01T00:00:00.000Z'
              Matching a user by external id or email:
                description: This will try and match an account first by external_id, then by email because we claim it's a verified email address. If a match is found, the user details will be updated.
                value:
                  external_id: e63e7e670d526bccd9dc37928b66c969
                  email: test@example.com
                  name: Test User
                  email_verified: true
                  expiry: '2025-09-01T00:00:00.000Z'
              Matching a user by external id, with an unverified email:
                description: This will only attempt to match by external id, because the email is not verified.
                value:
                  external_id: e63e7e670d526bccd9dc37928b66c969
                  email: test@example.com
                  name: Test User
                  email_verified: false
                  expiry: '2025-09-01T00:00:00.000Z'
              Creating an account if it doesn't exist:
                description: If a match isn't found the account will be created.
                value:
                  external_id: e63e7e670d526bccd9dc37928b66c969
                  email: test@example.com
                  name: Test User
                  create_user: true
                  email_verified: true
                  expiry: '2025-09-01T00:00:00.000Z'
              Passing additional demographic details:
                description: If an account is matched or created, the birthdate and gender will also be updated
                value:
                  external_id: e63e7e670d526bccd9dc37928b66c969
                  email: orson@welles.com
                  name: Orson Welles
                  create_user: true
                  email_verified: true
                  expiry: '2025-09-01T00:00:00.000Z'
                  gender: male
                  birthdate: '1915-05-06'
      responses:
        '200':
          $ref: '#/components/responses/AuthSessionResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/ApiErrorResponse'
        '422':
          $ref: '#/components/responses/ApiErrorResponse'
components:
  securitySchemes:
    AuthToken:
      type: apiKey
      in: header
      name: X-Auth-Token
      description: A user auth token or API key.
    AdminAuthToken:
      type: apiKey
      in: header
      name: X-Auth-Token
      description: A user with the admin role
    ApiKey:
      type: apiKey
      in: header
      name: X-Auth-Token
      description: An API key. This may need specific permissions, documented in the endpoint
  responses:
    AuthSessionResponse:
      description: |
        A user's auth token and details about their account
      content:
        application/json:
          schema:
            type: object
            properties:
              auth_token:
                type: string
                description: An auth token that can be used with the `X-Auth-Token` header.
              account:
                type: object
                properties:
                  user_id:
                    type: number
                    description: The Shift72 user's ID
                  name:
                    type: string
                    description: The user's name
                  email:
                    type: string
                    description: The user's name
                  dob:
                    type: string
                    nullable: true
                    description: The user's date of birth (YYYY-MM-DD)
                  gender:
                    type: string
                    nullable: true
                    description: The user's gender
                    enum:
                      - male
                      - female
                      - other
                      - diverse
                  bypass_cache:
                    type: boolean
                    description: 'If true, apps should add the `X-Bypass-Cache: 1` header to avoid cached responses. This usually means the user has some level of admin access'
                  permissions:
                    type: object
                    description: The user's permissions. If they're an admin user this will be populated.
    UnauthorizedError:
      description: Auth token or API key is missing or invalid
    ApiErrorResponse:
      description: A JSON API error
      content:
        application/json:
          schema:
            type: object
            properties:
              code:
                description: A keyed error code
                type: string
              error:
                description: Error message
                type: string
