openapi: 3.1.0
info:
  title: Resonance API
  description: |
    Complete REST API for Resonance loyalty platform. Track events, distribute rewards, manage wallets.
    
    ## Base URLs
    
    - **Event Handler**: `https://api.rsnc.network`
    - **Gas Relayer**: `https://relayer.rsnc.network`
    - **Pregeneration**: `https://register.rsnc.network`
    
    ## Authentication
    
    Most endpoints use Brand ID authentication (included in request body).
    Gas Relayer requires Privy Bearer token authentication.
    
  version: 1.0.0
  contact:
    name: Resonance Support
    email: support@rsnc.network
    url: https://docs.rsnc.network
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  externalDocs:
    description: Full Documentation
    url: https://docs.rsnc.network/api/rest-api

servers:
  - url: https://api.rsnc.network
    description: Production API
  - url: https://relayer.rsnc.network
    description: Gas Relayer API
  - url: https://register.rsnc.network
    description: OAuth Pregeneration API

tags:
  - name: Events
    description: Track customer events and trigger rewards
  - name: Gas Relayer
    description: Execute gasless transactions
  - name: Health
    description: System health and diagnostics

paths:
  /resonance-api/manual-event:
    post:
      tags:
        - Events
      summary: Track a customer event
      description: |
        Track a customer event and automatically reward them with RSNC tokens.
        The system will create a wallet if needed and distribute rewards based on your configured rules.
      operationId: trackEvent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EventRequest'
            examples:
              newsletterSignup:
                summary: Newsletter Signup
                value:
                  brandId: "0x47511fc1c6664c9598974cb112965f8b198e0c725e"
                  eventType: "newsletter_signup"
                  userEmail: "user@example.com"
                  domain: "example.com"
                  metadata:
                    source: "homepage"
                    campaign: "summer-2024"
              accountCreation:
                summary: Account Creation
                value:
                  brandId: "0x47511fc1c6664c9598974cb112965f8b198e0c725e"
                  eventType: "account_creation"
                  userEmail: "newuser@example.com"
                  domain: "example.com"
                  metadata:
                    userId: "user_123"
                    source: "website"
              purchase:
                summary: Purchase Event
                value:
                  brandId: "0x47511fc1c6664c9598974cb112965f8b198e0c725e"
                  eventType: "purchase"
                  userEmail: "customer@example.com"
                  domain: "example.com"
                  metadata:
                    orderId: "order_456"
                    amount: 99.99
                    items: 3
      responses:
        '200':
          description: Event tracked successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventResponse'
              examples:
                success:
                  summary: Successful event tracking
                  value:
                    success: true
                    eventId: "550e8400-e29b-41d4-a716-446655440000"
                    message: "100 RSNC tokens minted successfully!"
                    rewardAmount: 100
                    eventType: "newsletter_signup"
                    walletAddress: "0x1234567890123456789012345678901234567890"
                    transactionHash: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        '400':
          description: Bad request - validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Domain not authorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'

  /resonance-api/bulk-events:
    post:
      tags:
        - Events
      summary: Submit multiple events
      description: Submit multiple events in a single request for batch processing
      operationId: trackBulkEvents
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - events
              properties:
                events:
                  type: array
                  items:
                    $ref: '#/components/schemas/EventRequest'
                  minItems: 1
                  maxItems: 100
      responses:
        '200':
          description: Events processed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  processed:
                    type: integer
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/EventResponse'

  /resonance-api/event-config:
    get:
      tags:
        - Events
      summary: Get event configurations
      description: Retrieve all active event configurations for a brand
      operationId: getEventConfig
      parameters:
        - name: brandId
          in: query
          required: true
          schema:
            type: string
            pattern: '^0x[a-fA-F0-9]{40}$'
          description: Your brand wallet address
      responses:
        '200':
          description: Event configurations
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  brandId:
                    type: string
                  events:
                    type: array
                    items:
                      $ref: '#/components/schemas/EventConfig'

  /resonance-api/diagnostic:
    get:
      tags:
        - Health
      summary: System diagnostics
      description: Run diagnostic checks to verify worker configuration
      operationId: getDiagnostics
      responses:
        '200':
          description: Diagnostic information
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum: [healthy, degraded, down]
                  database:
                    type: string
                  blockchain:
                    type: string
                  privy:
                    type: string
                  timestamp:
                    type: string
                    format: date-time

  /relay:
    post:
      tags:
        - Gas Relayer
      summary: Execute gasless transaction
      description: |
        Execute a blockchain transaction on behalf of a user without requiring them to pay gas fees.
        Requires Privy authentication.
      operationId: relayTransaction
      security:
        - PrivyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RelayRequest'
      responses:
        '200':
          description: Transaction executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RelayResponse'
        '401':
          description: Unauthorized - invalid Privy token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Transaction validation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'

components:
  securitySchemes:
    PrivyAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Privy access token from Privy SDK

  schemas:
    EventRequest:
      type: object
      required:
        - brandId
        - eventType
        - userEmail
      properties:
        brandId:
          type: string
          pattern: '^0x[a-fA-F0-9]{40}$'
          description: Your brand wallet address (42 characters, starts with 0x)
          example: "0x47511fc1c6664c9598974cb112965f8b198e0c725e"
        eventType:
          type: string
          pattern: '^[a-zA-Z0-9_]{1,50}$'
          description: Event type identifier (alphanumeric + underscore, max 50 chars)
          example: "newsletter_signup"
        userEmail:
          type: string
          format: email
          maxLength: 254
          description: User's email address (RFC 5322 compliant)
          example: "user@example.com"
        domain:
          type: string
          maxLength: 253
          description: Your website domain (extracted from sourceUrl if not provided)
          example: "example.com"
        sourceUrl:
          type: string
          format: uri
          maxLength: 2048
          description: URL where the event occurred
          example: "https://example.com/newsletter"
        userIdentifier:
          type: string
          description: Alternative identifier (email or Ethereum address)
        metadata:
          type: object
          additionalProperties: true
          description: Additional event data
          example:
            source: "homepage"
            campaign: "summer-2024"
            userId: "user_123"

    EventResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        eventId:
          type: string
          format: uuid
          description: Unique event identifier
          example: "550e8400-e29b-41d4-a716-446655440000"
        message:
          type: string
          example: "100 RSNC tokens minted successfully!"
        rewardAmount:
          type: integer
          description: Amount of RSNC tokens rewarded
          example: 100
        eventType:
          type: string
          example: "newsletter_signup"
        walletAddress:
          type: string
          pattern: '^0x[a-fA-F0-9]{40}$'
          description: User's wallet address (created if new)
          example: "0x1234567890123456789012345678901234567890"
        transactionHash:
          type: string
          pattern: '^0x[a-fA-F0-9]{64}$'
          description: Blockchain transaction hash
          example: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        reward:
          type: object
          properties:
            amount:
              type: integer
            eventType:
              type: string
            walletAddress:
              type: string
            transactionHash:
              type: string

    EventConfig:
      type: object
      properties:
        eventId:
          type: string
        eventType:
          type: string
        rewardAmount:
          type: integer
        maxClaims:
          type: integer
        cooldownHours:
          type: integer
        detectionMethod:
          type: string
          enum: [manual, url_pattern, form_auto, sdk_auto]
        detectionConfig:
          type: object
        isCustom:
          type: boolean

    RelayRequest:
      type: object
      required:
        - to
        - data
        - userAddress
      properties:
        to:
          type: string
          pattern: '^0x[a-fA-F0-9]{40}$'
          description: Contract address to call
          example: "0x997f05E7447Fdde75d47eBb12D4D6C65013AA0Da"
        data:
          type: string
          pattern: '^0x[a-fA-F0-9]+$'
          description: Encoded function call data (hex string)
          example: "0x1234abcd..."
        value:
          type: string
          default: "0"
          description: ETH value to send (in wei)
          example: "0"
        gasLimit:
          type: integer
          description: Maximum gas limit
          example: 500000
        userAddress:
          type: string
          pattern: '^0x[a-fA-F0-9]{40}$'
          description: User's wallet address
          example: "0x1234567890123456789012345678901234567890"
        metadata:
          type: object
          properties:
            action:
              type: string
              example: "claim_perk"
            perkId:
              type: string
            permit:
              $ref: '#/components/schemas/Permit'

    Permit:
      type: object
      properties:
        owner:
          type: string
          pattern: '^0x[a-fA-F0-9]{40}$'
        spender:
          type: string
          pattern: '^0x[a-fA-F0-9]{40}$'
        value:
          type: string
        deadline:
          type: integer
        v:
          type: integer
        r:
          type: string
        s:
          type: string

    RelayResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        transactionHash:
          type: string
          pattern: '^0x[a-fA-F0-9]{64}$'
          example: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
        gasUsed:
          type: string
          example: "250000"
        effectiveGasPrice:
          type: string
          example: "25000000000"
        blockNumber:
          type: integer
          example: 12345678
        from:
          type: string
          description: Dev wallet address that executed transaction
        to:
          type: string
          description: Contract address called
        status:
          type: string
          enum: [pending, confirmed, failed]

    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Human-readable error message
          example: "Invalid email address"
        code:
          type: string
          description: Machine-readable error code
          example: "INVALID_EMAIL"
        details:
          type: object
          additionalProperties: true
          description: Additional error details
          properties:
            errors:
              type: array
              items:
                type: string
            field:
              type: string
            value:
              type: string

    RateLimitError:
      allOf:
        - $ref: '#/components/schemas/ErrorResponse'
        - type: object
          properties:
            retryAfter:
              type: integer
              description: Seconds to wait before retrying
              example: 3600
            details:
              type: object
              properties:
                message:
                  type: string
                reason:
                  type: string
                  enum: [cooldown_not_expired, rate_limit_exceeded]
                cooldownSeconds:
                  type: integer

