{
  "openapi": "3.0.1",
  "info": {
    "title": "outseo.lol Scraper - Organic Clicks & Rank Monitoring",
    "description": "outseo.lol organic traffic leaderboard as sortable rows: see real Search Console click volume for the indie SaaS sites ranked on it, never a traffic estimate. Get share of board, clicks per day, and change rows naming who climbed since your last run. Opt-in contact emails.",
    "version": "0.0",
    "x-build-id": "gkv1hOpzNHRoSKV4M"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/memo23~outseo-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-memo23-outseo-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/memo23~outseo-scraper/runs": {
      "post": {
        "operationId": "runs-sync-memo23-outseo-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/memo23~outseo-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-memo23-outseo-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": {
          "startUrls": {
            "title": "Start URLs (optional)",
            "type": "array",
            "description": "outseo.lol board URLs. The leaderboard is a single page, so this is optional — leave it empty and the whole board is scraped. Only outseo.lol URLs are accepted; anything else fails fast rather than silently scraping the board instead.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "minRank": {
            "title": "Minimum rank",
            "minimum": 0,
            "type": "integer",
            "description": "Start from this rank. Pair with 'Maximum rank' to pull a slice such as ranks 20-50 without paying for the rows above it. Empty or 0 = start at rank 1.",
            "default": 0
          },
          "maxRank": {
            "title": "Maximum rank",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this rank. Empty or 0 = the entire board. The whole leaderboard arrives in one request either way, so this trims the bill rather than the crawl.",
            "default": 0
          },
          "minOrganicClicks": {
            "title": "Minimum organic clicks",
            "minimum": 0,
            "type": "integer",
            "description": "Only entries with at least this many verified Search Console clicks over the board's window. Set to 1 to drop the long tail of sites that have connected but recorded nothing yet.",
            "default": 0
          },
          "maxOrganicClicks": {
            "title": "Maximum organic clicks",
            "minimum": 0,
            "type": "integer",
            "description": "Only entries with at most this many clicks — the 'who is still small' query. Empty or 0 = no ceiling.",
            "default": 0
          },
          "keywords": {
            "title": "Include keywords",
            "type": "array",
            "description": "Keep only entries matching any of these (case-insensitive substring). Matched against the domain, destination URL and description unless `keywordFields` narrows it. Example: `[\"ai\", \"video\"]` keeps every entry mentioning either. Empty = keep everything. Default `[]`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Drop entries matching any of these (case-insensitive substring). Applied after `keywords`, so an excluded term always wins. Example: `[\"casino\"]`. Empty = drop nothing. Default `[]`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "keywordFields": {
            "title": "Match keywords against",
            "type": "array",
            "description": "Restrict keyword matching to specific fields. Empty = match across the domain, URL and description at once.",
            "items": {
              "type": "string",
              "enum": [
                "domain",
                "url",
                "description"
              ],
              "enumTitles": [
                "Domain",
                "Destination URL",
                "Description"
              ]
            },
            "default": []
          },
          "domains": {
            "title": "Domains",
            "type": "array",
            "description": "Only entries on these domains. Subdomains are included automatically, and a bare TLD such as `.ai` matches every entry on it.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "includeSponsored": {
            "title": "Include paid sponsor placements",
            "type": "boolean",
            "description": "Emit the board's sponsored cards. They carry a name, description and destination but no rank and no click count, since the board does not measure them.",
            "default": false
          },
          "includeSpotlight": {
            "title": "Include the 'Lucky duck' spotlight",
            "type": "boolean",
            "description": "Emit the random spotlight card at the top of the page. It is drawn from the board itself, so it is normally already present as a ranked row — turning this on usually means one duplicated site.",
            "default": false
          },
          "monitorChanges": {
            "title": "Track changes since the last run",
            "type": "boolean",
            "description": "Emit `rowType: \"change\"` rows for entries that are new, gone, re-ranked, or moving on clicks. Each carries the previous value and the delta. The first run has nothing to compare against, so it stores a baseline and reports zero changes.",
            "default": false
          },
          "onlyChanges": {
            "title": "Emit only the changes",
            "type": "boolean",
            "description": "Skip the full board and return the change rows alone. This is the cheap scheduled-run setting: a quiet day costs a handful of rows instead of the entire board. Has no effect unless `monitorChanges` is also true. Example: `monitorChanges: true, onlyChanges: true`. Default false.",
            "default": false
          },
          "minClickJump": {
            "title": "Minimum click change to report",
            "minimum": 1,
            "type": "integer",
            "description": "A click move smaller than this is not a change. Search Console totals drift daily on every active site, so a threshold of 1 makes almost every entry a change row — raise it to see only meaningful movement.",
            "default": 1
          },
          "monitorStoreName": {
            "title": "Snapshot store name",
            "type": "string",
            "description": "Named key-value store holding the snapshot. Defaults to `outseo-monitor`. It must be a named store — a run's default store is created fresh each run, so a snapshot there would never survive to the next run. Give each scheduled monitor its own name so several can track different filters independently.",
            "default": ""
          },
          "sortBy": {
            "title": "Sort results by",
            "enum": [
              "rank",
              "clicksDesc",
              "clicksAsc",
              "domainAsc"
            ],
            "type": "string",
            "description": "Ordering of the entry rows: `rank` (board order), `clicksDesc`, `clicksAsc`, or `domainAsc`. Ranks are unaffected — a row always reports its real board position regardless of sort. Default `rank`.",
            "default": "rank"
          },
          "includeBoardStats": {
            "title": "Include board statistics row",
            "type": "boolean",
            "description": "Append one `rowType: \"boardStats\"` row with live visitors, the board's own benchmarked-site count, total and median organic clicks, the top site, and the asking price of every open sponsor slot. This row is never billed.",
            "default": true
          },
          "enrichEmails": {
            "title": "Find contact emails (opt-in)",
            "type": "boolean",
            "description": "Best-effort: visit each entry's own website and harvest contact emails, phone numbers and social profiles into `contactEmail` and `emailEnrichment`. Every entry on this board is a verified website, so no company-matching guesswork is involved. Billed only for entries where an email is actually found. Adds roughly a second per entry.",
            "default": false
          },
          "maxItems": {
            "title": "Maximum rows",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap on rows pushed to the dataset, counting entry and change rows together. Free-tier Apify accounts are capped at 100.",
            "default": 100000
          },
          "maxConcurrency": {
            "title": "Maximum concurrency",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Only used by the optional email enrichment — the board itself is a single request. Kept low on purpose so enrichment does not hammer the sites it visits.",
            "default": 8
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Runs direct by default, so you pay nothing for proxies. outseo.lol answers ordinary requests today. Should it ever switch on Vercel's security checkpoint the way its sibling board did, the actor clears it in-run on its own — still no proxy required. Enable one only if you want the traffic to originate from a specific network.",
            "default": {
              "useApifyProxy": false
            }
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}