openapi: 3.1.0
info:
  title: Daremeet Lieux upcoming events feed
  version: 1.1.0
  description: |
    Global JSON feed of upcoming local events aggregated on Daremeet Lieux city pages.
    Default scope `catalog` covers ~294 cities; `featured` limits to 50 SEO cities.
    Per-city cache refreshed every 6 hours; Vercel cron pre-warms caches (`/api/internal/lieux-events-warm`).
    Sources: Datatourisme, OpenAgenda, Ticketmaster, PredictHQ, SeatGeek.
    Pretty URL (rewrite): `/lieux-events-feed.json`
    RSS: `/{locale}/lieux-events-feed.xml` (root `/lieux-events-feed.xml` → fr)
    Sitemap anchors: `/sitemap/lieux-events.xml` (#lieux-upcoming-events per city)
servers:
  - url: https://www.daremeet.com
paths:
  /api/lieux-events-feed:
    get:
      operationId: daremeetLieuxEventsFeed
      tags: [lieux, agents]
      summary: Upcoming local events across Daremeet Lieux cities
      parameters:
        - name: locale
          in: query
          schema: { type: string, default: fr }
          description: BCP-47 locale for localized Lieux city page URLs in the response
        - name: scope
          in: query
          schema:
            type: string
            enum: [catalog, featured]
            default: catalog
          description: catalog (~294 cities) or featured (50 SEO cities)
        - name: country
          in: query
          schema: { type: string }
          description: Filter by country slug (e.g. france, united-states)
        - name: city_key
          in: query
          schema: { type: string }
          description: Single city key country/region/city (overrides scope)
        - name: limit
          in: query
          schema: { type: integer, default: 500, minimum: 1, maximum: 2000 }
      responses:
        '200':
          description: Events feed JSON
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LieuxEventsFeed'
        '502':
          description: feed_unavailable
  /lieux-events-feed.json:
    get:
      operationId: daremeetLieuxEventsFeedPretty
      tags: [lieux, agents]
      summary: Alias crawlable for the events feed
      description: Rewrites to `/api/lieux-events-feed`
      responses:
        '200':
          description: Events feed JSON
  /lieux-events-feed.xml:
    get:
      operationId: daremeetLieuxEventsFeedRssDefault
      tags: [lieux, agents]
      summary: RSS 2.0 events feed (default locale fr)
      responses:
        '200':
          description: RSS XML
          content:
            application/rss+xml:
              schema: { type: string }
  '/{locale}/lieux-events-feed.xml':
    get:
      operationId: daremeetLieuxEventsFeedRssLocale
      tags: [lieux, agents]
      summary: RSS 2.0 events feed per locale
      parameters:
        - name: locale
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: RSS XML
components:
  schemas:
    LieuxEventsFeed:
      type: object
      required: [schema_version, generated_at, locale, scope, events]
      properties:
        schema_version: { type: string, example: '1.1.0' }
        generated_at: { type: string, format: date-time }
        locale: { type: string }
        scope:
          type: string
          enum: [catalog, featured]
        catalog_city_count: { type: integer, example: 294 }
        description: { type: string }
        attribution: { type: string }
        sources_note: { type: string }
        feed_url: { type: string, format: uri }
        rss_url: { type: string, format: uri }
        featured_city_keys:
          type: array
          items: { type: string }
        city_count: { type: integer }
        event_count: { type: integer }
        cities:
          type: array
          items:
            type: object
            properties:
              key: { type: string }
              city_name: { type: string }
              event_count: { type: integer }
              lieux_city_page: { type: string, format: uri }
              lieux_city_events_anchor: { type: string, format: uri }
              snapshot_url: { type: string, format: uri }
        events:
          type: array
          items:
            type: object
            properties:
              id: { type: string }
              title: { type: string }
              start_date: { type: string, format: date-time, nullable: true }
              end_date: { type: string, format: date-time, nullable: true }
              location_name: { type: string, nullable: true }
              city_key: { type: string }
              city_name: { type: string }
              url: { type: string, format: uri }
              image_url: { type: string, format: uri, nullable: true }
              source:
                type: string
                enum: [datatourisme, openagenda, ticketmaster, predicthq, seatgeek]
              lieux_city_page: { type: string, format: uri }
              lieux_city_events_anchor: { type: string, format: uri }
              snapshot_url: { type: string, format: uri }
