openapi: 3.0.0
info:
  version: "1.0.0"
  title: BELparcel REST Service
  description: Service that allows communication with the BELparcel application to exchange information on notification, reporting, time registration in relation to the postal law for parcel deliverers

servers:
  - url: https://services-sim.socialsecurity.be/REST/belParcel/v1/
  - url: https://services.socialsecurity.be/REST/belParcel/v1/

tags:
  - name: Documentation
    description: Everything related to API documentation
  - name: Reporting
    description: Everything related to reporting
    externalDocs:
      url: https://belparcel.be/en/which-obligations/half-yearly-report.html

paths:
  /doc/openapi.yaml:
    get:
      tags:
        - "Documentation"
      summary: "Returns the API documentation in YAML Swagger format"
      description: ""
      operationId: "getSwagger"
      parameters: [ ]
      security:
        - Oauth:
            - scope:rsz-onss:gestion:soplafi-rest:professionalconsult
            - scope:rsz-onss:gestion:soplafi-rest:professionalnotirep
      x-oauth2-required-scopes: any
      responses:
        '200':
          description: successful operation
          content:
            application/yaml:
              schema:
                type: string
                format: binary
        default:
          description: Default
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  
  /doc/reporting:
    get:
      tags:
        - "Documentation"
      summary: "Returns the Reporting API documentation in YAML Swagger format"
      description: ""
      operationId: "getReportingSwagger"
      parameters: [ ]
      security:
        - Oauth:
            - scope:rsz-onss:gestion:soplafi-rest:systementerprise
            - scope:rsz-onss:gestion:soplafi-rest:systemmandatary
            - scope:rsz-onss:gestion:soplafi-rest:professionalconsult
            - scope:rsz-onss:gestion:soplafi-rest:professionalnotirep
      x-oauth2-required-scopes: any
      responses:
        '200':
          description: successful operation
          content:
            application/yaml:
              schema:
                type: string
                format: binary
        default:
          description: Default
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    
  /reports/{reference}:
    get:
      summary: Get a specific report by reference for an enterprise number
      description: Returns a specific report with detailed information for the given enterprise number and reference.
      operationId: getReportByReference
      tags:
        - Reporting
      parameters:
        - name: reference
          in: path
          description: The reference of the report this is a unique business key of the report generated by the application
          required: true
          schema:
            type: string
          example: "724101716317"
        - name: enterpriseNumber
          in: query
          description: The enterprise number
          required: true
          schema:
            $ref: '#/components/schemas/EnterpriseNumber'
      security:
        - Oauth:
            - scope:rsz-onss:gestion:soplafi-rest:systementerprise
            - scope:rsz-onss:gestion:soplafi-rest:systemmandatary
            - scope:rsz-onss:gestion:soplafi-rest:professionalnotirep
      x-oauth2-required-scopes: any
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Report'
        '400':
          description: Bad request
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Unauthorised
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Forbidden
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Not found
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: Internal server error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        default:
          description: Unexpected error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  
  /reports:
    get:
      summary: Get reports using query parameters enterprise number, start of period, status and detail
      description: Returns all reports for an enterprise number and/or specific period. By default, only the general report information (status,…) is returned unless the detail parameter is specified. Optionally, the status can be provided as an additional search criteria
      operationId: getReports
      tags:
        - Reporting
      parameters:
        - name: enterpriseNumber
          in: query
          description: The enterprise number for which you want to see a report. This is required in case call is done by an enterprise or mandatary.
          required: false
          schema:
            $ref: '#/components/schemas/EnterpriseNumber'
        - name: periodStart
          in: query
          description: The first month of the period for which reports are to be returned. Format yyyy-MM
          required: false
          schema:
            $ref: '#/components/schemas/YearMonth'
        - name: status
          in: query
          description: Filter reports by status (optional)
          required: false
          schema:
            type: string
            enum:
              - initiated
              - draft
              - submitted
              - reopened
              - resubmitted
          example: "draft"
        - name: detail
          in: query
          description: Include detailed information of the reports in the response such as the remunerations, the contacts data and the distribution centers (optional)
          required: false
          schema:
            type: boolean
            default: false
      security:
        - Oauth:
            - scope:rsz-onss:gestion:soplafi-rest:systementerprise
            - scope:rsz-onss:gestion:soplafi-rest:systemmandatary
            - scope:rsz-onss:gestion:soplafi-rest:professionalnotirep
      x-oauth2-required-scopes: any
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Reports'
        '400':
          description: Bad request
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Not authorised
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: No reports found
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: Internal server error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        default:
          description: Unexpected error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    post:
      summary: Update a specific report for an enterprise number
      description: Update an existing report for the given enterprise number. Provide the full body of the report. The logic determines the correct period to update based on the period object.
      operationId: updateReport
      tags:
        - Reporting
      requestBody:
        description: The report object to update
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Report'
      security:
        - Oauth:
            - scope:rsz-onss:gestion:soplafi-rest:systementerprise
            - scope:rsz-onss:gestion:soplafi-rest:systemmandatary
      x-oauth2-required-scopes: any
      responses:
        '200':
          description: Report successfully created or updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Report'
        '400':
          description: Bad request
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Not authorised
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Forbidden
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Not found
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '409':
          description: Conflict
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: Internal server error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        default:
          description: Unexpected error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  
  /periods:
    get:
      summary: Get periods
      description: Returns open and closed periods.
      operationId: getPeriods
      tags:
        - Reporting
      parameters:
        - name: status
          in: query
          description: The status of the period depending on start and end date
          required: false
          schema:
            type: array
            items:
              type: string
              description: The status of the periods you want to see. If nothing is provided all periods are returned. Otherwise a combination of OPEN(active periods), CLOSED (periods with end date in the past) are provided.
              enum:
                - open
                - closed
      security:
        - Oauth:
            - scope:rsz-onss:gestion:soplafi-rest:systementerprise
            - scope:rsz-onss:gestion:soplafi-rest:systemmandatary
            - scope:rsz-onss:gestion:soplafi-rest:professionalnotirep
      x-oauth2-required-scopes: any
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Periods'
        '400':
          description: Bad request
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Not authorised
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: Internal server error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        default:
          description: Unexpected error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'

components:
  schemas:    
    EnterpriseNumber:
      description: Identifier issued by CBE for a registered organization
      type: string
      pattern: '^[0-1]\d{9}$'
      example: "0123456789"
    
    PhoneNumber:
      description: International phone number
      type: string
      pattern: '^\+[1-9]{1}[0-9]{7,14}$'
      example: "+32123456789"
    
    Language:
      description: A language represented by an ISO-639-1 code
      type: string
      pattern: "^[a-z]{2}$"
      example: "en"
    
    EuroCentPositiveAmount:
      description: Money amount in Euro cents >= 0
      type: integer # representation as Euro cent instead of Euro to avoid floating point rounding problems and need for custom 'number' format
      minimum: 0
    
    YearMonth:
      description: A month of a year
      type: string
      pattern: '^[0-9]{4}-[0-1][0-9]$'
      example: '2020-01'
        
    TranslatedString:
      type: object
      description: Translation of an element.
      properties:
        fr:
          type: string
          description: The french translation of the element
        
        nl:
          type: string
          description: The dutch translation of the element
        
        de:
          type: string
          description: The german translation of the element
        
        en:
          type: string
          description: The english translation of the element
    
    Problem:
      description: A Problem Details object (RFC 7807)
      type: object
      properties:
        type:
          type: string
          format: uri
          description: An URI reference that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g. using HTML).
          default: about:blank
        href:
          type: string
          format: uri
          description: An absolute URI that, when dereferenced, provides human-readable documentation for the problem type (e.g. using HTML).
        title:
          type: string
          description: A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized)
        status:
          type: integer
          format: int32
          description: The HTTP status code generated by the origin server for this occurrence of the problem.
          minimum: 400
          maximum: 600
          exclusiveMaximum: true
        detail:
          type: string
          description: A human-readable explanation specific to this occurrence of the problem
        instance:
          type: string
          format: uri
          description: A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.
      example:
        {
          "type": "urn:problem-type:belgif:payloadTooLarge",
          "href": "https://www.belgif.be/specification/rest/api-guide/problems/payloadTooLarge.html", # location of linked doc will change in the future to recommended URI structure
          "title": "Payload Too Large",
          "status": 413,
          "detail": "Request message must not be larger than 10 MB",
          "instance": "urn:uuid:123e4567-e89b-12d3-a456-426614174000",
          "limit": 10485760  # additional properties specific to the problem type are allowed
        }
    
    InputValidationProblem:
      type: object
      allOf:
        - $ref: "#/components/schemas/Problem"
      properties:
        issues:
          type: array
          items:
            $ref: "#/components/schemas/InputValidationIssue"
      example:
        type: urn:problem-type:belgif:badRequest
        href: https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html
        title: Bad Request
        status: 400
        detail: "The input message is incorrect"
        instance: urn:uuid:123456-1234-1235-4567489798
        issues:
          - type: urn:problem-type:belgif:input-validation:schemaViolation #mandatory
            # href: TODO: foresee dereferenceable link for belgif input validation problems
            title: "Input isn't valid with respect to schema"
            detail: enterpriseNumber abc should be numeric # recommended, if more detail can be provided
            in: path
            name: enterpriseNumber
            value: abc
          - type: urn:problem-type:cbss:input-validation:replacedSsin # example of custom input validation issue defined by organization "CBSS"
            href: https://api.ksz-bcss.fgov.be/problems/replacedSsin
            title: "SSIN has been replaced. Use new ssin."
            detail: "SSIN 12345678901 has been replaced by 23456789012"
            in: body
            name: parent[0].ssin
            value: "12345678901"
            replacedBy: "23456789012"
          - type: urn:problem-type:cbss:input-validation:invalidPeriod
            title: period is invalid
            detail: endDate should be after startDate
            in: body
            name: period
            value:
              startDate: "2020-12-31"
              endDate: "2020-01-01"
          - type: urn:problem-type:cbss:input-validation:invalidSsin
            title: "There is no person with the given SSIN"
            in: path
            name: ssin
            value: "12345678911"
    
    InputValidationIssue:
      type: object
      allOf:
        - $ref: "#/components/schemas/Problem"
        # status property of Problem is usually not used for input validation issues
      properties:
        in:
          type: string
        name:
          type: string
    
    Periods:
      type: object
      description: List of periods
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Period"
    
    Period:
      type: object
      description: Contains the reporting periods and their submission dates
      properties:
        startYearMonth:
          $ref: '#/components/schemas/YearMonth'
        endYearMonth:
          $ref: '#/components/schemas/YearMonth'
        submissionStartDate:
          type: string
          format: date
          description: The starting date from which companies can start entering their report concerning the report period.
          example: "1985-05-15"
        submissionEndDate:
          type: string
          format: date
          description: The end date from which companies can start entering their report concerning the report period
          example: "1985-05-15"
        status:
          type: string
          description: The status of the period either OPEN or CLOSED
          example: "OPEN"
        minSubmissionDate:
          type: string
          format: date
          description: The earliest date the report can be submitted for a reporting period
          example: "1985-05-15"
      required:
        - startYearMonth
    
    Reports:
      type: object
      description: List of reports
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Report"
    
    Report:
      type: object
      description: Report of a specific company for a period
      properties:
        reference:
          type: string
          description: Unique business key of the report generated by the application. This is automatically generated by BELparcel (format 7YY123456789)
          example: "724101716317"
          maxLength: 250
        status:
          type: string
          description: The status of the report.INITIATED=Report empty; DRAFT=Report filled but not submitted; SUBMITTED=Report completed; REOPENED=Report reopened by IBPT; RESUBMITTED=Report submitted after being REOPENED. Status that can be used by external system = DRAFT, SUBMITTED, RESUBMITTED.
          enum:
            - initiated
            - draft
            - submitted
            - reopened
            - resubmitted
          example: "draft"
        enterpriseNumber:
          $ref: '#/components/schemas/EnterpriseNumber'
        notificationReference:
          type: string
          description: Unique business key of the notification generated by the application. This is automatically generated by BELparcel (format 9YY123456789)
          example: "924101716317"
          maxLength: 250
        submissionDate:
          type: string
          format: date-time
          description: Date and time on which the report was submitted or resubmitted in UTC format yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
          example: "2023-01-15T12:00:00Z"
        resubmissionEndDate:
          type: string
          format: date
          description: Last day on which the company can resubmit their reopened report. Format yyyy-MM-dd
          example: "2023-02-01"
        confirmedNoActivities:
          type: boolean
          description: Confirmation that no activities are to be declared for this report.
          default: false
        confirmedNoProvidedServices:
          type: boolean
          description: Confirmation that no services are to be declared for this report.
          default: false
        confirmedNoContactData:
          type: boolean
          description: Confirmation that no contact data are to be declared for this report.
          default: false
        confirmedNoContractor:
          type: boolean
          description: Confirmation that no contractor remunerations are to be declared for this report.
          default: false
        confirmedNoSubcontractor:
          type: boolean
          description: Confirmation that no subcontractor remunerations are to be declared for this report.
          default: false
        confirmedNoDistributionCenter:
          type: boolean
          description: Confirmation that no distribution centers are to be declared for this report.
          default: false
        remunerations:
          $ref: '#/components/schemas/Remunerations'
        contactDataList:
          $ref: '#/components/schemas/ContactDataList'
        distributionCenters:
          $ref: '#/components/schemas/DistributionCenters'
        providedServices:
          $ref: '#/components/schemas/ProvidedServices'
        period:
          $ref: '#/components/schemas/Period'
    
    Remunerations:
      type: array
      description: List of renumerations
      items:
        $ref: "#/components/schemas/Remuneration"
    
    Remuneration:
      type: object
      description: Remuneration received from contractor or given to subcontractor for a specific period
      properties:
        enterpriseNumber:
          $ref: '#/components/schemas/EnterpriseNumber'
        role:
          type: string
          description: Role of the provided enterprise
          enum:
            - contractor
            - subcontractor
          example: "contractor"
        parcelAmount:
          type: integer
          description: The number of parcels delivered by or for the company
          example: 250
          minimum: 0
        fee:
          $ref: '#/components/schemas/EuroCentPositiveAmount'
      required:
        - enterpriseNumber
        - role
    
    ContactDataList:
      type: array
      description: List of contact data
      items:
        $ref: "#/components/schemas/ContactData"
    
    ContactData:
      type: object
      description: Contact information of the contact persons of the enterprise
      properties:
        role:
          type: string
          description: The role the contact has within the company.
          enum:
            - coordinator # the transport coordinator (only 1 allowed)
            - transportManager # transport manager
            - licenseHolder # holder of the transport manager's certificate of competence
          example: "coordinator"
        contactData:
          $ref: '#/components/schemas/ContactForm'
      required:
        - role
        - contactData
    
    DistributionCenters:
      type: array
      description: List of distribution centers
      items:
        $ref: "#/components/schemas/DistributionCenter"
    
    DistributionCenter:
      type: object
      description: Distribution centers that are owned by the company submitting the report
      properties:
        name:
          type: string
          maxLength: 255
          description: Name used to distinguish the distribution center
          example: "Dockx Center"
        street:
          type: string
          maxLength: 255
          description: Street name of the address
          example: "Main Street"
        houseNumber:
          type: string
          maxLength: 255
          description: House number of the address
          example: "123"
        boxNumber:
          type: string
          maxLength: 255
          description: Box number of the address
          example: "4A"
        municipality:
          type: string
          maxLength: 255
          description: City name of the address
          example: "Brussels"
        postCode:
          type: string
          maxLength: 255
          description: Postal code of the address
          example: "1000"
        countryIsoCode:
          type: string
          maxLength: 2
          pattern: "^[A-Z]{2}$"
          description: Country represented by an ISO 3166-1 alpha-2 code
          example: "BE"
        comment:
          type: string
          maxLength: 1000
          description: Free additional information on the distribution center
          example: "Primary distribution center"
      required:
        - name
        - street
        - houseNumber
        - municipality
        - postCode
        - countryIsoCode
    
    ContactForm:
      type: object
      description: Details of the contact
      properties:
        email:
          type: string
          maxLength: 320
          description: Email address of the contact
          format: email
          example: "john.doe@example.com"
        givenName:
          type: string
          maxLength: 255
          description: First name of the contact
          example: "John"
        familyName:
          type: string
          maxLength: 255
          description: Family name of the contact
          example: "Doe"
        phoneNumber:
          $ref: '#/components/schemas/PhoneNumber'
        comment:
          type: string
          maxLength: 1000
          description: Additional comments about the contact
          example: "Primary contact for the belparcel reporting"
      required:
        - email
        - familyName
        - phoneNumber
    
    ProvidedServices:
      type: object
      description: This table contains the enterprise's description of their services during the period of the report.
      properties:
        serviceExpress:
          type: boolean
          description: Indicates whether the enterprise offers express service to their clients.
        nationalExclusive:
          type: boolean
          description: Indicates whether the enterprise works exclusively within Belgium.
        nightWeekendDelivery:
          type: boolean
          description: Indicates whether the enterprise makes deliveries at night or during the weekend.
        packagesExclusive:
          type: boolean
          description: Indicates whether the enterprise exclusively delivers packages or other types of mail.
        packagesExclusiveComment:
          type: string
          maxLength: 1000
          description: Free field to clarify what other kind of deliveries are provided in case packages_exclusive is false.
        typesOfGoods:
          description: Indicates the types of goods that are transported by the enterprise. This field is in json format to allow a multiselect.
          type: array
          items:
            type: string
            enum:
              - food
              - electronics
              - books
              - chemicals
              - medicins
              - textiles
              - other
          example: [ "food","electronics" ]
        packageContentUnknown:
          type: boolean
          description: Indicates whether the enterprise is unaware of the types of goods being delivered as they do not know the content of the packages.
        typesOfGoodsOther:
          type: string
          maxLength: 1000
          description: Free field to clarify what other types of goods are delivered if the enterprise selected "OTHER".
        transactionType:
          description: Indicates the type of transactions the enterprise maintains. This field is in json format to allow a multiselect.
          type: array
          items:
            type: string
            enum:
              - b2b
              - b2c
              - c2x
              - unknown
          example: [ "b2b","c2x" ]
  
  securitySchemes:
    Oauth:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: 'https://oauth-v5.socialsecurity.be/oauth2/authorize'
          scopes:
            'scope:rsz-onss:gestion:soplafi-rest:systementerprise': access (CRUD) to own enterprise data as enterprise system user
            'scope:rsz-onss:gestion:soplafi-rest:systemmandatary': access (CRUD) to own enterprise data as enterprise system user
            'scope:rsz-onss:gestion:soplafi-rest:professionalconsult': consult access as agent
            'scope:rsz-onss:gestion:soplafi-rest:professionalnotirep': access (CRUD) to notification and reporting data as agent
