openapi: 3.0.3
info:
  title: Looopin Platform API
  version: "0.3.0"
  description: >
    Live HTTP surfaces for the Next.js platform. Wallet issue remains non-live
    until Apple/Google certificates are configured. POS adapters award points
    only when a matching customer phone/email exists.
servers:
  - url: https://app.looopin.net
  - url: http://localhost:3000
paths:
  /api/health:
    get:
      summary: Health check
      responses:
        "200":
          description: OK
  /api/v1/pos/webhook:
    post:
      summary: Generic POS ingest
      parameters:
        - in: header
          name: x-looopin-signature
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [businessId, eventType]
              properties:
                businessId: { type: integer }
                provider: { type: string }
                eventType: { type: string }
                externalId: { type: string }
                payload: { type: object }
                idempotencyKey: { type: string }
      responses:
        "200": { description: Ingested }
  /api/v1/pos/shopify:
    post:
      summary: Shopify orders webhook
      parameters:
        - in: query
          name: businessId
          required: true
          schema: { type: integer }
      responses:
        "200": { description: Processed }
  /api/v1/pos/woocommerce:
    post:
      summary: WooCommerce orders webhook
      responses:
        "200": { description: Processed }
  /api/v1/pos/square:
    post:
      summary: Square payments webhook
      responses:
        "200": { description: Processed }
  /api/v1/pos/foodics:
    post:
      summary: Foodics orders webhook
      responses:
        "200": { description: Processed }
  /api/v1/wallet/preview:
    get:
      summary: Unsigned wallet pass preview (live=false)
      parameters:
        - in: query
          name: format
          schema: { type: string, enum: [json, html] }
          description: html returns a visual card preview; default is JSON
        - in: query
          name: business
          schema: { type: string }
        - in: query
          name: name
          schema: { type: string }
        - in: query
          name: points
          schema: { type: number }
        - in: query
          name: cardId
          schema: { type: string }
      responses:
        "200": { description: Preview JSON or HTML card (live=false) }
  /api/export/customers:
    get:
      summary: Export merchant customers as CSV (auth cookie required)
      responses:
        "200": { description: text/csv download }
        "401": { description: Unauthorized }
  /api/v1/wallet/issue:
    post:
      summary: Wallet issue gate (live=false without certs)
      responses:
        "200": { description: Readiness response }
  /api/cron/deliver-webhooks:
    post:
      summary: Deliver pending merchant webhooks
      security: [{ cronBearer: [] }]
      responses:
        "200": { description: Delivery batch }
  /api/cron/maintenance:
    post:
      summary: Enqueue webhooks + expire points + deliver
      security: [{ cronBearer: [] }]
      responses:
        "200": { description: Maintenance batch }
components:
  securitySchemes:
    cronBearer:
      type: http
      scheme: bearer
