openapi: 3.0.3
info:
  title: Sprime API
  description: Unified gateway for Weather, Crypto, News, Forex, Timezone, Air Quality, Geocode, IP Lookup, and Holiday data.
  version: 2.5.4
  contact:
    email: support@sprime.io
  license:
    name: Commercial
    url: https://sprime.io/terms.html

servers:
  - url: https://sprime.io/v1
    description: Production

security:
  - apiKey: []

components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

  schemas:
    WeatherResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        data:
          $ref: '#/components/schemas/WeatherData'
        source:
          type: string
          example: open-meteo
        timestamp:
          type: string
          format: date-time

    WeatherData:
      type: object
      properties:
        temp:
          type: number
          example: 22.5
        condition:
          type: integer
          example: 3
        unit:
          type: string
          example: celsius
        timezone:
          type: string
          example: America/New_York
        sunrise:
          type: string
          example: "2026-01-25T07:15:00"
        sunset:
          type: string
          example: "2026-01-25T17:30:00"
        uv_index:
          type: number
          example: 4
        windspeed:
          type: number
          example: 12.5
        winddirection:
          type: integer
          example: 180

    CryptoResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        data:
          $ref: '#/components/schemas/CryptoData'
        source:
          type: string
          example: coingecko
        timestamp:
          type: string
          format: date-time

    CryptoData:
      type: object
      properties:
        symbol:
          type: string
          example: btc
        price:
          type: number
          example: 43250.18
        change_24h:
          type: number
          example: 2.3
        market_cap:
          type: number
          example: 847500000000

    NewsResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        data:
          type: array
          items:
            $ref: '#/components/schemas/NewsArticle'
        source:
          type: string
          example: newsapi
        timestamp:
          type: string
          format: date-time

    NewsArticle:
      type: object
      properties:
        title:
          type: string
        source:
          type: string
        url:
          type: string
        published_at:
          type: string
          format: date-time
        description:
          type: string
        category:
          type: string
        sentiment:
          type: string
          enum: [positive, negative, neutral]

    WebhookRegistration:
      type: object
      required: [url, type, condition]
      properties:
        url:
          type: string
          format: uri
          description: HTTPS endpoint to receive webhook deliveries
        type:
          type: string
          enum: [crypto, weather, news]
        condition:
          oneOf:
            - $ref: '#/components/schemas/CryptoCondition'
            - $ref: '#/components/schemas/WeatherCondition'
            - $ref: '#/components/schemas/NewsCondition'

    CryptoCondition:
      type: object
      required: [symbol, threshold, direction]
      properties:
        symbol:
          type: string
          example: btc
        threshold:
          type: number
          example: 50000
        direction:
          type: string
          enum: [above, below]

    WeatherCondition:
      type: object
      required: [trigger, threshold]
      properties:
        trigger:
          type: string
          enum: [temp_above, temp_below, wind_above]
        threshold:
          type: number
          example: 35
        location:
          type: object
          properties:
            lat:
              type: number
            lon:
              type: number

    NewsCondition:
      type: object
      required: [category]
      properties:
        category:
          type: string
          enum: [general, business, technology, sports, entertainment, health, science]
        keywords:
          type: array
          items:
            type: string
          description: Match articles containing ANY of these keywords

    BatchRequest:
      type: object
      required: [requests]
      description: |
        Batch multiple API calls into one request. Max items and concurrency depend on plan:
        - Free: 10 items, 4 concurrent
        - Starter: 25 items, 8 concurrent
        - Pro: 75 items, 16 concurrent
        Each item counts as one request toward your daily quota.
      properties:
        requests:
          type: array
          maxItems: 75
          description: "Max per plan: Free=10, Starter=25, Pro=75"
          items:
            type: object
            required: [endpoint]
            properties:
              endpoint:
                type: string
                enum: [weather, crypto, news]
              params:
                type: object

    Error:
      type: object
      properties:
        error:
          type: string

paths:
  /weather:
    get:
      summary: Get weather data
      description: Accepts either a city name via "location" or coordinates via "lat" and "lon".
      parameters:
        - name: location
          in: query
          description: City name (e.g. miami, london, tokyo). Geocoded automatically.
          schema:
            type: string
        - name: lat
          in: query
          description: Latitude. Use with "lon" as alternative to "location".
          schema:
            type: number
        - name: lon
          in: query
          description: Longitude. Use with "lat" as alternative to "location".
          schema:
            type: number
        - name: format
          in: query
          schema:
            type: string
            enum: [celsius, fahrenheit, kelvin]
            default: celsius
        - name: enriched
          in: query
          schema:
            type: boolean
            default: false
        - name: fields
          in: query
          schema:
            type: string
          description: Comma-separated field names
        - name: fresh
          in: query
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Weather data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WeatherResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '429':
          description: Rate limit exceeded

  /weather/auto:
    get:
      summary: Get weather for detected IP location
      parameters:
        - name: format
          in: query
          schema:
            type: string
            enum: [celsius, fahrenheit, kelvin]
        - name: enriched
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: Weather data with detected location
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WeatherResponse'

  /crypto:
    get:
      summary: Get cryptocurrency price
      parameters:
        - name: symbol
          in: query
          required: true
          schema:
            type: string
          example: btc
        - name: convert
          in: query
          schema:
            type: string
          description: Convert to currency (eur, gbp, jpy)
        - name: history
          in: query
          schema:
            type: string
            enum: ['7d', '30d']
        - name: fields
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Crypto data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CryptoResponse'

  /crypto/history:
    get:
      summary: Get historical crypto price
      parameters:
        - name: symbol
          in: query
          required: true
          schema:
            type: string
        - name: date
          in: query
          required: true
          schema:
            type: string
            format: date
          description: Date in YYYY-MM-DD format
      responses:
        '200':
          description: Historical price data

  /crypto/trending:
    get:
      summary: Get trending cryptocurrencies
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 50
      responses:
        '200':
          description: Trending coins

  /crypto/rankings:
    get:
      summary: Get top cryptocurrencies by market cap
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
        - name: page
          in: query
          schema:
            type: integer
            default: 1
      responses:
        '200':
          description: Market cap rankings

  /news:
    get:
      summary: Get news headlines
      parameters:
        - name: category
          in: query
          schema:
            type: string
            enum: [general, business, technology, sports, entertainment, health, science]
            default: general
        - name: sentiment
          in: query
          schema:
            type: boolean
            default: false
        - name: fields
          in: query
          schema:
            type: string
      responses:
        '200':
          description: News articles
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NewsResponse'

  /batch:
    post:
      summary: Execute multiple API calls
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchRequest'
      responses:
        '200':
          description: Batch results

  /webhooks/register:
    post:
      summary: Register a webhook (Beta)
      description: |
        Register a webhook to receive notifications when conditions are met.
        
        **Security:** URLs are validated at registration AND delivery time. 
        Private IPs, localhost, and metadata endpoints are blocked.
        
        **Rate limiting:** Webhooks are capped at 1 delivery per hour per condition to prevent spam.
        
        **Supported types:**
        - `crypto`: Price threshold alerts (above/below)
        - `weather`: Temperature and wind thresholds
        - `news`: Category + keyword matching
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookRegistration'
      responses:
        '200':
          description: Webhook registered
        '400':
          description: Validation error

  /webhooks/list:
    get:
      summary: List active webhooks
      responses:
        '200':
          description: Webhook list

  /webhooks/{id}:
    delete:
      summary: Delete a webhook
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Webhook deleted

  /forex:
    get:
      summary: Get current exchange rates (Starter+)
      description: ECB exchange rates via Frankfurter. Updated daily.
      parameters:
        - name: base
          in: query
          schema:
            type: string
            default: USD
        - name: symbols
          in: query
          description: Comma-separated target currencies (e.g., EUR,GBP,JPY)
          schema:
            type: string
      responses:
        '200':
          description: Exchange rates
        '403':
          description: Plan upgrade required

  /forex/history:
    get:
      summary: Get historical exchange rate (Starter+)
      parameters:
        - name: date
          in: query
          required: true
          schema:
            type: string
            format: date
        - name: base
          in: query
          schema:
            type: string
            default: USD
        - name: symbols
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Historical exchange rate
        '403':
          description: Plan upgrade required

  /timezone:
    get:
      summary: Get current time for a timezone (Starter+)
      parameters:
        - name: location
          in: query
          required: true
          description: IANA timezone (e.g., America/New_York)
          schema:
            type: string
      responses:
        '200':
          description: Timezone data
        '403':
          description: Plan upgrade required

  /timezone/list:
    get:
      summary: List all available timezones (Starter+)
      responses:
        '200':
          description: Array of IANA timezone identifiers
        '403':
          description: Plan upgrade required

  /air-quality:
    get:
      summary: Get air quality index (Starter+)
      parameters:
        - name: location
          in: query
          description: City name
          schema:
            type: string
        - name: lat
          in: query
          schema:
            type: number
        - name: lon
          in: query
          schema:
            type: number
      responses:
        '200':
          description: AQI and pollutant readings
        '403':
          description: Plan upgrade required

  /geocode:
    get:
      summary: Geocode a place name (Starter+)
      parameters:
        - name: query
          in: query
          required: true
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            default: 5
            maximum: 10
      responses:
        '200':
          description: Geocoding results
        '403':
          description: Plan upgrade required

  /ip-lookup:
    get:
      summary: IP geolocation lookup (Starter+)
      parameters:
        - name: ip
          in: query
          description: IP address (default is requesting IP)
          schema:
            type: string
      responses:
        '200':
          description: IP geolocation data
        '403':
          description: Plan upgrade required

  /holidays:
    get:
      summary: Get public holidays (Starter+)
      parameters:
        - name: country
          in: query
          schema:
            type: string
            default: US
          description: ISO 3166-1 country code
        - name: year
          in: query
          schema:
            type: integer
          description: Year (default current year)
      responses:
        '200':
          description: Public holidays list
        '403':
          description: Plan upgrade required

  /endpoints:
    get:
      summary: Discover available endpoints for your plan
      responses:
        '200':
          description: Endpoint listing with accessibility info

  /echo:
    post:
      summary: Echo request details (for debugging)
      responses:
        '200':
          description: Echoed request info

  /mock/weather:
    get:
      summary: Mock weather (no auth, no limits)
      security: []
      responses:
        '200':
          description: Mock data

  /mock/crypto:
    get:
      summary: Mock crypto (no auth, no limits)
      security: []
      responses:
        '200':
          description: Mock data

  /mock/news:
    get:
      summary: Mock news (no auth, no limits)
      security: []
      responses:
        '200':
          description: Mock data


