asyncapi: 3.0.0

info:
  title: Ticketing Service Async API
  version: 2.1.0
  description: |
    Kafka event contracts for ticketing-svc.

    All events use CloudEvents 1.0 envelope format and are partitioned by tenant_id
    for tenant isolation and ordering guarantees.

    **Event Flow:**
    - Purchase → pass.issued → (blockchain minting) → pass.updated
    - Transfer → transfer.initiated → (recipient action) → transfer.completed/rejected
    - Refund → refund.requested → (admin review) → refund.approved/rejected
    - Check-in → checkin.completed
  contact:
    name: EventZR Platform Team
    email: platform@eventzr.com
  license:
    name: Proprietary
    url: https://eventzr.com/licenses

servers:
  production:
    host: boot-gpm4u49z.c2.kafka-serverless.us-east-1.amazonaws.com:9098
    protocol: kafka
    description: Amazon MSK Serverless (Production - us-east-1)
    security:
      - $ref: '#/components/securitySchemes/saslIam'
    tags:
      - name: env:production
      - name: region:us-east-1

  staging:
    host: boot-gpm4u49z.c2.kafka-serverless.us-east-1.amazonaws.com:9098
    protocol: kafka
    description: Amazon MSK Serverless (Staging - us-east-1)
    security:
      - $ref: '#/components/securitySchemes/saslIam'
    tags:
      - name: env:staging
      - name: region:us-east-1

channels:
  passIssued:
    address: eventzr.ticketing.pass.issued.v1
    messages:
      PassIssuedEvent:
        $ref: '#/components/messages/PassIssuedEvent'
    description: Published when a pass is created after successful purchase
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 604800000 # 7 days

  passUpdated:
    address: eventzr.ticketing.pass.updated.v1
    messages:
      PassUpdatedEvent:
        $ref: '#/components/messages/PassUpdatedEvent'
    description: Published when a pass is updated (blockchain status, metadata changes)
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 604800000

  purchaseCreated:
    address: eventzr.ticketing.purchase.created.v1
    messages:
      PurchaseCreatedEvent:
        $ref: '#/components/messages/PurchaseCreatedEvent'
    description: Published when a new purchase is completed
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 2592000000 # 30 days

  purchaseCancelled:
    address: eventzr.ticketing.purchase.cancelled.v1
    messages:
      PurchaseCancelledEvent:
        $ref: '#/components/messages/PurchaseCancelledEvent'
    description: Published when a purchase is cancelled
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 2592000000

  transferInitiated:
    address: eventzr.ticketing.transfer.initiated.v1
    messages:
      TransferInitiatedEvent:
        $ref: '#/components/messages/TransferInitiatedEvent'
    description: Published when a transfer request is created
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 604800000

  transferCompleted:
    address: eventzr.ticketing.transfer.completed.v1
    messages:
      TransferCompletedEvent:
        $ref: '#/components/messages/TransferCompletedEvent'
    description: Published when a transfer is approved and completed
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 2592000000

  transferRejected:
    address: eventzr.ticketing.transfer.rejected.v1
    messages:
      TransferRejectedEvent:
        $ref: '#/components/messages/TransferRejectedEvent'
    description: Published when a transfer is rejected by the recipient
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 604800000

  transferCancelled:
    address: eventzr.ticketing.transfer.cancelled.v1
    messages:
      TransferCancelledEvent:
        $ref: '#/components/messages/TransferCancelledEvent'
    description: Published when a transfer is cancelled by the sender
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 604800000

  refundRequested:
    address: eventzr.ticketing.refund.requested.v1
    messages:
      RefundRequestedEvent:
        $ref: '#/components/messages/RefundRequestedEvent'
    description: Published when a refund request is created
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 2592000000

  refundApproved:
    address: eventzr.ticketing.refund.approved.v1
    messages:
      RefundApprovedEvent:
        $ref: '#/components/messages/RefundApprovedEvent'
    description: Published when a refund is approved and processed
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 2592000000

  refundRejected:
    address: eventzr.ticketing.refund.rejected.v1
    messages:
      RefundRejectedEvent:
        $ref: '#/components/messages/RefundRejectedEvent'
    description: Published when a refund is rejected
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 2592000000

  checkinCompleted:
    address: eventzr.ticketing.checkin.completed.v1
    messages:
      CheckinCompletedEvent:
        $ref: '#/components/messages/CheckinCompletedEvent'
    description: Published when a successful check-in occurs
    bindings:
      kafka:
        partitionBy: tenant_id
        replicas: 3
        configs:
          retention.ms: 7776000000 # 90 days (compliance)

operations:
  publishPassIssued:
    action: send
    channel:
      $ref: '#/channels/passIssued'
    summary: Publish pass issued event
    description: Triggered after successful purchase completion
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishPassUpdated:
    action: send
    channel:
      $ref: '#/channels/passUpdated'
    summary: Publish pass updated event
    description: Triggered when pass blockchain status or metadata changes
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishPurchaseCreated:
    action: send
    channel:
      $ref: '#/channels/purchaseCreated'
    summary: Publish purchase created event
    description: Triggered after successful payment and purchase creation
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishPurchaseCancelled:
    action: send
    channel:
      $ref: '#/channels/purchaseCancelled'
    summary: Publish purchase cancelled event
    description: Triggered when a purchase is cancelled (before event start)
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishTransferInitiated:
    action: send
    channel:
      $ref: '#/channels/transferInitiated'
    summary: Publish transfer initiated event
    description: Triggered when a pass transfer is requested
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishTransferCompleted:
    action: send
    channel:
      $ref: '#/channels/transferCompleted'
    summary: Publish transfer completed event
    description: Triggered when a transfer is approved and ownership changes
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishTransferRejected:
    action: send
    channel:
      $ref: '#/channels/transferRejected'
    summary: Publish transfer rejected event
    description: Triggered when a recipient rejects a transfer
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishTransferCancelled:
    action: send
    channel:
      $ref: '#/channels/transferCancelled'
    summary: Publish transfer cancelled event
    description: Triggered when a sender cancels a pending transfer
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishRefundRequested:
    action: send
    channel:
      $ref: '#/channels/refundRequested'
    summary: Publish refund requested event
    description: Triggered when a user requests a refund
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishRefundApproved:
    action: send
    channel:
      $ref: '#/channels/refundApproved'
    summary: Publish refund approved event
    description: Triggered when an admin approves a refund
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishRefundRejected:
    action: send
    channel:
      $ref: '#/channels/refundRejected'
    summary: Publish refund rejected event
    description: Triggered when an admin rejects a refund request
    traits:
      - $ref: '#/components/operationTraits/kafka'

  publishCheckinCompleted:
    action: send
    channel:
      $ref: '#/channels/checkinCompleted'
    summary: Publish check-in completed event
    description: Triggered when a pass is successfully checked in at an event
    traits:
      - $ref: '#/components/operationTraits/kafka'

components:
  messages:
    PassIssuedEvent:
      name: PassIssuedEvent
      title: Pass Issued
      summary: Pass created after purchase
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/PassIssuedPayload'

    PassUpdatedEvent:
      name: PassUpdatedEvent
      title: Pass Updated
      summary: Pass metadata or blockchain status updated
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/PassUpdatedPayload'

    PurchaseCreatedEvent:
      name: PurchaseCreatedEvent
      title: Purchase Created
      summary: New purchase completed
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/PurchaseCreatedPayload'

    PurchaseCancelledEvent:
      name: PurchaseCancelledEvent
      title: Purchase Cancelled
      summary: Purchase cancelled by user or admin
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/PurchaseCancelledPayload'

    TransferInitiatedEvent:
      name: TransferInitiatedEvent
      title: Transfer Initiated
      summary: Pass transfer request created
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/TransferInitiatedPayload'

    TransferCompletedEvent:
      name: TransferCompletedEvent
      title: Transfer Completed
      summary: Transfer approved and completed
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/TransferCompletedPayload'

    TransferRejectedEvent:
      name: TransferRejectedEvent
      title: Transfer Rejected
      summary: Transfer rejected by recipient
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/TransferRejectedPayload'

    TransferCancelledEvent:
      name: TransferCancelledEvent
      title: Transfer Cancelled
      summary: Transfer cancelled by sender
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/TransferCancelledPayload'

    RefundRequestedEvent:
      name: RefundRequestedEvent
      title: Refund Requested
      summary: Refund request created
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/RefundRequestedPayload'

    RefundApprovedEvent:
      name: RefundApprovedEvent
      title: Refund Approved
      summary: Refund approved and processed
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/RefundApprovedPayload'

    RefundRejectedEvent:
      name: RefundRejectedEvent
      title: Refund Rejected
      summary: Refund rejected by admin
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/RefundRejectedPayload'

    CheckinCompletedEvent:
      name: CheckinCompletedEvent
      title: Check-In Completed
      summary: Successful check-in at event
      contentType: application/cloudevents+json
      traits:
        - $ref: '#/components/messageTraits/cloudEvent'
      payload:
        $ref: '#/components/schemas/CheckinCompletedPayload'

  schemas:
    PassIssuedPayload:
      type: object
      required:
        - passId
        - tenantId
        - eventId
        - purchaseId
        - tierId
        - ownerUserId
        - blockchainEnabled
      properties:
        passId:
          type: string
          format: uuid
          description: Unique pass identifier
        tenantId:
          type: string
          format: uuid
          description: Tenant identifier
        eventId:
          type: string
          format: uuid
          description: Event identifier
        purchaseId:
          type: string
          format: uuid
          description: Purchase identifier
        tierId:
          type: string
          format: uuid
          description: Tier identifier
        ownerUserId:
          type: string
          format: uuid
          description: Pass owner user ID
        blockchainEnabled:
          type: boolean
          description: Whether blockchain minting is enabled
        blockchainChainId:
          type: string
          nullable: true
          description: Blockchain chain ID if enabled
          example: 'polygon'
        blockchainPolicy:
          type: string
          nullable: true
          description: Blockchain policy (transferable/soulbound)
          enum: [transferable, soulbound]

    PassUpdatedPayload:
      type: object
      required:
        - passId
        - tenantId
        - updatedAt
      properties:
        passId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        blockchainTokenId:
          type: string
          nullable: true
          description: Blockchain token ID (ERC-721)
        blockchainTxHash:
          type: string
          nullable: true
          description: Blockchain transaction hash
        updatedAt:
          type: string
          format: date-time
          description: Update timestamp

    PurchaseCreatedPayload:
      type: object
      required:
        - purchaseId
        - tenantId
        - eventId
        - userId
        - tierId
        - quantity
        - totalAmountCents
        - currency
        - status
      properties:
        purchaseId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        eventId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        tierId:
          type: string
          format: uuid
        quantity:
          type: integer
          minimum: 1
        totalAmountCents:
          type: integer
          description: Total amount in cents
        currency:
          type: string
          example: 'USD'
        status:
          type: string
          enum: [pending, completed, cancelled]

    PurchaseCancelledPayload:
      type: object
      required:
        - purchaseId
        - tenantId
        - eventId
        - userId
        - reason
        - refundInitiated
      properties:
        purchaseId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        eventId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        reason:
          type: string
          description: Cancellation reason
        refundInitiated:
          type: boolean
          description: Whether refund was initiated

    TransferInitiatedPayload:
      type: object
      required:
        - transferId
        - tenantId
        - passId
        - fromUserId
        - recipientEmail
      properties:
        transferId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        passId:
          type: string
          format: uuid
        fromUserId:
          type: string
          format: uuid
          description: Sender user ID
        recipientEmail:
          type: string
          format: email
          description: Recipient email address

    TransferCompletedPayload:
      type: object
      required:
        - transferId
        - tenantId
        - passId
        - fromUserId
        - toUserId
      properties:
        transferId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        passId:
          type: string
          format: uuid
        fromUserId:
          type: string
          format: uuid
        toUserId:
          type: string
          format: uuid
          description: New pass owner user ID

    TransferRejectedPayload:
      type: object
      required:
        - transferId
        - tenantId
        - passId
        - fromUserId
        - reason
      properties:
        transferId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        passId:
          type: string
          format: uuid
        fromUserId:
          type: string
          format: uuid
        reason:
          type: string
          description: Rejection reason

    TransferCancelledPayload:
      type: object
      required:
        - transferId
        - tenantId
        - passId
        - fromUserId
      properties:
        transferId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        passId:
          type: string
          format: uuid
        fromUserId:
          type: string
          format: uuid

    RefundRequestedPayload:
      type: object
      required:
        - refundId
        - tenantId
        - purchaseId
        - userId
        - amountCents
        - currency
        - reason
      properties:
        refundId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        purchaseId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        amountCents:
          type: integer
        currency:
          type: string
          example: 'USD'
        reason:
          type: string

    RefundApprovedPayload:
      type: object
      required:
        - refundId
        - tenantId
        - purchaseId
        - userId
        - amountCents
        - processedAt
      properties:
        refundId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        purchaseId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        amountCents:
          type: integer
        processedAt:
          type: string
          format: date-time

    RefundRejectedPayload:
      type: object
      required:
        - refundId
        - tenantId
        - purchaseId
        - userId
        - rejectionReason
      properties:
        refundId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        purchaseId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        rejectionReason:
          type: string

    CheckinCompletedPayload:
      type: object
      required:
        - checkInId
        - tenantId
        - passId
        - eventId
        - userId
        - method
        - checkedInAt
      properties:
        checkInId:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        passId:
          type: string
          format: uuid
        eventId:
          type: string
          format: uuid
        userId:
          type: string
          format: uuid
        method:
          type: string
          enum: [qr, nfc, manual]
          description: Check-in method
        checkedInAt:
          type: string
          format: date-time

  securitySchemes:
    saslIam:
      type: scramSha256
      description: AWS IAM SASL authentication for MSK Serverless

  operationTraits:
    kafka:
      bindings:
        kafka:
          groupId:
            type: string
            description: Consumer group ID

  messageTraits:
    cloudEvent:
      headers:
        type: object
        required:
          - specversion
          - id
          - source
          - type
          - time
          - datacontenttype
          - subject
        properties:
          specversion:
            type: string
            const: '1.0'
            description: CloudEvents specification version
          id:
            type: string
            format: uuid
            description: Unique event identifier
          source:
            type: string
            const: ticketing-svc
            description: Event source service
          type:
            type: string
            description: Event type (com.eventzr.ticketing.<entity>.<action>)
          time:
            type: string
            format: date-time
            description: Event timestamp
          datacontenttype:
            type: string
            const: application/json
            description: Content type of data field
          subject:
            type: string
            format: uuid
            description: Tenant ID (for partitioning)

tags:
  - name: passes
    description: Pass lifecycle events
  - name: purchases
    description: Purchase lifecycle events
  - name: transfers
    description: Transfer lifecycle events
  - name: refunds
    description: Refund lifecycle events
  - name: checkins
    description: Check-in events
