openapi: 3.0.1
info:
    title: PictureTasks API
    version: 1.0.1
    termsOfService: https://www.picturetasks.net/tnc
    description: |
        Interface for the mobile app
    contact:
        name: AKI innovations IT
        url: https://aki-innovations.net
        email: support@aki-innovations.net
        
servers:    
    - url: https://api.picturetasks.net/
      description: "Online Live Environment"
      
paths:
    /login/apple/implicit/:
        post:
            summary: Sign In with Apple ID
            tags:
                - Accounts
            description: |
                Implicit OIDC flow:
                Takes a signed JWT identity token and verifies it.        

                - If the account is an existing one, the user is logged in and the session
                is tied to the current user.        
                - If the account does not exist, it is being created on the fly and the user
                is again logged in like before.

                The call will accept firstname, lastname and middlename parameters as well as
                an email parameter. Those values are optional an _MAY_ be provided to be stored 
                in the user's account. However, this data is just visible to the user himself to
                identify him as being the right owner of the account (if he wants to verify it).

            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            type: object
                            properties:
                                sid:
                                    type: string
                                    format: uuid
                                    pattern: ^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$
                                    description: |
                                        The session id returned by `/session/start`
                                key:
                                    type: string
                                    format: byte
                                    pattern: ^(?:[a-zA-Z0-9\+\/]{4})*(?:[a-zA-Z0-9\+\/]{4}|[a-zA-Z0-9\+\/]{3}=|[a-zA-Z0-9\+\/]{2}==)$
                                    description: |
                                        The session key retrieved from the initial call to `/session/start` 
                                jwt:
                                    type: string
                                    format: byte
                                    pattern: ^(?:[a-zA-Z0-9\+\/]{4})*(?:[a-zA-Z0-9\+\/]{4}|[a-zA-Z0-9\+\/]{3}=|[a-zA-Z0-9\+\/]{2}==)$
                                    description: |
                                        The identity token
                                email:
                                    type: string
                                    description: |
                                        The user's email address
                                firstName:
                                    type: string
                                    description: |
                                        The user's given name
                                lastName:
                                    type: string
                                    description: |
                                        The user's family name
                                middleNames:
                                    type: string
                                    description: |
                                        The user's additional given names
                            additionalProperties: false
                            required:
                                - sid
                                - jwt

            responses:
                '200':
                    description: |
                        The login succeeded
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    uid:
                                        type: string
                                        format: uuid
                                        description: |
                                            The user id as generated in our systems
                                    aid:
                                        type: string
                                        description: |
                                            The user's friendly unique id. Will be displayed to the user
                                    newUser:
                                        type: boolean
                                        description: |
                                            True, if the user has been seen for the first time
                                            and therefore a new account has just been created
                                    email:
                                        type: string
                                        description: |
                                            The user's email address
                                    firstName:
                                        type: string
                                        description: |
                                            The user's given name
                                    lastName:
                                        type: string
                                        description: |
                                            The user's family name
                                    middleNames:
                                        type: string
                                        description: |
                                            The user's additional given names
                                additionalProperties: false
                                required:
                                    - uid
                                    - newUser                            

                '400':
                    $ref: '#/components/responses/Error400'
                '401':
                    $ref: '#/components/responses/Error401'
                '403':
                    $ref: '#/components/responses/Error403'

    /session/start/:
        post:
            summary: Start a new session
            tags:
                - Session
            description: |
                Starts a new session. Unless stored session information is available, this
                is the first call that should be made against the API because nearly all other
                calls require a session id (for an alive session).

                If there is stored session information available when starting up, first
                call `/session/heartbeat` to revive that session (which might fail, so you
                might end up calling `/session/start` eventually anyway).

            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            type: object
                            properties:
                                clientType:
                                    type: string
                                    pattern: ^(ios|android|web)$
                                    description: |
                                        The client type for the app making the request
                                did:
                                    type: string
                                    format: uuid
                                    pattern: ^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$
                                    description: |                            
                                        The unique device id generated on app installation
                                dname:
                                    type: string
                                    description: |
                                        The device's name for easier identification in the user's device list
                            additionalProperties: false
                            required:
                                - clientType                        
                                - did
                                - dname

            responses:
                '200':
                    description: |
                        A new session was started
                    content:
                        application/Json:
                            schema:
                                type: object
                                properties:
                                    sid:
                                        type: string
                                        format: uuid
                                        description: |
                                            The id of the newly started session
                                    key:
                                        type: string
                                        format: byte
                                        description: |
                                            A private sequence of random bytes used to authenticate the session. This prevents session-
                                            hijacking by guessing valid session ids as their UUID generation might not be as unpredictable
                                            as desired
                                additionalProperties: false
                                required:
                                    - sid
                                    - key
                '400':  
                    $ref: '#/components/responses/Error400'
                '401':
                    $ref: '#/components/responses/Error401'
                '403':
                    $ref: '#/components/responses/Error403'

    /session/heartbeat/:
        post:
            summary: Tries to keep a running session alive
            tags:
                - Session
            description: |
                Tries to keep a session alive to prevent it from timing out due to inactivity.
                The server may decide to terminate the session anyway in certain situations.
                In this case, the request fails with a custom error code
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            type: object
                            properties:
                                sid:
                                    type: string
                                    format: uuid
                                    pattern: ^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$
                                    description: |
                                        The session id retrieved from the initial call to `/session/start`
                                key:
                                    type: string
                                    format: byte
                                    pattern: ^(?:[a-zA-Z0-9\+\/]{4})*(?:[a-zA-Z0-9\+\/]{4}|[a-zA-Z0-9\+\/]{3}=|[a-zA-Z0-9\+\/]{2}==)$
                                    description: |
                                        The session key retrieved from the initial call to `/session/start`
                            additionalProperties: false
                            required:
                                - sid
                                - key

            responses:
                '200':
                    description: |
                        The session was refreshed successfully
                    content:
                        application/Json:
                            schema:
                                type: object
                                properties:
                                    sid:
                                        type: string
                                        format: uuid
                                        description: |
                                            The id of the session returned
                                additionalProperties: false
                                required:
                                    - sid
                '400':  
                    $ref: '#/components/responses/Error400'
                '401':
                    $ref: '#/components/responses/Error401'
                '403':
                    $ref: '#/components/responses/Error403'

    /session/resume/:
        post:
            summary: Tries to resume a suspended session
            tags:
                - Session
            description: |
                Tries to revive a suspended session. A session gets suspended after 30 minutes of inactivity. To prevent a session from getting suspended, 
                one can call `/session/heartbeat`. A suspended session gets terminated after 7 days of continuous suspension. After that, a new session has
                to be requested.        
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            type: object
                            properties:
                                sid:
                                    type: string
                                    format: uuid
                                    pattern: ^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$
                                    description: |
                                        The session id retrieved from the initial call to `/session/start`
                                key:
                                    type: string
                                    format: byte
                                    pattern: ^(?:[a-zA-Z0-9\+\/]{4})*(?:[a-zA-Z0-9\+\/]{4}|[a-zA-Z0-9\+\/]{3}=|[a-zA-Z0-9\+\/]{2}==)$
                                    description: |
                                        The session key retrieved from the initial call to `/session/start` 
                                did:
                                    type: string
                                    format: uuid
                                    pattern: ^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$
                                    description: |
                                        The device id from which the session was started. A session can only be resumed from the same device
                            additionalProperties: false
                            required:
                                - sid
                                - key
                                - did

            responses:
                '200':
                    description: |
                        The session was refreshed successfully
                    content:
                        application/Json:
                            schema:
                                type: object
                                properties:
                                    sid:
                                        type: string
                                        format: uuid
                                        description: |
                                            The id of the session returned                            
                                additionalProperties: false
                                required:
                                    - sid
                '400':  
                    $ref: '#/components/responses/Error400'
                '401':
                    $ref: '#/components/responses/Error401'
                '403':
                    $ref: '#/components/responses/Error403'

components:
    responses:
        Error401:
            description: |
                You are not allowed to perform this action.
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            message:
                                type: string
                        required: 
                            - message
        Error403:
            description: |
                The provided information was not suitable for the call.
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            severity:
                                type: string
                                description: |
                                    Contains a single character indicating the severity level of the error:
                                    - `W` is a warning. The action is not required as the current state is already sufficient
                                    - `E` is an error. The action can not succeed given the information provided
                                    - `P` is a problem. The action can not succeed right now because preconditions are not fulfilled (e.g. wrong sequence of API calls) or the state of the session is not suitable for the call
                                    - `C` is a critical error. The action can not proceed due to illegal actions. These usually result in session termination
                                
                            error:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        description: |
                                            A description of what went wrong.
                                    code:
                                        type: integer
                                        description: |
                                            A unique error code further referencing the nature of the error.
                                            This can be used to handle different errors in different ways.


                                            The possible error codes returned are subject to the respective action called.
                                required:
                                    - message
                                    - code
                        required:
                            - error

        Error400:
            description: |
                The content body did not contain valid JSON or did not match the request format.
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            message:
                                type: string
                        required: 
                            - message
                        