openapi: 3.1.0
info:
  title: Webhook API
  version: 1.0.0
  description: |
    This document provides an overview of the webhooks supported by the V2 platform. Each webhook request includes the following headers:

    - `x-webhook-id`: Unique ID of the event. The same ID will be sent if the webhook is redelivered.
    - `x-webhook-dispatch-attempt-count`: Dispatch attempt count.
    - `x-webhook-payload-hash`: HMAC-SHA1 hash of the webhook payload (generated using the provided secret key).

      Example in PHP:
      ```php
      $payload = '{}';
      $secretKey = 'secret-key';
      $hmac = hash_hmac('sha1', $payload, $secretKey);
      ```
      Example in Node.js:
      ```js
      const crypto = require('crypto');
      const payload = '{}';
      const secretKey = 'secret-key';
      const hmac = crypto.createHmac('sha1', secretKey).update(payload).digest('hex');
      ```
    
    - `x-event-created-at`: Time at which the event occurred.
    - `x-event-created-at-epoch`: Time at which the event occurred as an epoch timestamp.
    - `x-api-key`: API key used to authenticate with the recipient.

paths:
  /:
    post:
      operationId: acceptWebhook
      summary: Receive a webhook
      description: Endpoint to receive a webhook. The semantics depend on the specific endpoint.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Webhook"
            examples:
              ReservationStarted:
                summary: ReservationStarted webhook
                value:
                  type: "RESERVATION_STARTED"
                  timestamp: "2025-03-03T12:00:00Z"
                  data:
                    id: 45232
              RentalStarted:
                summary: RentalStarted webhook
                value:
                  type: "RENTAL_STARTED"
                  timestamp: "2025-03-03T12:00:00Z"
                  data:
                    id: 12345
              RentalEnded:
                summary: RentalEnded webhook
                value:
                  type: "RENTAL_ENDED"
                  timestamp: "2025-03-03T14:30:00Z"
                  data:
                    id: 67890
              UserCreated:
                summary: UserCreated webhook
                value:
                  type: "USER_CREATED"
                  timestamp: "2025-03-03T12:00:00Z"
                  data:
                    id: 712
              UserLicenseApproved:
                summary: UserLicenseApproved webhook
                value:
                  type: "USER_LICENSE_APPROVED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    userId: 112233
              UserPaymentMethodAdded:
                summary: UserPaymentMethodAdded webhook
                value:
                  type: "USER_PAYMENT_METHOD_ADDED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    userId: 123235
              VehicleServiceStateChanged:
                summary: VehicleServiceStateChanged webhook
                value:
                  type: "VEHICLE_SERVICE_STATE_CHANGED"
                  timestamp: "2025-03-03T12:00:00Z"
                  data:
                    id: 43
                    previousState: "FUNCTIONAL"
                    newState: "RETIRED"
              VehicleMovedOutsideRental:
                summary: VehicleMovedOutsideRental webhook
                value:
                  type: "VEHICLE_MOVED_OUTSIDE_RENTAL"
                  timestamp: "2025-03-03T12:00:00Z"
                  data:
                    id: 43
              InvoiceCreated:
                summary: InvoiceCreated webhook
                value:
                  type: "INVOICE_CREATED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    id: 32
                    invoiceNumber: "DE-1234567"
                    userId: 2034
                    totalGross: 10.00
                    totalNet: 8.00
                    taxAmount: 2.00
                    taxRate: 25
                    currencyCode: "EUR"
                    type: "INVOICE"
                    lineItems:
                      - id: 1
                        type: "PRICE"
                        grossPrice: 10.00
                        netPrice: 8.00
                        taxAmount: 2.00
                        taxRate: 25
                        rentalId: 900
                      - id: 2
                        type: "PRICE"
                        grossPrice: 5.00
                        netPrice: 4.00
                        taxAmount: 1.00
                        taxRate: 25
                        bookingId: 901
                      - id: 3
                        type: "FULL_REFUND"
                        grossPrice: -5.00
                        netPrice: -4.00
                        taxAmount: -1.00
                        taxRate: 25
                        refundedInvoiceLineItemId: 2
              InvoicePaymentFailed:
                summary: InvoicePaymentFailed webhook
                value:
                  type: "INVOICE_PAYMENT_FAILED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    id: 32
              InvoicePaid:
                summary: InvoicePaid webhook
                value:
                  type: "INVOICE_PAID"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    id: 32
              InvoiceRefunded:
                summary: InvoiceRefunded webhook
                value:
                  type: "INVOICE_REFUNDED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    id: 32
                    invoiceNumber: "DE-1234567"
                    userId: 2034
                    totalGross: -10.00
                    totalNet: -8.00
                    taxAmount: -2.00
                    taxRate: 25
                    currencyCode: "EUR"
                    type: "REFUND"
                    lineItems:
                      - id: 3
                        type: "PARTIAL_REFUND"
                        grossPrice: -5.00
                        netPrice: -4.00
                        taxAmount: -1.00
                        taxRate: 25
                        refundedInvoiceId: 21
                        refundedInvoiceLineItemId: 4
                      - id: 4
                        type: "FULL_REFUND"
                        grossPrice: -5.00
                        netPrice: -4.00
                        taxAmount: -1.00
                        taxRate: 25
                        refundedInvoiceId: 21
                        refundedInvoiceLineItemId: 7
              VoucherRedeemed:
                summary: VoucherRedeemed webhook
                value:
                  type: "VOUCHER_REDEEMED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    voucherId: 34
                    userId: 21
                    voucherCode: KE3D3ABM
              IssueCreated:
                summary: IssueCreated webhook
                value:
                  type: "ISSUE_CREATED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    id: 14
                    category: PARKING_PROBLEM
              PackagePurchased:
                summary: PackagePurchased webhook
                value:
                  type: "PACKAGE_PURCHASED"
                  timestamp: "2025-03-03T09:15:00Z"
                  data:
                    packageId: 123
                    userId: 23
              TaskCreated:
                summary: TaskCreated webhook
                value:
                  type: "TASK_CREATED"
                  timestamp: "2025-03-03T14:45:00Z"
                  data:
                    taskId: 456
                    vehicleId: 789
                    rentalId: 123
                    userId: 321
                    status: "NEW"
                    priority: "HIGH"
                    category: "MAINTENANCE"
                    categoryInfo:
                      id: 1
                      name: "Maintenance"
                    title: "Replace front tire"
                    description: "Front left tire needs replacement"
              TaskUpdated:
                summary: TaskUpdated webhook
                value:
                  type: "TASK_UPDATED"
                  timestamp: "2025-03-03T14:45:00Z"
                  data:
                    taskId: 456
                    vehicleId: 789
                    previousStatus: "NEW"
                    newStatus: "IN_PROGRESS"
      responses:
        "200":
          description: Webhook received successfully

components:
  schemas:
    Webhook:
      oneOf:
        - $ref: '#/components/schemas/ReservationStarted'
        - $ref: '#/components/schemas/RentalStarted'
        - $ref: '#/components/schemas/RentalEnded'
        - $ref: '#/components/schemas/UserCreated'
        - $ref: '#/components/schemas/UserLicenseApproved'
        - $ref: '#/components/schemas/VehicleServiceStateChanged'
        - $ref: '#/components/schemas/VehicleMovedOutsideRental'
        - $ref: '#/components/schemas/InvoiceCreated'
        - $ref: '#/components/schemas/InvoicePaymentFailed'
        - $ref: '#/components/schemas/InvoicePaid'
        - $ref: '#/components/schemas/InvoiceRefunded'
        - $ref: '#/components/schemas/VoucherRedeemed'
        - $ref: '#/components/schemas/IssueCreated'
        - $ref: '#/components/schemas/PackagePurchased'
        - $ref: '#/components/schemas/UserPaymentMethodAdded'
        - $ref: '#/components/schemas/TaskCreated'
        - $ref: '#/components/schemas/TaskUpdated'
      discriminator:
        propertyName: type
        mapping:
          RESERVATION_STARTED: '#/components/schema/ReservationStarted'
          RENTAL_STARTED: '#/components/schema/RentalStarted'
          RENTAL_ENDED: '#/components/schema/RentalEnded'
          USER_CREATED: '#/components/schema/UserCreated'
          USER_LICENSE_APPROVED: '#/components/schema/UserLicenseApproved'
          USER_PAYMENT_METHOD_ADDED: '#/components/schema/UserPaymentMethodAdded'
          VEHICLE_SERVICE_STATE_CHANGED: '#/components/schema/VehicleServiceStateChanged'
          VEHICLE_MOVED_OUTSIDE_RENTAL: '#/components/schema/VehicleMovedOutsideRental'
          INVOICE_CREATED: '#/components/schema/InvoiceCreated'
          INVOICE_PAYMENT_FAILED: '#/components/schema/InvoicePaymentFailed'
          INVOICE_PAID: '#/components/schema/InvoicePaid'
          INVOICE_REFUNDED: '#/components/schema/InvoiceRefunded'
          VOUCHER_REDEEMED: '#/components/schema/VoucherRedeemed'
          ISSUE_CREATED: '#/components/schema/IssueCreated'
          PACKAGE_PURCHASED: '#/components/schema/PackagePurchased'
          TASK_CREATED: '#/components/schema/TaskCreated'
          TASK_UPDATED: '#/components/schema/TaskUpdated'

    WebhookData:
      type: object
      properties:
        type:
          type: string
        timestamp:
          type: string
          format: date-time
          example: "2025-03-03T12:00:00Z"

    VehicleServiceState:
      type: string
      enum:
        - FUNCTIONAL
        - INSPECT
        - RELOCATE
        - COLLECT
        - SERVICE_ON_SITE
        - SERVICE_WORKSHOP
        - SERVICE_EXTERNAL
        - REPLACE
        - IMPOUNDED
        - LOST
        - RETIRED
        - OTHER
        - READY_FOR_DEPLOYMENT
        - MAINTENANCE
        - WAITING_FOR_PARTS
        - UNREPAIRABLE
        - DEFLEETED

    IssueCategory:
      type: string
      enum:
        - FINE
        - ACCIDENT
        - VEHICLE_PARTS_MISSING
        - VEHICLE_NEEDS_SERVICE
        - VEHICLE_NEEDS_INSPECTION
        - VEHICLE_NOT_READY
        - VEHICLE_DAMAGED
        - VEHICLE_COMMUNICATION
        - PARKING_PROBLEM
        - PURCHASE
        - TOLL
        - INSURANCE
        - DELIVERY

    TaskState:
      type: string
      enum:
        - NEW
        - IN_PROGRESS
        - RECURRING
        - COMPLETED

    TaskPriority:
      type: string
      enum:
        - LOW
        - NORMAL
        - HIGH
        - SEVERE

    TaskCategory:
      type: string
      enum:
        - MAINTENANCE
        - CLEANING
        - RELOCATION
        - INSPECTION
        - LOW_SOC
        - VEHICLE_SWAP
        - DAMAGE
        - ACCESS_AND_TELEMATICS
        - VEHICLE_FAULT
        - REGULATORY_AND_COMPLIANCE
        - BILLING_AND_CUSTOMER_CHARGE
        - ADMINISTRATIVE

    RentalEnded:
      description: Webhook published when a rental ends
      title: RentalEnded
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ RENTAL_ENDED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: rental identifier of the rental that ended

    
    RentalStarted:
      description: Webhook published when a rental starts
      title: RentalStarted
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ RENTAL_STARTED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: rental identifier of the rental that started

    ReservationStarted:
      description: Webhook published when a reservation starts
      title: ReservationStarted
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ RESERVATION_STARTED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: rental identifier of the rental that started

    UserCreated:
      description: Webhook published when a user is created
      title: UserCreated
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ USER_CREATED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the user that was created

    UserLicenseApproved:
      description: Webhook published when the license of a user has been approved
      title: UserLicenseApproved
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ USER_LICENSE_APPROVED ]
            data:
              type: object
              properties:
                userId:
                  type: integer
                  format: int64
                  description: user identifier of the approved license

    UserPaymentMethodAdded:
      description: Webhook published when a user payment method is added
      title: UserPaymentMethodAdded
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ USER_PAYMENT_METHOD_ADDED ]
            data:
              type: object
              properties:
                userId:
                  type: integer
                  format: int64
                  description: user identifier of the added payment method

    VehicleServiceStateChanged:
      description: Webhook published when the vehicle's service state is changed
      title: VehicleServiceStateChanged
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ VEHICLE_SERVICE_STATE_CHANGED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the vehicle whose service state has changed
                previousState:
                  $ref: "#/components/schemas/VehicleServiceState"
                  description: the previous service state
                newState:
                  $ref: "#/components/schemas/VehicleServiceState"
                  description: the new service state

    VehicleMovedOutsideRental:
      description: Webhook published when a vehicle is moved outside a rental
      title: VehicleMovedOutsideRental
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ VEHICLE_MOVED_OUTSIDE_RENTAL ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the vehicle that moved outside a rental

    InvoiceCreated:
      description: Webhook published when an invoice is created
      title: InvoiceCreated
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ INVOICE_CREATED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the created invoice
                invoiceNumber:
                  type: string
                  description: Number of the invoice
                userId:
                  description: Identifier of the user the invoice was created for
                  type: integer
                  format: int64
                totalGross:
                  description: Total gross amount of the invoice
                  type: number
                totalNet:
                  description: Total net amount of the invoice
                  type: number
                taxAmount:
                  description: Total tax amount of the invoice
                  type: number
                taxRate:
                  description: Tax rate of the invoice
                  type: number
                currencyCode:
                  description: Currency of the invoice
                  type: string
                type:
                  type: string
                  enum:
                    - INVOICE
                    - ISSUE
                    - VOUCHER_PURCHASE
                    - REFUND
                lineItems:
                  type: array
                  items:
                    $ref: '#/components/schemas/InvoiceLineItem'
    InvoiceLineItem:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: Unique identifier of this line item
        type:
          type: string
          enum:
            - PRICE
            - PARTIAL_REFUND
            - FULL_REFUND
          description: |
            Type of the line item.
            
            PRICE - line item is for a purchase (voucher), rental fee, booking fee, etc.
            PARTIAL_REFUND - line item is a partial refund of another line item
            FULL_REFUND - line item is a full refund of another line item
        grossPrice:
          type: number
          description: gross price of the line item
        netPrice:
          type: number
          description: net price of the line item
        taxAmount:
          type: number
          description: tax amount of the line item
        taxRate:
          type: number
          description: tax rate of the line item
        rentalId:
          type: integer
          format: int64
          description: Rental identifier if this line item is for invoicing of a rental.
        bookingId:
          type: integer
          format: int64
          description: Booking identifier if this line item is for invoicing of a booking
        refundedInvoiceId:
          type: integer
          format: int64
          description: |
            Identifier of the invoice where a line item was refunded.
            Only set if the refunded line item's invoice is different from this line item's
        refundedInvoiceLineItemId:
          type: integer
          format: int64
          description: Identifier of the line item that was refunded.
    InvoicePaymentFailed:
      description: Webhook published when an invoice payment fails
      title: InvoicePaymentFailed
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ INVOICE_PAYMENT_FAILED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the invoice whose payment has failed

    InvoicePaid:
      description: Webhook published when an invoice is paid
      title: InvoicePaid
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ INVOICE_PAID ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the paid invoice

    InvoiceRefunded:
      description: Webhook published when an invoice is refunded
      title: InvoiceRefunded
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ INVOICE_REFUNDED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the refunded invoice
                invoiceNumber:
                  type: string
                  description: Number of the invoice
                userId:
                  description: Identifier of the user the invoice was created for
                  type: integer
                  format: int64
                totalGross:
                  description: Total gross amount of the invoice
                  type: number
                totalNet:
                  description: Total net amount of the invoice
                  type: number
                taxAmount:
                  description: Total tax amount of the invoice
                  type: number
                taxRate:
                  description: Tax rate of the invoice
                  type: number
                currencyCode:
                  description: Currency of the invoice
                  type: string
                type:
                  type: string
                  enum:
                    - INVOICE
                    - ISSUE
                    - VOUCHER_PURCHASE
                lineItems:
                  type: array
                  items:
                    $ref: '#/components/schemas/InvoiceLineItem'

    VoucherRedeemed:
      description: Webhook published when a voucher is redeemed
      title: VoucherRedeemed
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ VOUCHER_REDEEMED ]
            data:
              type: object
              properties:
                voucherId:
                  type: integer
                  format: int64
                  description: identifier of the redeemed voucher
                userId:
                  type: integer
                  format: int64
                  description: identifier of the user who redeemed the voucher
                voucherCode:
                  type: string
                  description: code of the redeemed the voucher

    IssueCreated:
      description: Webhook published when an issue is created
      title: IssueCreated
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ ISSUE_CREATED ]
            data:
              type: object
              properties:
                id:
                  type: integer
                  format: int64
                  description: identifier of the created issue
                category:
                  $ref: "#/components/schemas/IssueCategory"
                  description: the issue category

    PackagePurchased:
      description: Webhook published when a package is purchased
      title: PackagePurchased
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ PACKAGE_PURCHASED ]
            data:
              type: object
              properties:
                packageId:
                  type: integer
                  format: int64
                  description: identifier of the purchased package
                userId:
                  type: integer
                  format: int64
                  description: identifier of the user who purchased the package

    TaskCreated:
      description: Webhook published when a task is created
      title: TaskCreated
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ TASK_CREATED ]
            data:
              type: object
              properties:
                taskId:
                  type: integer
                  format: int64
                  description: identifier of the task that was created
                vehicleId:
                  type: integer
                  format: int64
                  nullable: true
                  description: identifier of the vehicle associated with the task (null if task has no vehicle)
                rentalId:
                  type: integer
                  format: int64
                  nullable: true
                  description: identifier of the rental associated with the task via its issue (null if task has no issue or issue has no rental)
                userId:
                  type: integer
                  format: int64
                  nullable: true
                  description: identifier of the user associated with the task (null if task has no user)
                status:
                  $ref: "#/components/schemas/TaskState"
                  description: the task status
                priority:
                  $ref: "#/components/schemas/TaskPriority"
                  description: the task priority
                category:
                  $ref: "#/components/schemas/TaskCategory"
                  deprecated: true
                  nullable: true
                  description: >-
                    Deprecated. Use categoryInfo instead.
                    Contains the legacy enum value only when the task's category
                    matches a predefined system category. Set to null when the
                    task uses a custom category that has no enum mapping.
                    Consumers should not rely on this field being populated.
                categoryInfo:
                  type: object
                  nullable: true
                  description: >-
                    The canonical source of truth for the task's category.
                    Present for both system and custom categories whenever the
                    task has a category assigned; null when no category is set.
                    Consumers must prefer this field over the deprecated
                    category enum for all category details.
                  properties:
                    id:
                      type: integer
                      format: int64
                    name:
                      type: string
                title:
                  type: string
                  description: the task title
                description:
                  type: string
                  nullable: true
                  description: the task description

    TaskUpdated:
      description: Webhook published when a task status changes
      title: TaskUpdated
      allOf:
        - $ref: '#/components/schemas/WebhookData'
        - type: object
          properties:
            type:
              type: string
              enum: [ TASK_UPDATED ]
            data:
              type: object
              properties:
                taskId:
                  type: integer
                  format: int64
                  description: identifier of the task that was updated
                vehicleId:
                  type: integer
                  format: int64
                  nullable: true
                  description: identifier of the vehicle associated with the task (null if task has no vehicle)
                previousStatus:
                  $ref: "#/components/schemas/TaskState"
                  description: the previous task status
                newStatus:
                  $ref: "#/components/schemas/TaskState"
                  description: the new task status
