{
  "openapi": "3.0.1",
  "info": {
    "title": "Ryanair Flight Fares Scraper [Just 💰$0.18]",
    "description": "Get Ryanair fares per day for a route like BER-MAD or from one airport: price and currency, departure and arrival times, sold-out flags and the booking link. Structured rows that load straight into fare tracking or a spreadsheet.",
    "version": "0.1",
    "x-build-id": "yje2mlRfcz4RdgxoU"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/blackfalcondata~ryanair-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-blackfalcondata-ryanair-com-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/blackfalcondata~ryanair-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-blackfalcondata-ryanair-com-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/blackfalcondata~ryanair-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-blackfalcondata-ryanair-com-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "title": "✈️ Route or Origin Airport",
            "type": "string",
            "description": "What to look up, as Ryanair airport codes (IATA, 3 letters). `BER-MAD` returns a day-by-day price calendar for that route (one month per page). A single code such as `BER` returns the cheapest fare to every destination from that airport. For several searches use a JSON array, e.g. `[\"BER-MAD\",\"DUB-STN\"]`."
          },
          "location": {
            "title": "📅 Date Range",
            "type": "string",
            "description": "Route calendar (`BER-MAD`): the first month as `YYYY-MM`, e.g. `2026-11`; later pages continue month by month, up to 12 months ahead. Origin only (`BER`): a departure window `YYYY-MM-DD..YYYY-MM-DD`, e.g. `2026-11-01..2026-11-30`. Leave empty for the current month, or the next 30 days. The Depart From / Depart To fields below take precedence when set."
          },
          "market": {
            "title": "🌍 Market",
            "type": "string",
            "description": "Language and country of the Ryanair site, as `language-country`, e.g. `en-gb`, `de-de`, `es-es`. Default `en-gb`. It sets the booking links and the market the cheapest-fare list is requested for.",
            "default": "en-gb"
          },
          "maxResults": {
            "title": "💯 Max Results",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "Maximum total results (0 = unlimited).",
            "default": 100
          },
          "startUrls": {
            "title": "🔗 Start URLs",
            "type": "array",
            "description": "Paste raw search URLs from the target site. Each URL becomes its own search task; results are merged and deduped by listing ID across all URLs. A pasted flight-selection link keeps its exact outbound day, its return day (round trip), passengers and the site language/country; a fare-finder link keeps its outbound and return windows. These override the matching fields above for that link only. When provided, startUrls REPLACE the query/location fields (each supported URL becomes one task; unsupported URLs are skipped, and if none is supported the run stops with an input error).",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "tripType": {
            "title": "🔁 Trip Type",
            "enum": [
              "oneWay",
              "roundTrip"
            ],
            "type": "string",
            "description": "One way (default) or round trip. A round trip on a route (`BER-MAD`) returns one row per outbound day, paired with the cheapest return flight inside the return window that leaves after the outbound lands; the price is the total of both legs per person. A round trip on an origin only (`BER`) returns Ryanair's cheapest return deals with both legs.",
            "default": "oneWay"
          },
          "departDateFrom": {
            "title": "🛫 Depart From",
            "type": "string",
            "description": "First outbound day, `YYYY-MM-DD`. Set it equal to Depart To for one exact day. Replaces the Date Range field when set."
          },
          "departDateTo": {
            "title": "🛫 Depart To",
            "type": "string",
            "description": "Last outbound day, `YYYY-MM-DD`. Leave empty to continue to the end of the booking window (a route calendar) or 30 days (an origin only)."
          },
          "returnDateFrom": {
            "title": "🛬 Return From",
            "type": "string",
            "description": "Round trips only: first return day, `YYYY-MM-DD`. Default: the first outbound day."
          },
          "returnDateTo": {
            "title": "🛬 Return To",
            "type": "string",
            "description": "Round trips only: last return day, `YYYY-MM-DD`. Default: the last outbound day plus 7 days."
          },
          "allFlights": {
            "title": "🕒 All Flights Per Day",
            "type": "boolean",
            "description": "Route search, one way only: return a row for every scheduled flight of each day instead of only the day's cheapest. Ryanair prices the day, not each flight, so only the cheapest flight carries `price` (the other flights have `price: null`); every row shows `dayCheapestPrice` and `isDayCheapest`. Ignored (with a log warning) for round trips and for an origin-only search.",
            "default": false
          },
          "currency": {
            "title": "💱 Currency",
            "type": "string",
            "description": "Currency code the fares are quoted in, e.g. `EUR`, `GBP`, `USD`, `PLN`. Default `EUR`. Ryanair decides which currencies exist per route.",
            "default": "EUR"
          },
          "adults": {
            "title": "🧑 Adults",
            "minimum": 1,
            "type": "integer",
            "description": "Passengers aged 16+. Default 1. Fares are always per person; this only sets the passenger counts on the result and in the booking link.",
            "default": 1
          },
          "teens": {
            "title": "🧒 Teens",
            "minimum": 0,
            "type": "integer",
            "description": "Passengers aged 12-15. Default 0.",
            "default": 0
          },
          "children": {
            "title": "👶 Children",
            "minimum": 0,
            "type": "integer",
            "description": "Passengers aged 2-11. Default 0.",
            "default": 0
          },
          "infants": {
            "title": "🍼 Infants",
            "minimum": 0,
            "type": "integer",
            "description": "Passengers under 2. Default 0.",
            "default": 0
          },
          "maxPrice": {
            "title": "💰 Max Price",
            "minimum": 0,
            "type": "number",
            "description": "Only return fares up to this price per person, in the chosen currency. For a round trip the total of both legs counts. Empty = no price limit. Days without a price are left out when this is set."
          },
          "includeUnavailable": {
            "title": "🚫 Include Sold-Out / Unavailable Days",
            "type": "boolean",
            "description": "Keep days with no bookable fare (sold out or not flown), marked `available: false`, so a calendar has no gaps. Turn off to return bookable fares only.",
            "default": true
          },
          "sortBy": {
            "title": "↕️ Sort By",
            "enum": [
              "sourceOrder",
              "cheapest",
              "earliestDeparture",
              "shortestDuration"
            ],
            "type": "string",
            "description": "Order of the delivered results: Source order (as Ryanair serves them, streamed while scraping), Cheapest, Earliest departure or Shortest duration. A sorted run delivers its results at the end of the run instead of streaming them.",
            "default": "sourceOrder"
          },
          "compact": {
            "title": "📦 Compact Output",
            "type": "boolean",
            "description": "Core fare fields only (for AI-agent/MCP workflows).",
            "default": false
          },
          "excludeEmptyFields": {
            "title": "Exclude empty fields from output",
            "type": "boolean",
            "description": "Drop null, empty-string, and empty-array fields from each record before push. Smaller payloads for AI agents and dashboards.",
            "default": false
          },
          "descriptionFormat": {
            "title": "📝 Description Format",
            "enum": [
              "all",
              "text",
              "html",
              "markdown"
            ],
            "type": "string",
            "description": "Choose which representation of the listing description to include. `all` keeps every variant; the others keep only the selected one.",
            "default": "all"
          },
          "incrementalMode": {
            "title": "♻️ Incremental Mode",
            "type": "boolean",
            "description": "Compare against previous run state. stateKey is optional — defaults to a value derived from the search inputs (route or origin, dates, trip type, currency, market, passengers, price limit, startUrls) so different searches never share state. Sort By does not change it.",
            "default": false
          },
          "stateKey": {
            "title": "🔑 State Key",
            "type": "string",
            "description": "Optional. Stable identifier for the tracked search universe. Leave empty to auto-generate from search inputs."
          },
          "emitUnchanged": {
            "title": "🔁 Emit Unchanged",
            "type": "boolean",
            "description": "When Incremental Mode is on, also return fares whose price and availability have not changed since the previous run. Off by default: only new and changed fares are returned.",
            "default": false
          },
          "skipReposts": {
            "title": "🚫 Skip Reposts",
            "type": "boolean",
            "description": "When incremental, skip listings whose content matches an expired listing from a prior run (cross-run duplicate detection).",
            "default": false
          },
          "notifyOnlyChanges": {
            "title": "🔄 Notify Only New/Updated",
            "type": "boolean",
            "description": "When Incremental Mode is on, only send notifications for NEW and UPDATED listings. Has no effect outside incremental mode.",
            "default": false
          },
          "notificationLimit": {
            "title": "📊 Max Listings Per Notification",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of listings included in each notification message (1–20).",
            "default": 5
          },
          "telegramToken": {
            "title": "🔑 Telegram Bot Token",
            "type": "string",
            "description": "Telegram bot token (from @BotFather). Required for Telegram notifications."
          },
          "telegramChatId": {
            "title": "💬 Telegram Chat ID",
            "type": "string",
            "description": "Telegram chat or channel ID (e.g. \"-100123456789\"). Required when telegramToken is set."
          },
          "discordWebhookUrl": {
            "title": "🎮 Discord Webhook URL",
            "type": "string",
            "description": "Discord incoming webhook URL. Server Settings → Integrations → Webhooks → New Webhook."
          },
          "slackWebhookUrl": {
            "title": "💼 Slack Webhook URL",
            "type": "string",
            "description": "Slack incoming webhook URL. api.slack.com/messaging/webhooks."
          },
          "whatsappPhoneNumberId": {
            "title": "📞 WhatsApp Phone Number ID",
            "type": "string",
            "description": "Your WhatsApp Business phone-number ID (numeric, from Meta dashboard). Required when whatsappAccessToken is set."
          },
          "whatsappAccessToken": {
            "title": "📱 WhatsApp Access Token",
            "type": "string",
            "description": "WhatsApp Cloud API permanent access token (System User token from Meta Business). Recipient must have messaged the business number within the last 24h (service-conversation window — free since Nov 2024)."
          },
          "whatsappTo": {
            "title": "📲 WhatsApp Recipient",
            "type": "string",
            "description": "Recipient phone in E.164 format without + (e.g. \"436641234567\"). Recipient must have messaged your business number within last 24h."
          },
          "webhookUrl": {
            "title": "🪝 Generic Webhook URL",
            "type": "string",
            "description": "Receives a JSON POST with {metadata, items} after each run. Universal escape hatch for n8n / Make / Zapier / custom backends."
          },
          "webhookHeaders": {
            "title": "📋 Webhook Headers",
            "type": "object",
            "description": "Optional JSON object of custom headers (e.g. {\"Authorization\":\"Bearer ...\"})."
          },
          "appConnector": {
            "title": "Send results to a connected app",
            "type": "string",
            "description": "Optional. Pick a connected app under Settings → API & Integrations to receive your results (including any contact details). Best-effort across MCP connectors as Apify expands its catalog."
          },
          "mcpIssueTeam": {
            "title": "Issue tracker team",
            "type": "string",
            "description": "Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one."
          },
          "maxPages": {
            "title": "📄 Max Pages",
            "minimum": 0,
            "maximum": 12,
            "type": "integer",
            "description": "Maximum result pages per search (0 = all, until Ryanair has no more). For a route calendar one page is one month, so 3 returns the next three months. Origin-only searches page through the destinations.",
            "default": 0
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}