openapi: 3.1.0
info:
  title: CheckYout Partner API
  version: 1.0.0
  description: |
    Die CheckYout Partner API ermöglicht es PMS- und Ops-Plattformen,
    Checkout-Events zu empfangen und WhatsApp-Benachrichtigungen auszulösen.
  contact:
    name: CheckYout Support
    email: info@checkyout.app
    url: https://checkyout.app/developers

servers:
  - url: https://checkyout.app/api/v1
    description: Produktion

security:
  - ApiKeyAuth: []

tags:
  - name: Notify
    description: WhatsApp-Benachrichtigungen auslösen
  - name: Webhooks
    description: Von CheckYout gesendete Events

paths:
  /notify:
    post:
      operationId: sendNotification
      summary: WhatsApp-Benachrichtigung senden
      description: |
        Sendet eine WhatsApp-Nachricht an die angegebene Telefonnummer.
        Das Gerät (device_id) muss dem Account des API-Key-Inhabers gehören.
      tags:
        - Notify
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NotifyRequest'
            example:
              device_id: d4f8a2b1-3c5e-4f6a-8b9c-1d2e3f4a5b6c
              phone: "+41791234567"
              name: Ferienwohnung Alpenblick
      responses:
        '200':
          description: Nachricht erfolgreich gesendet
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotifySuccessResponse'
              example:
                success: true
                message_sid: SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        '400':
          description: Ungültige Anfrage
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missingFields:
                  summary: Fehlende Pflichtfelder
                  value:
                    error: "Missing required fields: device_id, phone"
                invalidPhone:
                  summary: Ungültiges Telefonnummernformat
                  value:
                    error: "Phone must be in E.164 format (starting with +)"
        '401':
          description: Nicht authentifiziert
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: Invalid or missing API key
        '404':
          description: Gerät nicht gefunden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: Device not found or does not belong to your account
        '500':
          description: Interner Serverfehler
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: Failed to send WhatsApp
                details: Twilio service unavailable

webhooks:
  checkoutEvent:
    post:
      operationId: onCheckout
      summary: Checkout-Event
      description: |
        Wird an Ihren konfigurierten Webhook-Endpoint gesendet,
        wenn ein Gast das CheckYout-Sign (QR-Code) scannt und den Checkout bestätigt.
      tags:
        - Webhooks
      parameters:
        - name: X-CheckYout-Signature
          in: header
          required: false
          description: HMAC-SHA256 Hex-Digest des Request-Body (nur mit Webhook-Secret)
          schema:
            type: string
            example: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCheckoutEvent'
            example:
              event: checkout
              device_id: d4f8a2b1-3c5e-4f6a-8b9c-1d2e3f4a5b6c
              property_name: Ferienwohnung Alpenblick
              property_city: Interlaken
              timestamp: "2026-04-11T14:32:00.000Z"
              source: checkyout
      responses:
        '200':
          description: Event empfangen

  cleaningCompletedEvent:
    post:
      operationId: onCleaningCompleted
      summary: Cleaning-Completed-Event
      description: |
        Wird an Ihren konfigurierten Webhook-Endpoint gesendet,
        wenn eine Reinigungskraft den Abschluss der Reinigung über den Token-Link bestätigt.
      tags:
        - Webhooks
      parameters:
        - name: X-CheckYout-Signature
          in: header
          required: false
          description: HMAC-SHA256 Hex-Digest des Request-Body (nur mit Webhook-Secret)
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCleaningCompletedEvent'
            example:
              event: cleaning.completed
              device_id: d4f8a2b1-3c5e-4f6a-8b9c-1d2e3f4a5b6c
              property_name: Ferienwohnung Alpenblick
              property_city: Interlaken
              cleaning_completed_at: "2026-04-11T16:45:00.000Z"
              timestamp: "2026-04-11T16:45:00.000Z"
              source: checkyout
      responses:
        '200':
          description: Event empfangen

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Partner API-Key im Format cyo_xxxxxxxxxxxx

  schemas:
    NotifyRequest:
      type: object
      required:
        - device_id
        - phone
      properties:
        device_id:
          type: string
          format: uuid
          description: UUID des CheckYout-Geräts. Muss dem Account des API-Key-Inhabers gehören.
          example: d4f8a2b1-3c5e-4f6a-8b9c-1d2e3f4a5b6c
        phone:
          type: string
          description: Telefonnummer im E.164-Format (muss mit + beginnen).
          pattern: '^\+[1-9]\d{1,14}$'
          example: "+41791234567"
        name:
          type: string
          description: Anzeigename der Unterkunft in der WhatsApp-Nachricht. Fallback ist der property_name des Geräts.
          example: Ferienwohnung Alpenblick

    NotifySuccessResponse:
      type: object
      required:
        - success
        - message_sid
      properties:
        success:
          type: boolean
          const: true
        message_sid:
          type: string
          description: Twilio Message SID der gesendeten WhatsApp-Nachricht.
          example: SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Kurze Fehlerbeschreibung.
          example: Invalid or missing API key
        details:
          type: string
          description: Optionale zusätzliche Informationen zur Fehlerursache.
          example: Twilio service unavailable

    WebhookCheckoutEvent:
      type: object
      required:
        - event_id
        - event
        - device_id
        - property_name
        - timestamp
        - source
      properties:
        event_id:
          type: string
          format: uuid
          description: Eindeutige UUID des Events. Zur Deduplizierung verwenden.
        event:
          type: string
          const: checkout
          description: Event-Typ.
        device_id:
          type: string
          format: uuid
          description: UUID des CheckYout-Geräts (Sign).
        property_name:
          type: string
          description: Name der Unterkunft.
        property_city:
          type: string
          nullable: true
          description: Stadt der Unterkunft, sofern hinterlegt.
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 Zeitstempel des Checkout-Events.
        source:
          type: string
          const: checkyout
          description: Immer "checkyout".

    WebhookCleaningCompletedEvent:
      type: object
      required:
        - event_id
        - event
        - device_id
        - property_name
        - cleaning_completed_at
        - timestamp
        - source
      properties:
        event_id:
          type: string
          format: uuid
          description: Eindeutige UUID des Events. Zur Deduplizierung verwenden.
        event:
          type: string
          const: cleaning.completed
          description: Event-Typ.
        device_id:
          type: string
          format: uuid
          description: UUID des CheckYout-Geräts (Sign).
        property_name:
          type: string
          description: Name der Unterkunft.
        property_city:
          type: string
          nullable: true
          description: Stadt der Unterkunft, sofern hinterlegt.
        cleaning_completed_at:
          type: string
          format: date-time
          description: ISO 8601 Zeitstempel der Reinigungsbestätigung.
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 Zeitstempel des Events.
        source:
          type: string
          const: checkyout
          description: Immer "checkyout".
