openapi: 3.1.0
info:
  title: Dealome API
  version: 1.0.0-development
  description: Affiliate-only Stage 2 contract. No cashback, wallet, or payout resources.
servers:
  - url: https://dealome.com/api/v1
paths:
  /health:
    get:
      operationId: health
      responses:
        "200":
          description: Service and database are healthy.
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: object
                    required: [status, service, phase, time]
                    properties:
                      status: { type: string, const: ok }
                      service: { type: string }
                      phase: { type: integer }
                      time: { type: string, format: date-time }
  /merchants:
    get:
      operationId: listMerchants
      parameters:
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        "200":
          description: Cursor-paginated published merchants.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantCollection"
  /merchants/{slug}:
    get:
      operationId: getMerchant
      parameters:
        - { name: slug, in: path, required: true, schema: { type: string } }
      responses:
        "200":
          description: Published merchant.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: "#/components/schemas/Merchant" }
        "404": { $ref: "#/components/responses/NotFound" }
  /offers:
    get:
      operationId: listOffers
      parameters:
        - { name: market, in: query, schema: { type: string, default: AE, minLength: 2, maxLength: 2 } }
        - { name: cursor, in: query, schema: { type: string } }
      responses:
        "200":
          description: Cursor-paginated active offers.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OfferCollection"
  /offers/{slug}:
    get:
      operationId: getOffer
      parameters:
        - { name: slug, in: path, required: true, schema: { type: string } }
      responses:
        "200":
          description: Published offer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { $ref: "#/components/schemas/Offer" }
        "404": { $ref: "#/components/responses/NotFound" }
  /search:
    get:
      operationId: searchCatalog
      parameters:
        - { name: q, in: query, required: true, schema: { type: string, minLength: 2, maxLength: 100 } }
        - { name: market, in: query, schema: { type: string, default: AE } }
      responses:
        "200":
          description: Matching published offers and merchants.
components:
  responses:
    NotFound:
      description: Resource not found.
      content:
        application/problem+json:
          schema: { $ref: "#/components/schemas/Problem" }
  schemas:
    Merchant:
      type: object
      required: [id, name, slug, trust_score, country]
      properties:
        id: { type: string, pattern: "^[0-9A-HJKMNP-TV-Z]{26}$" }
        name: { type: string }
        slug: { type: string }
        summary: { type: [string, "null"] }
        trust_score: { type: integer, minimum: 0, maximum: 100 }
        country: { type: string }
        offers_count: { type: integer }
        updated_at: { type: string, format: date-time }
    Offer:
      type: object
      required: [id, type, title, slug, summary, merchant, verification, market]
      properties:
        id: { type: string, pattern: "^[0-9A-HJKMNP-TV-Z]{26}$" }
        type: { type: string, enum: [coupon, deal] }
        title: { type: string }
        slug: { type: string }
        summary: { type: string }
        merchant: { $ref: "#/components/schemas/Merchant" }
        code: { type: [string, "null"] }
        discount: { type: object }
        verification: { type: object }
        market: { type: string }
        expires_at: { type: [string, "null"], format: date-time }
        updated_at: { type: string, format: date-time }
    MerchantCollection:
      type: object
      properties:
        data: { type: array, items: { $ref: "#/components/schemas/Merchant" } }
        meta: { type: object }
        links: { type: object }
    OfferCollection:
      type: object
      properties:
        data: { type: array, items: { $ref: "#/components/schemas/Offer" } }
        meta: { type: object }
        links: { type: object }
    Problem:
      type: object
      required: [type, title, status, request_id]
      properties:
        type: { type: string, format: uri-reference }
        title: { type: string }
        status: { type: integer }
        detail: { type: string }
        request_id: { type: string }
