openapi: 3.0.1
info:
  title: Supplement 2 to Annex 2 to the FDF EETS and Fuel Card Providers Ordinance
  x-audience: partner
  description: |
    This Fuelcard API is provided by fuelcard providers to allowing BAZG to charge and refund fuelcards for services and products provided by BAZG.
    
    ### Why We Use PUT Instead of POST for Creating Resources
    
    In this API, we use the PUT method to create resources. This choice is driven by our commitment to ensure that the operation of creating resources is idempotent. Idempotency is a fundamental characteristic that guarantees that multiple identical requests will have the same effect as a single request which is important when charging fuelcards.
    
    #### Key Aspects of Using PUT:
    
    - **Idempotent Operations**: PUT is inherently idempotent. Using PUT means that if a request to create a resource with a specific identifier is repeated because of network retries or other issues, it will not result in duplicate resource creation, ensuring consistent state without duplication.
      
    - **Client-Specified resource Identifiers**: The PUT method requires the client to specify the resource identifier. This approach is suitable for scenarios where clients are capable of determining the unique identifiers of the resources they are creating. As we use UUID to identify resources, this is possible. The URI at which the resource is accessible is defined by the client, and does not change between requests, which aligns with the idempotent nature of PUT.
    
    - **Retry is ok**: If the client triggers a retry, the server sends the same response as for the first request.
    
    - **Clarity and Predictability**: This method provides clarity and predictability for API consumers. Clients can be confident about the outcome of their requests without side effects of unintended multiple resource creations.
    
    #### Implications:
    
    Using PUT for resource creation simplifies the handling of requests and minimizes potential errors associated with duplicate entries, which are common in non-idempotent operations typically associated with POST. It is especially advantageous in distributed systems where request duplication might occur more frequently.
    
    By choosing PUT over POST for creating resources, we ensure robustness and reliability of our API, providing a straightforward and error-reducing interaction model for our clients.

  version: 1.1.2
  contact:
    name: Camiuns
    email: camiuns@bazg.admin.ch
tags:
  - name: BAZG Fuelcard API
    description: API provided by fuelcard providers to BAZG

paths:
  /authorizations/{authorization-id}:
    put:
      summary: Create an authorization for later capture
      tags:
        - charge
      operationId: createAuthorization
      security:
        - OAuth2ClientCredentials: [write]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: authorization-id
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Authorization'    
      responses:
        '200':
          $ref: '#/components/responses/AuthorizationAcceptedResponse'
        '400':
          $ref: '#/components/responses/AuthorizationErrorResponse'
        '409':
          $ref: '#/components/responses/AuthorizationRejectionResponse'
          
  /authorizations/{authorization-id}/captures/{capture-id}:
    put:
      summary: Capture a previously made authorization 
      tags:
        - charge
      operationId: createCapture
      security:
        - OAuth2ClientCredentials: [write]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: authorization-id
          description: the resource id of the authorizeation to capture
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
        - in: path
          name: capture-id
          description: the resource id of the capture to create
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Capture'    
      responses:
        '200':
          $ref: '#/components/responses/CaptureCreatedResponse'
        '400':
          $ref: '#/components/responses/CaptureErrorResponse'
        '404':
          $ref: '#/components/responses/CaptureNotFoundResponse'

  /authorizations/{authorization-id}/cancellations/{cancellation-id}:
    put:
      summary: Request to cancel an authorization
      tags:
        - charge
      operationId: cancelAuthorization
      security:
        - OAuth2ClientCredentials: [write]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: authorization-id
          description: the resource id of the authorizeation to be cancelled
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
        - in: path
          name: cancellation-id
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
      responses:
        '200':
          $ref: '#/components/responses/CancelAcceptedResponse'
        '400':
          $ref: '#/components/responses/CancelErrorResponse'
        '404':
          $ref: '#/components/responses/CancelNotFoundResponse'

  /charges/{charge-id}:
    put:
      summary: Charge a fuelcard directly
      tags:
        - charge
      operationId: createCharge
      security:
        - OAuth2ClientCredentials: [write]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: charge-id
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Charge'    
      responses:
        '200':
          $ref: '#/components/responses/ChargeCreatedResponse'
        '400':
          $ref: '#/components/responses/ChargeErrorResponse'
        '409':
          $ref: '#/components/responses/ChargeRejectionResponse'

  /refunds/{refund-id}:
    put:
      summary: Refund a fuelcard 
      tags:
        - refund
      operationId: createRefund
      security:
        - OAuth2ClientCredentials: [write]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: refund-id
          required: true
          schema:
            $ref: '#/components/schemas/ResourceId'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Refund'    
      responses:
        '200':
          $ref: '#/components/responses/RefundCreatedResponse'
        '400':
          $ref: '#/components/responses/RefundErrorResponse'
        '404':
          $ref: '#/components/responses/DebitNotFoundResponse'

  /summaries:
    summary: Summaries are reports of all transactions within a period. A summary can encompass many transactions. Providing a summary may require more time than is available for responding to a synchronous request. To eliminate the risk of timeouts, summaries are automatically generated by the fuel card provider. The BAZG regularly checks for new summaries and retrieves them. Subsequently, the BAZG confirms the receipt of the summaries, after which the fuel card provider can delete the summary
    get:
      summary: Get a list of available summaries
      tags:
        - clearing
      operationId: listSummaries
      security:
        - OAuth2ClientCredentials: [read]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
      responses:
        '200':
          description: A list of available summaries. The list is empty in case no summaries are available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListOfSummary'
        '400':
          $ref: '#/components/responses/SummariesErrorResponse'

  /summaries/{summary-id}:
    get:
      summary: Get the summary specified by id.
      tags:
        - clearing
      operationId: readSummary
      security:
        - OAuth2ClientCredentials: [read]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: summary-id
          schema:
            $ref: '#/components/schemas/SummaryId'
          required: true

      responses:
        '200':
          description: Summary for the period of time specified
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Summary'    
        '400':
          $ref: '#/components/responses/SummaryErrorResponse'
        '404':
          $ref: '#/components/responses/SummaryNotFoundResponse'

    delete:
      summary: Confirm receipt of the summary specified.
      description: |
        After successful confirmation, the summary is no longer listed in the list of available summaries and may be physically deleted by the fuel card provider
          - **Deletion of Summary**: After successful confirmation the summary may be deleted by the fuel card provider at any time 
          - **Idempotent Operation**: In case the client retries to confirm a summary, which has been deleted due to previous confirmation, the returned status code is 200 and explicitely NOT 404 
      tags:
        - clearing
      operationId: confirmReceipt
      security:
        - OAuth2ClientCredentials: [write]
      parameters:
        - in: header
          name: X-BPID
          required: true
          schema:
            $ref: '#/components/schemas/bpId'
        - in: path
          name: summary-id
          schema:
            $ref: '#/components/schemas/SummaryId'
          required: true
      responses:
        '204':
          description: Receipt of Summary successfully confirmed
        '400':
          $ref: '#/components/responses/SummaryErrorResponse'
        '404':
          $ref: '#/components/responses/SummaryNotFoundResponse'
components:

  parameters:
    IdempotenceKeyHeader:
      name: Idempotency-Key
      in: header
      description: A unique identifier for the request to ensure idempotency.
      required: true
      schema:
        type: string
        format: uuid

  responses:
    AuthorizationAcceptedResponse:
      description: Response in case authorization for a charge has been accepted
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              date-created:
                allOf:
                  - description: the date/time the authorization has been created
                  - $ref: '#/components/schemas/DateTime'
            required:
              - authorization-id
              - date-created
              
    AuthorizationRejectionResponse:
      description: Response in case the authorization request is technically valid but is rejected by the fuel card provider
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              reason:
                $ref: '#/components/schemas/RejectionReason'
              detail:
                description: Additional details about the reason for the rejection
                type: string
                example: Fuelcard 5001878976540310 expired 2015-04-28
              date-rejected:
                allOf:
                  - description: the date/time the request has been rejected
                  - $ref: '#/components/schemas/DateTime'

    AuthorizationErrorResponse:
      description: Response in case of invalid authorization request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid requests, intended for debugging
            properties:
              timestamp:
                type: string
                format: date-time
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              errorCode:
                type: string
              errorMessage:
                type: string

    CaptureCreatedResponse:
      description: Response created in case to a accepted caputure request
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              capture-id:
                allOf:
                  - description: provided in case the charge has been created due to a capture
                  - $ref: '#/components/schemas/ResourceId'
              date-created:
                allOf:
                  - description: the date/time the charge has been created
                  - $ref: '#/components/schemas/DateTime'
            required:
              - authorization-id
              - capture-id
              - date-created
              
    CaptureNotFoundResponse:
      description: An authorization with the Id specified does not exist
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              capture-id:
                allOf:
                  - description: provided in case the charge has been created due to a capture
                  - $ref: '#/components/schemas/ResourceId'
            required:
              - authorization-id
              - capture-id
              
    CaptureRejectionResponse:
      description: Response in case the request is technically valid but is rejected by the fuel card provider
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              capture-id:
                allOf:
                  - description: provided in case the charge has been created due to a capture
                  - $ref: '#/components/schemas/ResourceId'
              reason:
                $ref: '#/components/schemas/RejectionReason'
              detail:
                description: Additional details about the reason for the rejection
                type: string
                example: Fuelcard 5001878976540310 expired 2015-04-28
              date-rejected:
                allOf:
                  - description: the date/time the request has been rejected
                  - $ref: '#/components/schemas/DateTime'

    CaptureErrorResponse:
      description: Response in case of invalid capture request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid requests, intended for debugging
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              capture-id:
                allOf:
                  - description: provided in case the charge has been created due to a capture
                  - $ref: '#/components/schemas/ResourceId'
              timestamp:
                type: string
                format: date-time
              errorCode:
                type: string
              errorMessage:
                type: string
                
    CancelAcceptedResponse:
      description: Response in case of cancel an authorization has been accepted
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              cancellation-id:
                $ref: '#/components/schemas/ResourceId'
              date-created:
                allOf:
                  - description: the date/time the cancellation has been created
                  - $ref: '#/components/schemas/DateTime'
            required:
              - authorization-id
              - cancellation-id
              - date-created 
              
    
    CancelNotFoundResponse:
      description: An authorization with the Id specified does not exist 
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              cancellation-id:
                $ref: '#/components/schemas/ResourceId'
            required:
              - authorization-id
              - cancellation-id
              
    CancelRejectionResponse:
      description: Response in case the request is technically valid but is rejected by the fuel card provider
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              cancellation-id:
                $ref: '#/components/schemas/ResourceId'
              reason:
                $ref: '#/components/schemas/RejectionReason'
              detail:
                description: Additional details about the reason for the rejection
                type: string
                example: Fuelcard 5001878976540310 expired 2015-04-28
              date-rejected:
                allOf:
                  - description: the date/time the request has been rejected
                  - $ref: '#/components/schemas/DateTime'

    CancelErrorResponse:
      description: Response in case of invalid request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid cancellation requests, intended for debugging
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              cancellation-id:
                $ref: '#/components/schemas/ResourceId'
              timestamp:
                type: string
                format: date-time
              errorCode:
                type: string
              errorMessage:
                type: string
    
    ChargeCreatedResponse:
      description: Response created in case of an accepted charge request
      content:
        application/json:
          schema:
            type: object
            properties:
              charge-id:
                $ref: '#/components/schemas/ResourceId'
              date-created:
                allOf:
                  - description: the date/time the charge has been created
                  - $ref: '#/components/schemas/DateTime'
            required:
              - charge-id
              - date-created

    ChargeRejectionResponse:
      description: Response in case the charge request is technically valid but is rejected by the fuel card provider
      content:
        application/json:
          schema:
            type: object
            properties:
              charge-id:
                $ref: '#/components/schemas/ResourceId'
              reason:
                $ref: '#/components/schemas/RejectionReason'
              detail:
                description: Additional details about the reason for the rejection
                type: string
                example: Fuelcard 5001878976540310 expired 2015-04-28
              date-rejected:
                allOf:
                  - description: the date/time the request has been rejected
                  - $ref: '#/components/schemas/DateTime'

    ChargeErrorResponse:
      description: Response in case of invalid charge request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid charge requests, intended for debugging
            properties:
              timestamp:
                type: string
                format: date-time
              charge-id:
                $ref: '#/components/schemas/ResourceId'
              errorCode:
                type: string
              errorMessage:
                type: string


              
    RefundCreatedResponse:
      description: Response created in case a refund has been created due to an accepted refund request
      content:
        application/json:
          schema:
            type: object
            properties:
              refund-id:
                $ref: '#/components/schemas/ResourceId'
              date-created:
                allOf:
                  - description: the date/time the refund has been created
                  - $ref: '#/components/schemas/DateTime'
            required:
              - refund-id
              - date-created

    RefundErrorResponse:
      description: Response in case of invalid request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid requests, intended for debugging
            properties:
              timestamp:
                type: string
                format: date-time
              refund-id:
                $ref: '#/components/schemas/ResourceId'
              errorCode:
                type: string
              errorMessage:
                type: string

    DebitNotFoundResponse:
      description: A capture or charge with the Id specified does not exist
      content:
        application/json:
          schema:
            type: object
            properties:
              debit-id:
                $ref: '#/components/schemas/ResourceId'
              refund-id:
                $ref: '#/components/schemas/ResourceId'
            required:
              - debit-id
              - refund-id

    RejectionResponse:
      description: Response in case the request is technically valid but is rejected by the fuel card provider
      content:
        application/json:
          schema:
            type: object
            properties:
              authorization-id:
                $ref: '#/components/schemas/ResourceId'
              reason:
                $ref: '#/components/schemas/RejectionReason'
              detail:
                description: Additional details about the reason for the rejection
                type: string
                example: Fuelcard 5001878976540310 expired 2015-04-28
              date-rejected:
                allOf:
                  - description: the date/time the request has been rejected
                  - $ref: '#/components/schemas/DateTime'

    SummaryErrorResponse:
      description: Response in case of invalid request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid requests, intended for debugging
            properties:
              timestamp:
                type: string
                format: date-time
              summary-id:
                $ref: '#/components/schemas/SummaryId'
              errorCode:
                type: string
              errorMessage:
                type: string

    SummariesErrorResponse:
      description: Response in case of invalid request (400)
      content:
        application/json:
          schema:
            type: object
            description: Response in case of invalid requests, intended for debugging
            properties:
              timestamp:
                type: string
                format: date-time
              errorCode:
                type: string
              errorMessage:
                type: string
                
    SummaryNotFoundResponse:
      description: An summary with the Id specified does not exist 
      content:
        application/json:
          schema:
            type: object
            properties:
              summary-id:
                $ref: '#/components/schemas/SummaryId'
            required:
              - summary-id

                
  schemas:
    Authorization:
      description: Request to authorize a fuelcard for a debit
      properties:
        receipt-id: 
          $ref: '#/components/schemas/ReceiptId'
        card:
          $ref: '#/components/schemas/Card'
        total:
          $ref: '#/components/schemas/Amount'
        products:
          description: may be empty 
          type: array
          minItems: 0
          items:
            $ref: '#/components/schemas/Product'
      required: [card, total]

    Capture:
      description: Request to capture an amount previously authorized
      properties:
        amount:
          $ref: '#/components/schemas/Amount'
      required: [amount]

    Charge:
      description: Request to charge a fuelcard for a debit
      properties:
        receipt-id: 
          $ref: '#/components/schemas/ReceiptId'
        card:
          $ref: '#/components/schemas/Card'
        total:
          $ref: '#/components/schemas/Amount'
        products:
          type: array
          minItems: 0
          items:
            $ref: '#/components/schemas/Product'
      required: [card, total, authorizedate]
          
    Refund:
      description: > 
        Request to create a refund on a fuelcard. 
          * the debit-id is the resource id previously used in capture (capture-id) or charge (charge-id)
          * together with the debit-type it is clear if the debit-id is a capture- or charge-id
      properties:
        receipt-id: 
          $ref: '#/components/schemas/ReceiptId'
        debit-id:
          $ref: '#/components/schemas/ResourceId'
        debit-type: 
          $ref: '#/components/schemas/DebitType'
        amount:
          $ref: '#/components/schemas/Amount'
      required: [debit-id, debit-type, amount]
      
    DebitType:
      type: string
      example:
        CHARGE
      enum: 
        - CAPTURE
        - CHARGE
      description: >
        There are following debit types:
          * 'CAPTURE' - The debit was of type capture
          * 'CHARGE' - The debit was of type charge
          
        A debit (charge or capture) can be refunded.

    ListOfSummary:
      description: A list of summaries
      properties:
        summaries:
          type: array
          items: 
            $ref: '#/components/schemas/SummaryDescription'
          minItems: 0
      required: [summaries]

    SummaryDescription:
      description: Metadata of a summary
      type: object
      properties:
        summary-id:
          allOf:
          - description: the unique id of the summary
          - $ref: '#/components/schemas/SummaryId'
        summary-start:
          allOf:
          - description: start of summary period
          - $ref: '#/components/schemas/DateTime'
        summary-end:
          allOf:
          - description: end of summary period
          - $ref: '#/components/schemas/DateTime'
        summary-created:
          allOf:
          - description: timestamp when the summary has been created
          - $ref: '#/components/schemas/DateTime'
        summary-size:
          description: the number of transactions contained in the summary
          type: integer
          example: 258
      required: [summary-id, summary-start, summary-end, summary-size, summary-created]

    Summary:
      description: List of transactions (charges and refund) for one summary
      type: object
      properties:
        summary-id:
          $ref: '#/components/schemas/SummaryId'
        transactions:
          type: array
          minItems: 0
          items:
            $ref: '#/components/schemas/Transaction'
      required: [summary-id, transactions]

    Transaction:
      description: Base type for Transaction (Charge or Refund)
      properties:
        transaction-type: 
          $ref: '#/components/schemas/TransactionType'
        receipt-id:
          $ref: '#/components/schemas/ReceiptId'
        date-created:
          allOf:
            - $ref: '#/components/schemas/DateTime'
            - description: the date/time the transaction has been created
        amount:
          $ref: '#/components/schemas/Amount'
      allOf:
        - type: object
          properties:
            transaction-id:
              $ref: '#/components/schemas/ResourceId'
      required: [transaction-id, amount,  date-created, type]
  
    TransactionType:
      type: string
      example:
        CHARGE
      enum: 
        - CAPTURE
        - CHARGE
        - REFUND
      description: >
        There are following transaction types:
          * 'CAPTURE' - The transaction is of type capture
          * 'CHARGE' - The transaction is of type charge
          * 'REFUND' - The transaction is of type refund

    DateTime:
      type: string
      format: date-time
      example: "2015-05-28T14:07:17Z"

    ReceiptId:
      type: string
      pattern: '^\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-[A-Z]{4}-[0-9a-fA-F]{1,24}$'
      description: |
        Unique id of the receipt, identifying the business process
        ### Pattern Description
        
        The string must match the following regex pattern: `^\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-[A-Z]{4}-[0-9a-fA-F]{1,24}$`
        
        - `^\d{2}`: The first two digits represent the year (`yy`).
        - `(0[1-9]|1[0-2])`: The next two digits represent the month (`mm`), which must be between `01` and `12`.
        - `(0[1-9]|[12]\d|3[01])`: The next two digits represent the day (`dd`), which must be between `01` and `31`.
        - `-[A-Z]{4}-`: The next segment is a constant string that identifies the business domain, consisting of a hyphen, four uppercase letters, and another hyphen.
        - `[0-9a-fA-F]{1,24}$`: The last segment is a random hexadecimal number, containing between 1 and 24 characters.
        
        ### Summary
        
        - The first six digits represent the date in the format `yymmdd`.
        - The next four characters identify the business domain.
        - The last part, up to 24 characters, is a random hexadecimal number.

      example: "240815-OLBH-8Ca03eBa3ddb0ff"
      
    SummaryId:
      type: string
      pattern: '^(\d{2})(\d{2})(\d{2})PCFC([1-9][0-9]{9})([A-Fa-f0-9]{5})$'
      description: |
        Unique id of the summary
        ### Pattern Explanation
        
        The string must match the following regex pattern: `^\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-PCFC-([1-9][0-9]{9})([A-Fa-f0-9]{5})$`
        
        1. `^`: Indicates the start of the string.
        2. `\d{2}`: The first two digits represent the year (`yy`).
        3. `(0[1-9]|1[0-2])`: The next two digits represent the month (`mm`), which must be between `01` and `12`.
        4. `(0[1-9]|[12]\d|3[01])`: The next two digits represent the day (`dd`), which must be between `01` and `31`.
        5. `-PCFC-`: This is a constant string that stands for "Payment Claim Fuel Card", surrounded by hyphens.
        6. `([1-9][0-9]{9})`: This part is the Business Partner ID, which consists of one digit between 1 and 9 followed by nine digits.
        7. `([A-Fa-f0-9]{5})`: The last five characters must be unique per day and can be any hexadecimal characters (0-9, A-F).
        8. `$`: Indicates the end of the string.
        
        ### Summary
        
        - The first two characters are the year in `yy` format.
        - The next two characters are the month in `mm` format and must be between `01` and `12`.
        - The next two characters are the day in `dd` format and must be between `01` and `31`.
        - `-PCFC-` is a constant string and stands for "Payment Claim Fuel Card".
        - The part `([1-9][0-9]{9})` is the Business Partner ID.
        - The last five characters must be unique per day.
      example: "240729-PCFC-11234567890000A"

    ResourceId:
      type: string
      format: uuid
      description: Unique id of a resource created by the fuelcard provider
      example: "e0811c60-3da5-417f-af70-cc59f47b9577"

    bpId:
      type: string
      pattern: '^\d{10}$'
      description: Unique id of a business partner
      example: "1000201754"

    Card:
      type: object
      description: Identifies the fuel card
      properties:
        brand:
          type: string
          example: "abc"
        cardno:
          type: string
          pattern: "[0-9]*"
          example: '5001878976540310'
        cvv:
          type: string
          pattern: '^\d{0,6}$'
          example: '123454'
        expiry:
          type: string
          example: '0724'
      required: [brand, cardno, expiry]
    Amount:
      type: object
      description: The amount of money and currency
      properties:
        value:
          type: integer
          description: The value in cents
          example: 13560
        currency:
          type: string
          format: iso-4217
          description:  three letter currency codes based on ISO 4217
          example: "CHF"
      required: [value, currency]
        
    Product:
      type: object
      description: A product or service from BAZG
      properties:
        article:
          type: string
          description: Identification of the article
          example: "NMTS"
        description:
          type: string
          description: human readable description of the article - i18n?
          example: "National Manual Toll Service"
        amount:
          $ref: '#/components/schemas/Amount'
      required: [article, amount]

    RejectionReason:
      type: string
      example:
        CARD-EXPIRED
      enum: 
        - CARD-UNKNOWN
        - CARD-EXPIRED
        - CARD-BLOCKED
        - PRODUCT-NOT-ALLOWED
        - PRODUCT-LIMIT-REACHED
        - INVALID-STATE
      description: >
        Rejection reason to be shown to the user:
          * 'CARD-UNKNOWN' - The fuel card referenced is not known
          * 'CARD-EXPIRED' - The fuelcard is expired
          * 'CARD-BLOCKED' - The fuelcard is blocked
          * 'PRODUCT-NOT-ALLOWED' - The fuelcard is not allowed for this product
          * 'PRODUCT-LIMIT-REACHED' - The limit of a certain product paid with this fuelcard has been reached
          * 'INVALID-STATE' - The request could not be completed due to a conflict with the current state of the target resource

  securitySchemes:
    OAuth2ClientCredentials:
      type: oauth2
      description: OAuth2 Client Credentials security scheme
      flows:
        clientCredentials:
          tokenUrl: https://example.com/api/oauth/token
          scopes:
            read: Allows read access
            write: Allows write access
            admin: Allows access to admin operations
