openapi: 3.0.1
info:
  description: >
    This is the documentation for the Ratepay webhook subscription API. This API
    allows to manage webhook subscriptions by creating new subscriptions,

    getting a list of all active subscriptions, updating specific subscriptions
    or cancelling active subscriptions.


    # Payload properties


    The subscription consists of an event type that triggers the call of a URL,
    and a secret that is applied to the payload.

    There is an N:M association between the event type and the URL. A subscriber
    can create multiple event types for one URL and

    it is possible to subscribe to the same event type with different URLs.


    ## ID


    Every subscription is identified with a
    [nanoid](https://github.com/ai/nanoid). The ID is required for updating and
    deleting a subscription.


    ## URL


    The URL is the API resource endpoint the payload is sent to.

    The endpoint **must** be able to process **HTTP POST** requests with payload
    inside the body, no other HTTP method will be called.

    As the API does not inform about an incorrect URL, the correctness should be
    validated by the client.

    For example:

    * https://dev_api.important-merchant.com/customers/invoices

    * https://api-m.sandbox.baseurl.com/v2/customer/orders


    ## Event Type


    Each event type is bound to **one** URL. If it is necessary to respond to
    different event types with the same URL,

    a new subscription is required for each event type.

    The API sends messages to each URL configured for a given event type.


    ## Secret


    The secret enables us to validate Ratepay as the originator of a received
    payload. The secret **must** be at least **64** characters long.

    It is recommended to use one secret per URL to avoid a man-in-the-middle
    attack, but this is not required.

    The webhook service signs the payload using the provided secret with the
    SHA-512 cryptographic hash function.

    The hash is calculated on a string representation of the payload. I.e. if
    the payload is

    ```javascript

    {
      "key": "value"
    }

    ```

    then the input for the hash calculation is `'{"key":"value"}'`. The
    resulting signature for this example with the secret `abc123` would be
    `4c131d60caea39b5f65625b80270e5305d5a00ebc5d15a00ecf82da9de2fcc8ff45df068a11f8b336890b161eb1fdefafe452d2e452623b37e4bd3277bb348fd`.

    The 512-bit signature is inserted in the header named **x-signature**.


    # Retries


    If a webhook call to a configured URL fails, this API will try to repeat the
    identical call at a later time.

    This process is repeated multiple times with increasing intervals between
    retries.

    When the maximum number of retries is reached, an alarm is raised and a
    Ratepay employee is notified.

    No further attempts are made to reach the URL until the error is resolved.

    A webhook call is failed if it either times out or if the response code `x`
    is not in the range `200<=x<300`.
  title: Subscription webhooks
  version: 1.0.0
  contact:
    email: info@ratepay.com
    name: Ratepay
    url: https://www.ratepay.com
servers:
  - description: Ratepay integration platform
    url: https://api-integration.ratepay.com
paths:
  /webhook/management/v1:
    get:
      tags:
        - Endpoints
      summary: Endpoint to retrieve all owned subscriptions.
      description: >-
        Retrieves all subscriptions created and owned by the client identified
        by the JWT token.
      operationId: getSubscriptions
      parameters:
        - name: Authorization
          in: header
          description: >-
            For each request, a valid access token must be provided in the
            Authorization header. See                       [Authentication
            API](/docs/developer/authentication/authentication/) for obtaining a
            valid token.
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Array of subscriptions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArraySubscriptionsDto'
        '403':
          description: Bad request due to corrupt or invalid authentication information.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_403'
        '405':
          description: Bad request because the HTTP method is not allowed.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_405'
        '406':
          description: >-
            Bad request because the server cannot produce a response matching
            the list of acceptable values.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_406'
        '500':
          description: An internal server error occurred while processing the request.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_500'
    post:
      tags:
        - Endpoints
      description: Creates a new webhook subscription accessible only to the client.
      operationId: createSubscription
      parameters:
        - name: Authorization
          in: header
          description: >-
            For each request, a valid access token must be provided in the
            Authorization header. See                       [Authentication
            API](/docs/developer/authentication/authentication/) for obtaining a
            valid token.
          required: true
          schema:
            type: string
      summary: Endpoint to create a new subscription.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubscriptionDto'
      responses:
        '201':
          description: The subscription was created.
          headers:
            Location:
              description: The URL to retrieve all owned subscriptions.
              schema:
                type: string
                format: url
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionDto'
        '400':
          description: >-
            Bad request due to a client error in path parameters, header or
            body.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_400'
        '405':
          description: Bad request because the HTTP method is not allowed.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_405'
        '406':
          description: >-
            Bad request because the server cannot produce a response matching
            the list of acceptable values.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_406'
        '415':
          description: Bad request because the payload format is not supported.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_415'
        '500':
          description: An internal server error occurred while processing the request.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_500'
  /webhook/management/v1/{id}:
    put:
      tags:
        - Endpoints
      summary: Endpoint to update the properties of the subscription.
      operationId: updateSubscription
      description: >
        # Update Subscription

        ---


        The request body must contain the complete information about the
        subscription.


        The following values can be updated: The __URL__ used for the webhook,
        the __event type__ applied to this URL and the __secret__, which is used
        to sign the payload.

        It is not possible to change the identification of the subscription.


        Omitting properties from the request body (e.g. secret) will result in a
        validation error and return the status code 400.
      parameters:
        - in: path
          name: id
          schema:
            $ref: '#/components/schemas/id'
          required: true
          description: Subscription ID received when creating a subscription.
        - name: Authorization
          in: header
          description: >-
            For each request, a valid access token must be provided in the
            Authorization header. See                       [Authentication
            API](/docs/developer/authentication/authentication/) for obtaining a
            valid token.
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionWihoutIdDto'
      responses:
        '200':
          description: OK. The subscription was updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionDto'
        '400':
          description: >-
            Bad request due to a client error in path parameters, header or
            body.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_400'
        '401':
          description: Bad request because the client cannot be authorized.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_401'
        '403':
          description: >-
            Bad request because the client is not allowed to update the
            resource.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_403'
        '404':
          description: Bad request because the resource cannot be found.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_404'
        '405':
          description: Bad request because the HTTP method is not allowed.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_405'
        '406':
          description: >-
            Bad request because the server cannot produce a response matching
            the list of acceptable values.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_406'
        '415':
          description: Bad request because the payload format is not supported.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_415'
        '500':
          description: An internal server error occured while processing the request.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_500'
    delete:
      tags:
        - Endpoints
      summary: Endpoint to unsubscribe from the subscription.
      description: To resubscribe, you need to create a new subscription.
      operationId: deleteSubscription
      parameters:
        - in: path
          name: id
          schema:
            $ref: '#/components/schemas/id'
          required: true
          description: ID of the subscription to be deleted.
        - name: Authorization
          in: header
          description: >-
            For each request, a valid access token must be provided in the
            Authorization header. See                       [Authentication
            API](/docs/developer/authentication/authentication/) for obtaining a
            valid token.
          required: true
          schema:
            type: string
      responses:
        '204':
          description: OK. The subscription was successfully deleted.
        '400':
          description: >-
            Bad request due to a client error in path parameters, header or
            body.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_400'
        '401':
          description: Bad request because the client cannot be authorized.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_401'
        '403':
          description: >-
            Bad request because the client is not allowed to delete the
            resource.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_403'
        '404':
          description: Bad request because the resource cannot be found.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_404'
        '405':
          description: Bad request because the HTTP method is not allowed.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_405'
        '406':
          description: >-
            Bad request because the server cannot produce a response matching
            the list of acceptable values.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_406'
        '500':
          description: An internal server error occurred while processing the request.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/status_code_500'
security:
  - JSON Web Token: []
components:
  securitySchemes:
    JSON Web Token:
      description: >
        The authorization of an API user is validated through a JSON Web Token
        (JWT). The token should be located in the header as:


        * `Authorization: Bearer <jwttoken>`


        The process to request a token is described in the [ratepay
        authentication
        documentation.](/docs/developer/authentication/authentication/)
      type: http
      scheme: bearer
      bearerFormat: JSON Web Token
  schemas:
    id:
      type: string
      description: ID of the subscription.
      example: d8znR1k1_0Kw305BsoPT
      minLength: 20
      maxLength: 20
      pattern: ([A-Za-z0-9_-]{20})
    id_object:
      type: object
      properties:
        id:
          $ref: '#/components/schemas/id'
    ArraySubscriptionsDto:
      description: Array of subscriptions.
      type: array
      items:
        $ref: '#/components/schemas/SubscriptionDto'
    SubscriptionDto:
      type: object
      description: Subscription element.
      properties:
        id:
          $ref: '#/components/schemas/id'
        url:
          type: string
          format: url
          description: HTTP URL to execute the webhook call with the POST method.
          example: https://api.merchant.com/event
        event_type:
          type: string
          description: Type of the event to process by calling the API endpoint.
          example: INVOICE_INVOICE
        secret:
          type: string
          minLength: 64
          description: >-
            Parameter given by the client to sign their payloads. Recommended to
            be unique for each URL.
          example: 6GHbLH4d1Nx3eIs5CyLHCW4HuFi1qttpNSDawHKHlW7kurTpaddarwEKDWUI59IU
    CreateSubscriptionDto:
      type: object
      description: Subscription element.
      required:
        - url
        - event_type
        - secret
      properties:
        url:
          $ref: '#/components/schemas/SubscriptionDto/properties/url'
        event_type:
          $ref: '#/components/schemas/SubscriptionDto/properties/event_type'
        secret:
          $ref: '#/components/schemas/SubscriptionDto/properties/secret'
    SubscriptionWihoutIdDto:
      type: object
      description: Subscription element.
      required:
        - url
        - event_type
        - secret
      properties:
        url:
          $ref: '#/components/schemas/SubscriptionDto/properties/url'
        event_type:
          $ref: '#/components/schemas/SubscriptionDto/properties/event_type'
        secret:
          $ref: '#/components/schemas/SubscriptionDto/properties/secret'
    status_code_400:
      description: Bad request due to a client error in path parameters, header or body.
      type: object
      properties:
        name:
          type: string
          example: ValidationError
        message:
          type: string
          example: Error while validating the JWT token.
          description: A message containing the error.
    status_code_401:
      description: Bad request because the client could not be authorized.
      type: object
      properties:
        name:
          type: string
          example: UnauthorizedError
        message:
          type: string
          example: Bad request because the client could not be authorized.
          description: A message containing the error.
    status_code_403:
      description: Bad request because the client is not allowed to access the resource.
      type: object
      properties:
        name:
          type: string
          example: ForbiddenError
        message:
          type: string
          example: >-
            Bad request because the client is not allowed to update the
            resource.
          description: A message containing the error.
    status_code_404:
      description: Bad request because the resource cannot be found.
      type: object
      properties:
        name:
          type: string
          example: NotFoundError
        message:
          type: string
          example: Bad request because the resource cannot be found.
          description: A message containing the error.
    status_code_405:
      description: Bad request because the HTTP method is not allowed.
      type: object
      properties:
        message:
          type: string
          example: Bad request because the HTTP method is not allowed.
          description: A message containing the error.
    status_code_406:
      description: >-
        Bad request because the server cannot produce a response matching the
        list of acceptable values.
      type: object
      properties:
        message:
          type: string
          example: >-
            Bad request because the server cannot produce a response matching
            the list of acceptable values.
          description: A message containing the error.
    status_code_415:
      description: Bad request because the payload format is not supported.
      type: object
      properties:
        message:
          type: string
          example: Bad request because the payload format is not supported.
          description: A message containing the error.
    status_code_500:
      type: object
      properties:
        message:
          type: string
          example: Invalid authorization token.
          description: A message containing the error.
