Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Document API with OpenAPI #26

Open
ximex opened this issue Jan 5, 2024 · 1 comment
Open

Document API with OpenAPI #26

ximex opened this issue Jan 5, 2024 · 1 comment

Comments

@ximex
Copy link

ximex commented Jan 5, 2024

It would be great if you could document the API in the OpenAPI spec
https://www.openapis.org/

@ximex
Copy link
Author

ximex commented Oct 26, 2024

i created a first version of OpenAPI spec. I created it only from the docs here without comparing with the real data.
You could test it here: https://editor-next.swagger.io/

openapi: 3.1.1
info:
  title: blaulichtSMS
  description: All APIs for the blaulichtSMS service
  contact:
    name: SOLARYS Software GmbH
    url: https://blaulichtsms.net/support/#kontaktformular
  license:
    name: Creative Commons Attribution Share Alike 4.0 International
    identifier: CC-BY-SA-4.0
  version: 0.0.1
servers:
  - url: https://api-staging.blaulichtsms.net/blaulicht
    description: Test server
  - url: https://api.blaulichtsms.net/blaulicht
    description: Live server
paths:
  /api/alarm/v1/trigger:
    post:
      tags: ['Alarm']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AlarmTriggerRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AlarmTriggerResponse'
  /api/alarm/v1/query:
    post:
      tags: ['Alarm']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AlarmQueryRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AlarmQueryResponse'
  /api/alarm/v1/list:
    post:
      tags: ['Alarm']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AlarmListRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AlarmListResponse'

  /api/alarm/v1/dashboard/#:
    post:
      tags: ['Dashboard']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DashboardLoginRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DashboardLoginResponse'
  /api/alarm/v1/dashboard/{sessionId}:
    get:
      tags: ['Dashboard']
      parameters:
        - $ref: '#/components/parameters/SessionIdPath'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DashboardDataResponse'
        '401':
          description: Unauthorized

  /api/portal/v1/import/participants/json:
    post:
      tags: ['Import']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ImportParticipantsJsonRequest'
      responses:
        '200':
          description: OK
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
  /api/portal/v1/import/participants/csv/{customerId}:
    post:
      tags: ['Import']
      parameters:
        - $ref: '#/components/parameters/CustomerIdPath'
        - $ref: '#/components/parameters/UsernameHeader'
        - $ref: '#/components/parameters/PasswordHeader'
      requestBody:
        content:
          text/csv:
            schema:
              $ref: '#/components/schemas/ImportParticipantsCsvRequest'
      responses:
        '200':
          description: OK
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
  /api/portal/v1/import/trigger/json:
    post:
      tags: ['Import']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ImportTriggerJsonRequest'
      responses:
        '200':
          description: OK
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
  /api/portal/v1/import/trigger/csv/{customerId}:
    post:
      tags: ['Import']
      parameters:
        - $ref: '#/components/parameters/CustomerIdPath'
        - $ref: '#/components/parameters/UsernameHeader'
        - $ref: '#/components/parameters/PasswordHeader'
      requestBody:
        content:
          text/csv:
            schema:
              $ref: '#/components/schemas/ImportTriggerCsvRequest'
      responses:
        '200':
          description: OK
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
  /api/portal/v1/import/groups/json:
    post:
      tags: ['Import']
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ImportGroupsJsonRequest'
      responses:
        '200':
          description: OK
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
  /api/portal/v1/import/groups/csv/{customerId}:
    post:
      tags: ['Import']
      headers:
      parameters:
        - $ref: '#/components/parameters/CustomerIdPath'
        - $ref: '#/components/parameters/UsernameHeader'
        - $ref: '#/components/parameters/PasswordHeader'
      requestBody:
        content:
          text/csv:
            schema:
              $ref: '#/components/schemas/ImportGroupsCsvRequest'
      responses:
        '200':
          description: OK
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden

components:
  schemas:
    SessionId:
      type: string
    CustomerId:
      description: CustomerId as string
      type: string
      pattern: '^\d+$'
    Username:
      type: string
    Password:
      type: string
    Email:
      type: string
      format: email
    GroupId:
      type: string
      pattern: '^G\d{1,9}$'
    TemplateId:
      type: string
      pattern: '^A\d+$'
    AlarmId:
      type: string
    AlarmType:
      type: string
      enum:
        - 'alarm'
        - 'info'
    IntegrationType:
      type: string
      enum:
        - 'wasserkarte.info' # TODO
    ParticipationType:
      type: string
      enum:
        - 'yes'
        - 'no'
        - 'uknown' # TODO: typo?
        - 'pending'
    DateTime:
      type: string
      format: date-time
      pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$'
    HexColor:
      type: string
      pattern: '^#[0-9a-f]{6}$'
    Msisdn:
      type: string
      pattern: '^\+\d+$'
    Coordinates:
      type: object
      required: ['lat', 'lon']
      properties:
        lat:
          type: number
        lon:
          type: number
    Geolocation:
      type: object
      required: ['coordinates', 'positionSetByAuthor', 'radius', 'distance', 'address']
      properties:
        coordinates:
          $ref: '#/components/schemas/Coordinates'
        positionSetByAuthor:
          type: boolean
        radius:
          type: number
          nullable: true
        distance:
          type: number
          nullable: true
        address:
          type: string
          nullable: true
    Integration:
      type: object
      required: ['type', 'fields']
      properties:
        type:
          $ref: '#/components/schemas/IntegrationType'
        fields:
          type: object
          required: ['apiKey']
          properties: # TODO
            apiKey:
              type: string
    AlarmData:
      type: object
      required: ['alarmId', 'alarmGroups', 'alarmDate', 'endDate', 'authorName', 'alarmText', 'needsAcknowledgement', 'usersAlertedCount', 'geolocation', 'recipients', 'audioUrl']
      properties:
        alarmId:
          $ref: '#/components/schemas/AlarmId'
        alarmGroups:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmGroup'
        alarmDate:
          $ref: '#/components/schemas/DateTime'
        endDate:
          $ref: '#/components/schemas/DateTime'
        authorName:
          type: string
        alarmText:
          type: string
        needsAcknowledgement:
          type: boolean
        usersAlertedCount:
          type: integer
        geolocation:
          $ref: '#/components/schemas/Geolocation'
        recipients:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmRecipient'
        audioUrl:
          type: string
          nullable: true
    AlarmGroup:
      type: object
      required: ['groupId', 'groupName']
      properties:
        groupId:
          $ref: '#/components/schemas/GroupId'
        groupName:
          type: string
    AlarmRecipient:
      type: object
      required: ['id', 'name', 'msisdn', 'participation', 'participationMessage', 'functions']
      properties:
        id:
          type: string
        name:
          type: string
        msisdn:
          $ref: '#/components/schemas/Msisdn'
        participation:
          $ref: '#/components/schemas/ParticipationType'
        participationMessage:
          type: string
        functions:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmFunction'
    AlarmFunction:
      type: object
      required: ['functionId', 'name', 'order', 'shortForm', 'backgroundHexColorCode', 'foregroundHexColorCode']
      properties:
        functionId:
          type: string
          pattern: '^\d+$'
        name:
          type: string
        shortForm:
          type: string
        order:
          type: integer
        backgroundHexColorCode:
          $ref: '#/components/schemas/HexColor'
        foregroundHexColorCode:
          $ref: '#/components/schemas/HexColor'

    AlarmResultCode:
      type: string
      enum:
        - 'OK'
        - 'MISSING_INPUT_DATA'
        - 'MISSING_CUSTOMER_ID'
        - 'MISSING_USERNAME'
        - 'INVALID_CUSTOMER_ID'
        - 'NOT_CONFIGURED_FOR_CUSTOMER'
        - 'UNKNOWN_USER'
        - 'NOT_AUTHORIZED'
        - 'UNAUTHORIZED_SENDER_ID'
        - 'DEACTIVATED'
        - 'INVALID_GROUP'
        - 'INVALID_TEMPLATE'
        - 'NOT FOUND'
        - 'UNKNOWN_ERROR'
    AlarmDataExtended:
      allOf:
        - $ref: '#/components/schemas/AlarmData'
        - type: object
          required: ['customerId', 'indexNumber']
          properties:
            customerId:
              $ref: '#/components/schemas/CustomerId'
            indexNumber:
              type: integer
              nullable: true

    AlarmTriggerRequest:
      type: object
      required: ['username', 'password', 'customerId', 'type', 'needsAcknowledgement']
      properties:
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
        customerId:
          $ref: '#/components/schemas/CustomerId'
        type:
          $ref: '#/components/schemas/AlarmType'
        hideTriggerDetails:
          type: boolean
        alarmText:
          type: string
        indexNumber:
          type: integer
        needsAcknowledgement:
          type: boolean
        startDate:
          $ref: '#/components/schemas/DateTime'
        duration:
          type: integer
        recipientConfirmation:
          type: boolean
        recipientConfirmationTarget:
          $ref: '#/components/schemas/Msisdn'
        template:
          $ref: '#/components/schemas/TemplateId'
        groupCodes:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/GroupId'
        additionalMsisdns:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/Msisdn'
        coordinates:
          $ref: '#/components/schemas/Coordinates'
        geolocation:
          $ref: '#/components/schemas/Geolocation'
    AlarmTriggerResponse:
      type: object
      required: ['result', 'alarmId', 'customerId', 'description', 'alarmData']
      properties:
        result:
          $ref: '#/components/schemas/AlarmResultCode'
        alarmId:
          $ref: '#/components/schemas/AlarmId'
        customerId:
          $ref: '#/components/schemas/CustomerId'
        description:
          type: 'null'
        alarmData:
          $ref: '#/components/schemas/AlarmDataExtended'
    AlarmQueryRequest:
      type: object
      required: ['username', 'password', 'customerId', 'alarmId']
      properties:
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
        customerId:
          $ref: '#/components/schemas/CustomerId'
        alarmId:
          $ref: '#/components/schemas/AlarmId'
    AlarmQueryResponse:
      type: object
      required: ['result', 'alarmId', 'customerId', 'description', 'alarmData']
      properties:
        result:
          $ref: '#/components/schemas/AlarmResultCode'
        alarmId:
          $ref: '#/components/schemas/AlarmId'
        customerId:
          $ref: '#/components/schemas/CustomerId'
        description:
          type: string
        alarmData:
          $ref: '#/components/schemas/AlarmDataExtended'
    AlarmListRequest:
      type: object
      required: ['username', 'password', 'customerIds']
      properties:
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
        customerIds:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/CustomerId'
        startDate:
          $ref: '#/components/schemas/DateTime'
        endDate:
          $ref: '#/components/schemas/DateTime'
    AlarmListResponse:
      type: object
      required: ['result', 'description', 'alarms']
      properties:
        result:
          $ref: '#/components/schemas/AlarmResultCode'
        description:
          type: string
        alarms:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmDataExtended'
        scenariosEnabled: # TODO not in docu
          type: boolean

    LoginResultCode:
      type: string
      nullable: true
      enum:
        - 'MISSING_INPUT_DATA'
        - 'MISSING_PASSWORD'
        - 'MISSING_CUSTOMERID'
        - 'MISSING_USERNAME'
        - 'INVALID_CREDENTIALS'

    DashboardLoginRequest:
      type: object
      required: ['customerId', 'username', 'password']
      properties:
        customerId:
          $ref: '#/components/schemas/CustomerId'
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
    DashboardLoginResponse:
      type: object
      required: ['success', 'sessionId', 'error']
      properties:
        success:
          type: boolean
        sessionId:
          allOf:
            - $ref: '#/components/schemas/SessionId'
            - description: Is `null` if `success` is `false`
              nullable: true
        error:
          allOf:
            - $ref: '#/components/schemas/#ResultCode'
            - description: Is `null` if `success` is `true`
    DashboardDataResponse:
      type: object
      properties:
        customerId:
          $ref: '#/components/schemas/CustomerId'
        customerName:
          type: string
        username:
          $ref: '#/components/schemas/Username'
        integrations:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/Integration'
        alarms:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmData'
        infos:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmData'

    ParticipantData:
      type: object
      required: ['msisdn', 'givenname', 'surname', 'groups']
      properties:
        msisdn:
          $ref: '#/components/schemas/Msisdn'
        givenname:
          type: string
        surname:
          type: string
        email:
          $ref: '#/components/schemas/Email'
        groups:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/GroupId'
    AlarmGroupExtended:
      allOf:
        - $ref: '#/components/schemas/AlarmGroup'
        - type: object
          properties:
            redo:
              type: integer
              enum: [0, 1]
            redoInterval:
              description: If `redo` is `1`
              type: integer

    ImportParticipantsJsonRequest:
      type: object
      required: ['customerId', 'username', 'password', 'participants']
      properties:
        customerId:
          $ref: '#/components/schemas/CustomerId'
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
        participants:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/ParticipantData'
    ImportParticipantsCsvRequest:
      type: string
      example: |-
        givenname;surname;msisdn;email;groups
        John;Doe;+4366412345678;;G1
        Joanne;Doe;+4367612345678;joane@doe.com;G1,G2
    ImportTriggerJsonRequest:
      type: object
      required: ['customerId', 'username', 'password', 'trigger']
      properties:
        customerId:
          $ref: '#/components/schemas/CustomerId'
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
        trigger:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/ParticipantData'
    ImportTriggerCsvRequest:
      type: string
      example: |-
        givenname;surname;msisdn;email;groups
        Max;Mustermann;+4366412345678;;G1
        Martina;Musterfrau;+4367612345678;martina.musterfrau@example.com;G1,G2
    ImportGroupsJsonRequest:
      type: object
      required: ['customerId', 'username', 'password', 'groups']
      properties:
        customerId:
          $ref: '#/components/schemas/CustomerId'
        username:
          $ref: '#/components/schemas/Username'
        password:
          $ref: '#/components/schemas/Password'
        groups:
          type: array
          uniqueItems: true
          items:
            $ref: '#/components/schemas/AlarmGroupExtended'
    ImportGroupsCsvRequest:
      type: string
      example: |-
        groupId;name;redo;redoInterval
        G1;siren;;
        G2;silent alert;;
        G3;whole brigade;;

  parameters:
    SessionIdPath:
      name: sessionId
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/SessionId'
    CustomerIdPath:
      name: customerId
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/CustomerId'
    UsernameHeader:
      name: X-Username
      in: header
      required: true
      schema:
        $ref: '#/components/schemas/Username'
    PasswordHeader:
      name: X-Password
      in: header
      required: true
      schema:
        $ref: '#/components/schemas/Password'

tags:
  - name: Alarm
#    description: Alarm
#  - name: SMS
#    description: SMS
  - name: Dashboard
#    description: Dashboard
  - name: Import
#    description: Import

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant