openapi: 3.1.0
info:
  title: One Time Passcode API
  description: >-
    The One Time Passcode (OTP) API is a JSON-based RESTful API that enables
    merchants to verify OTP codes sent to buyers.
  contact:
    name: Ratepay GmbH
    url: https://www.ratepay.com/
    email: info@ratepay.com
  version: 1.0.0
servers:
  - url: https://api.ratepay.com
    description: Ratepay Production Platform
  - url: https://api-integration.ratepay.com
    description: Ratepay Integration Platform
paths:
  /transaction/management/2fa/v1/verify/{transactionId}:
    post:
      tags:
        - One Time Passcode
      summary: Validate an OTP code
      operationId: verifyCode
      parameters:
        - name: transactionId
          in: path
          description: The id of the transaction that initialized the OTP process
          required: true
          schema:
            type: string
            description: The id of the transaction that initialized the OTP process
            example: 684CWYHCK05X2CN5K_N6
          example: 684CWYHCK05X2CN5K_N6
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerificationRequestDto'
        required: true
      responses:
        '200':
          description: OTP code verified successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                OTP code verified successfully:
                  $ref: '#/components/examples/verify_success'
        '400':
          description: >-
            Input validation error. The sent request could not be parsed or was
            otherwise invalid. The response will include information on the
            wrong fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Invalid request:
                  $ref: '#/components/examples/verify_input_validation'
        '401':
          description: >-
            Failed to authorize the client. Authorization information is either
            missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                No authorization information provided:
                  $ref: '#/components/examples/verify_no_authorization_info'
                Authorization information is invalid:
                  $ref: '#/components/examples/verify_invalid_authorization_info'
                Authorization information is incomplete:
                  $ref: '#/components/examples/verify_no_claims_provided'
        '403':
          description: The client is not authorized to perform the requested operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Client is not authorized to access the requested transaction:
                  $ref: '#/components/examples/verify_transaction_access_not_allowed'
        '404':
          description: The transaction either does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Transaction does not exist:
                  $ref: '#/components/examples/verify_transaction_not_found'
        '422':
          description: >-
            OTP verification failed because the provided OTP code was invalid or
            OTP process failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Invalid OTP code provided:
                  $ref: '#/components/examples/verify_attempt_failed'
                Invalid OTP code provided, no more attempts left:
                  $ref: '#/components/examples/verify_no_attempts_left'
                Transaction has reached a terminal state:
                  $ref: '#/components/examples/verify_otp_failed'
        '500':
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Unexpected server error:
                  $ref: '#/components/examples/verify_server_error'
      security:
        - Bearer: []
  /transaction/management/2fa/v1/regenerate/{transactionId}:
    post:
      tags:
        - One Time Passcode
      summary: Regenerate OTP code for an active OTP process
      operationId: regenerate
      parameters:
        - name: transactionId
          in: path
          description: The id of the transaction that initialized the OTP process
          required: true
          schema:
            type: string
            description: The id of the transaction that initialized the OTP process
            example: 684CWYHCK05X2CN5K_N6
            minLength: 1
          example: 684CWYHCK05X2CN5K_N6
      responses:
        '200':
          description: OTP code was regenerated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendResponseDtoEntityModel'
              examples:
                OTP regenerated successful:
                  $ref: '#/components/examples/regenerate_success'
        '401':
          description: >-
            Failed to authorize the client. Authorization information is either
            missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                No authorization information provided:
                  $ref: '#/components/examples/regenerate_no_authorization_info'
                Authorization information is invalid:
                  $ref: '#/components/examples/regenerate_invalid_authorization_info'
                Authorization information is incomplete:
                  $ref: '#/components/examples/regenerate_no_claims_provided'
        '403':
          description: The client is not authorized to perform the requested operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Client is not authorized to access the requested transaction:
                  $ref: >-
                    #/components/examples/regenerate_transaction_access_not_allowed
        '422':
          description: >-
            OTP regeneration is not possible at the moment. Client should wait.
            or No more regeneration are allowed or The transaction is in a
            "terminal state" (successful, failed, etc.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                OTP code regeneration time not reached.:
                  $ref: '#/components/examples/regenerate_time_not_reached'
                No more regeneration attempts left:
                  $ref: '#/components/examples/regenerate_no_attempts_left'
                Transaction has reached a terminal state:
                  $ref: >-
                    #/components/examples/regenerate_active_transaction_not_found
        '429':
          description: >-
            Too Many Requests. The daily or total live SMS rate limit has been
            exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Daily limit exceeded response:
                  $ref: >-
                    #/components/examples/regenerate_daily_live_sms_rate_limit_exceeded
                Total limit exceeded response:
                  $ref: >-
                    #/components/examples/regenerate_total_live_sms_rate_limit_exceeded
        '500':
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponseDtoEntityModel'
              examples:
                Unexpected server error:
                  $ref: '#/components/examples/regenerate_internal_server_error'
      security:
        - Bearer: []
components:
  schemas:
    VerificationRequestDto:
      type: object
      description: Message sent to verify a OTP code
      properties:
        otp_code:
          type: string
          description: The OTP code given by the customer
          example: 15316
          minLength: 1
      required:
        - otp_code
    ApiResponseDtoEntityModel:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
          description: When the response was generated
        regeneration_possible_in_seconds:
          type: integer
          format: int64
          description: >-
            The time until another OTP can be sent. Might be null in error
            responses or when the OTP is verified.
        ratepay_transaction_id:
          type: string
          description: The id of the transaction that was tied to the OTP process
          example: 684CWYHCK05X2CN5K_N6
          minLength: 1
        result:
          type: string
          $ref: '#/components/schemas/ApiResponseDto_result'
          minLength: 1
        message:
          $ref: '#/components/schemas/ApiResponseDto_message'
        _links:
          $ref: '#/components/schemas/Links'
      required:
        - message
        - ratepay_transaction_id
        - result
        - timestamp
    SendResponseDtoEntityModel:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
          description: When the response was generated
        regeneration_possible_in_seconds:
          type: integer
          format: int64
          description: >-
            The time until another OTP can be sent. Might be null in error
            responses or when the OTP is verified.
        ratepay_transaction_id:
          type: string
          description: The id of the transaction that was tied to the OTP process
          example: 684CWYHCK05X2CN5K_N6
          minLength: 1
        result:
          type: string
          $ref: '#/components/schemas/ApiResponseDto_result'
          minLength: 1
        message:
          $ref: '#/components/schemas/ApiResponseDto_message'
        time_to_live_in_seconds:
          type: integer
          format: int64
          description: >-
            The time until the OTP process will expire and the OTP will be
            invalid.
        _links:
          $ref: '#/components/schemas/Links'
      required:
        - message
        - ratepay_transaction_id
        - result
        - time_to_live_in_seconds
        - timestamp
    Link:
      type: object
      properties:
        href:
          type: string
        hreflang:
          type: string
        title:
          type: string
        type:
          type: string
        deprecation:
          type: string
        profile:
          type: string
        name:
          type: string
        templated:
          type: boolean
    Links:
      type: object
      additionalProperties:
        $ref: '#/components/schemas/Link'
    ApiResponseDto_result:
      description: The machine-readable outcome of the operation of the OTP process
      enum:
        - otp_sent
        - unexpected_client_input
        - otp_verified
        - otp_regenerated
        - unexpected_server_error
        - otp_exists
        - otp_failed
        - verify_attempt_failed
        - no_more_verification_attempts_left
        - transaction_not_found
        - no_more_regeneration_attempts_left
        - retry_regeneration_later
        - no_authorization_data_provided
        - authorization_data_invalid
        - no_claims_provided
        - authorization_data_not_processable
        - transaction_access_not_allowed
        - otp_live_daily_sms_rate_limit_exceeded
        - otp_live_total_sms_rate_limit_exceeded_talk_to_ratepay
    ApiResponseDto_message:
      description: A detailed description of the outcome in English and German
      example:
        en: Your code has been successfully verified.
        de: Ihr Code wurde erfolgreich überprüft.
  examples:
    verify_success:
      value:
        timestamp: '2025-10-02T09:14:37.507714Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: otp_verified
        message:
          en: Your code has been successfully verified.
          de: Ihr Code wurde erfolgreich überprüft.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_input_validation:
      value:
        timestamp: '2025-10-02T09:14:37.507728Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: unexpected_client_input
        message:
          en: Unexpected client input
          de: Unerwartete Eingabe vom Client
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_transaction_not_found:
      value:
        timestamp: '2025-10-02T09:14:37.507730Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: transaction_not_found
        message:
          en: 'Transaction not found: 684CWYHCK05X2CN5K_N6.'
          de: 'Transaktion nicht gefunden: 684CWYHCK05X2CN5K_N6.'
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_attempt_failed:
      value:
        timestamp: '2025-10-02T09:14:37.507733Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: verify_attempt_failed
        message:
          en: Verify attempt failed, please try again.
          de: Verifizierungsversuch fehlgeschlagen, bitte versuchen Sie es erneut.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_no_attempts_left:
      value:
        timestamp: '2025-10-02T09:14:37.507735Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: no_more_verification_attempts_left
        message:
          en: Verification failed, no more attempt left.
          de: Verifizierung fehlgeschlagen, keine weiteren Versuche übrig.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_otp_failed:
      value:
        timestamp: '2025-10-02T09:14:37.507737Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: otp_failed
        message:
          en: The transaction 684CWYHCK05X2CN5K_N6 failed.
          de: Die Transaktion 684CWYHCK05X2CN5K_N6 ist fehlgeschlagen.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_server_error:
      value:
        timestamp: '2025-10-02T09:14:37.507739Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: unexpected_server_error
        message:
          en: Unexpected error occurred. Please try again later.
          de: >-
            Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es
            später noch einmal.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_no_authorization_info:
      value:
        timestamp: '2025-10-02T09:14:37.507742Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: no_authorization_data_provided
        message:
          en: The client needs to provide authorization information.
          de: Der Client muss Autorisierungsinformationen bereitstellen.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_invalid_authorization_info:
      value:
        timestamp: '2025-10-02T09:14:37.507744Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: authorization_data_invalid
        message:
          en: The provided authorization information is invalid.
          de: Die Autorisierungsinformationen sind ungültig.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_no_claims_provided:
      value:
        timestamp: '2025-10-02T09:14:37.507747Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: no_claims_provided
        message:
          en: The provided authorization information is incomplete.
          de: Die Autorisierungsinformationen sind unvollständig.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    verify_transaction_access_not_allowed:
      value:
        timestamp: '2025-10-02T09:14:37.507749Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: transaction_access_not_allowed
        message:
          en: The client is not allowed to access the transaction.
          de: Dem Client ist der Zugriff auf die Transaktion nicht gestattet.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    regenerate_success:
      value:
        timestamp: '2025-10-02T09:14:37.507764Z'
        regenerationPossibleInSeconds: 60
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: otp_sent
        message:
          en: The code has been sent to your phone number 0049123411223344.
          de: Der Code wurde an Ihre Telefonnummer 0049123411223344 gesendet.
        timeToLiveInSeconds: 120
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
          - rel: verify
            href: /transaction/management/2fa/v1/verify/684CWYHCK05X2CN5K_N6
    regenerate_active_transaction_not_found:
      value:
        timestamp: '2025-10-02T09:14:37.507766Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: otp_failed
        message:
          en: The transaction 684CWYHCK05X2CN5K_N6 failed.
          de: Die Transaktion 684CWYHCK05X2CN5K_N6 ist fehlgeschlagen.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_time_not_reached:
      value:
        timestamp: '2025-10-02T09:14:37.507770Z'
        regenerationPossibleInSeconds: 60
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: retry_regeneration_later
        message:
          en: >-
            Regenerating a new code is not possible at the moment, please retry
            in 60 seconds.
          de: >-
            Das Erzeugen eines neuen Codes ist momentan nicht möglich, bitte
            versuchen Sie es in 60 Sekunden erneut.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_no_attempts_left:
      value:
        timestamp: '2025-10-02T09:14:37.507773Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: no_more_regeneration_attempts_left
        message:
          en: >-
            Regenerating a new code is not possible, maximum number of attempts
            reached.
          de: >-
            Das Erzeugen eines neuen Codes ist nicht möglich, die maximale
            Anzahl an Versuchen wurde erreicht.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_internal_server_error:
      value:
        timestamp: '2025-10-02T09:14:37.507775Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: unexpected_server_error
        message:
          en: Unexpected error occurred. Please try again later.
          de: >-
            Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es
            später noch einmal.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_no_authorization_info:
      value:
        timestamp: '2025-10-02T09:14:37.507777Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: no_authorization_data_provided
        message:
          en: The client needs to provide authorization information.
          de: Der Client muss Autorisierungsinformationen bereitstellen.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_invalid_authorization_info:
      value:
        timestamp: '2025-10-02T09:14:37.507779Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: authorization_data_invalid
        message:
          en: The provided authorization information is invalid.
          de: Die Autorisierungsinformationen sind ungültig.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_no_claims_provided:
      value:
        timestamp: '2025-10-02T09:14:37.507781Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: no_claims_provided
        message:
          en: The provided authorization information is incomplete.
          de: Die Autorisierungsinformationen sind unvollständig.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_transaction_access_not_allowed:
      value:
        timestamp: '2025-10-02T09:14:37.507783Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: transaction_access_not_allowed
        message:
          en: The client is not allowed to access the transaction.
          de: Dem Client ist der Zugriff auf die Transaktion nicht gestattet.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_daily_live_sms_rate_limit_exceeded:
      value:
        timestamp: '2025-10-02T09:14:37.507785Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: otp_live_daily_sms_rate_limit_exceeded
        message:
          en: The daily rate limit for Live SMS OTPs has been exceeded.
          de: >-
            Die Tagesbegrenzung für die Live SMS Einmal-Codes wurde
            überschritten.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
    regenerate_total_live_sms_rate_limit_exceeded:
      value:
        timestamp: '2025-10-02T09:14:37.507785Z'
        ratepayTransactionId: 684CWYHCK05X2CN5K_N6
        result: otp_live_total_sms_rate_limit_exceeded_talk_to_ratepay
        message:
          en: >-
            The total rate limit for Live SMS OTPs has been exceeded. Please
            contact Ratepay.
          de: >-
            Die Gesamtbegrenzung für die Live SMS Einmal-Codes wurde
            überschritten. Bitte wenden Sie sich an Ratepay.
        links:
          - rel: self
            href: /transaction/management/2fa/v1/regenerate/684CWYHCK05X2CN5K_N6
  securitySchemes:
    Bearer:
      type: http
      description: >-
        Every request must be authenticated with a valid JWT token. See the
        authentication API for more information.
      scheme: bearer
      bearerFormat: JWT
