{
  "openapi": "3.0.1",
  "info": {
    "title": "UK Planning Applications Scraper — Agent Contacts",
    "description": "New planning applications from 31 UK councils (Leeds, Westminster, Glasgow, Edinburgh, Southwark…) plus any Idox portal. Applicant, agent name, phone & email, status, decision, deadlines. Daily monitoring.",
    "version": "0.1",
    "x-build-id": "CAOWLT6uNMfAIL9Yi"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/spotless_studios~uk-planning-applications-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-spotless_studios-uk-planning-applications-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/spotless_studios~uk-planning-applications-scraper/runs": {
      "post": {
        "operationId": "runs-sync-spotless_studios-uk-planning-applications-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/spotless_studios~uk-planning-applications-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-spotless_studios-uk-planning-applications-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": {
          "councils": {
            "title": "Councils",
            "type": "array",
            "description": "Pick one or more councils. Empty (with no custom portals) = Leeds and Glasgow.",
            "items": {
              "type": "string",
              "enum": [
                "aberdeen",
                "barnet",
                "brent",
                "cambridge",
                "canterbury",
                "cornwall",
                "croydon",
                "derby",
                "dundee",
                "ealing",
                "edinburgh",
                "fife",
                "glasgow",
                "greenwich",
                "hammersmith",
                "lambeth",
                "leeds",
                "lewisham",
                "midkent",
                "newham",
                "norwich",
                "nottingham",
                "oxford",
                "sheffield",
                "southampton",
                "southwark",
                "swansea",
                "towerhamlets",
                "westminster",
                "wolverhampton",
                "york"
              ],
              "enumTitles": [
                "Aberdeen City Council",
                "London Borough of Barnet",
                "London Borough of Brent",
                "Greater Cambridge Shared Planning",
                "Canterbury City Council",
                "Cornwall Council",
                "London Borough of Croydon",
                "Derby City Council",
                "Dundee City Council",
                "London Borough of Ealing",
                "City of Edinburgh Council",
                "Fife Council",
                "Glasgow City Council",
                "Royal Borough of Greenwich",
                "London Borough of Hammersmith & Fulham",
                "London Borough of Lambeth",
                "Leeds City Council",
                "London Borough of Lewisham",
                "Mid Kent (Maidstone, Swale, Tunbridge Wells)",
                "London Borough of Newham",
                "Norwich City Council",
                "Nottingham City Council",
                "Oxford City Council",
                "Sheffield City Council",
                "Southampton City Council",
                "London Borough of Southwark",
                "Swansea Council",
                "London Borough of Tower Hamlets",
                "Westminster City Council",
                "City of Wolverhampton Council",
                "City of York Council"
              ]
            },
            "default": [
              "leeds",
              "glasgow"
            ]
          },
          "customPortalUrls": {
            "title": "Other Idox portals",
            "type": "array",
            "description": "Any other council's Idox Public Access URL, e.g. https://planning.example.gov.uk/online-applications. Recognisable by 'search.do' / 'applicationDetails.do' in the address bar.",
            "items": {
              "type": "string"
            }
          },
          "dateType": {
            "title": "Date to search by",
            "enum": [
              "validated",
              "received",
              "decision"
            ],
            "type": "string",
            "description": "Validated = new applications accepted by the council (best for leads). Decision = recently decided. Received is used where the council supports it.",
            "default": "validated"
          },
          "daysBack": {
            "title": "Days back",
            "minimum": 1,
            "maximum": 3650,
            "type": "integer",
            "description": "Search the last N days (including today). Ignored when Date from is set.",
            "default": 7
          },
          "dateFrom": {
            "title": "Date from",
            "type": "string",
            "description": "YYYY-MM-DD or relative, e.g. 30 days."
          },
          "dateTo": {
            "title": "Date to",
            "type": "string",
            "description": "YYYY-MM-DD. Default: today."
          },
          "proposalContains": {
            "title": "Proposal contains (server-side)",
            "type": "string",
            "description": "Council-side search on the proposal text, e.g. 'loft conversion' or 'solar'. Fastest way to narrow big councils."
          },
          "postcodes": {
            "title": "Postcodes",
            "type": "array",
            "description": "Area (LS), district (LS6, SW1), sector (LS6 2), or full postcode.",
            "items": {
              "type": "string"
            }
          },
          "statuses": {
            "title": "Statuses",
            "type": "array",
            "description": "e.g. Current, Awaiting decision, Decided, Registered, Withdrawn.",
            "items": {
              "type": "string"
            }
          },
          "applicationTypes": {
            "title": "Application types (needs details)",
            "type": "array",
            "description": "e.g. Householder, Full Planning, Listed Building, Prior Approval, Change of Use.",
            "items": {
              "type": "string"
            }
          },
          "excludeApplicationTypes": {
            "title": "Exclude application types (needs details)",
            "type": "array",
            "description": "e.g. Tree Works, Advertisement, Discharge of Condition, Non Material Amendment.",
            "items": {
              "type": "string"
            }
          },
          "decisions": {
            "title": "Decisions (needs details)",
            "type": "array",
            "description": "e.g. Approved, Granted, Refused.",
            "items": {
              "type": "string"
            }
          },
          "wards": {
            "title": "Wards / parishes (needs details)",
            "type": "array",
            "description": "Ward, parish, or community council names.",
            "items": {
              "type": "string"
            }
          },
          "applicationUrls": {
            "title": "Direct application URLs",
            "type": "array",
            "description": "Fetch specific Idox planning application detail URLs (containing keyVal=...) directly without running a date-range search.",
            "items": {
              "type": "string"
            }
          },
          "includeDetails": {
            "title": "Include details & contacts",
            "type": "boolean",
            "description": "Visit each application for application type, case officer, ward, applicant, agent name, company, address, phone, and email, plus consultation and decision deadlines. Billed as an add-on per application.",
            "default": false
          },
          "requireAgentContact": {
            "title": "Only with agent phone or email",
            "type": "boolean",
            "description": "Keep only applications whose agent published a phone number or email.",
            "default": false
          },
          "includeKeywords": {
            "title": "Include keywords",
            "type": "array",
            "description": "Keep applications whose proposal, address, type, applicant, or agent contain these words. /regex/ supported.",
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Drop applications containing any of these words or /regex/, e.g. tree, TPO, advertisement.",
            "items": {
              "type": "string"
            }
          },
          "keywordMatch": {
            "title": "Include keyword logic",
            "enum": [
              "any",
              "all"
            ],
            "type": "string",
            "description": "Require any or all include keywords.",
            "default": "any"
          },
          "onlyNewItems": {
            "title": "Only new applications (monitoring mode)",
            "type": "boolean",
            "description": "Remember applications from previous runs and save only new ones. Schedule daily with Days back = 3.",
            "default": false
          },
          "stateKey": {
            "title": "Monitor name",
            "type": "string",
            "description": "Separate memory per saved search.",
            "default": "default"
          },
          "maxResults": {
            "title": "Max applications",
            "minimum": 1,
            "maximum": 200000,
            "type": "integer",
            "description": "Stop after saving this many applications in total.",
            "default": 50
          },
          "maxResultsPerCouncil": {
            "title": "Max applications per council",
            "minimum": 1,
            "type": "integer",
            "description": "Keeps one big council from using the whole budget."
          },
          "outputPreset": {
            "title": "Data preset",
            "enum": [
              "full",
              "lean",
              "contacts"
            ],
            "type": "string",
            "description": "Quickly choose how much data to save per record: full record, lean summary, or contact & social links only.",
            "default": "full"
          },
          "outputFields": {
            "title": "Output fields",
            "type": "array",
            "description": "Save only these fields, in this order (e.g. councilName, reference, address, postcode, proposal, agentName, agentEmail, agentPhone). Supports nested dot-paths (e.g. makers.username). Empty keeps all fields from the selected preset.",
            "items": {
              "type": "string"
            }
          },
          "excludeFields": {
            "title": "Exclude fields",
            "type": "array",
            "description": "Remove specific fields (or nested dot-paths) from each saved record to keep datasets compact.",
            "items": {
              "type": "string"
            }
          },
          "includeEmptyFields": {
            "title": "Keep empty / null fields",
            "type": "boolean",
            "description": "When turned off, strips null, empty strings, empty arrays, and empty objects from every saved record.",
            "default": true
          },
          "requiredFields": {
            "title": "Required non-empty fields",
            "type": "array",
            "description": "Only save (and only pay for) records where every listed field or dot-path has a non-empty value (e.g. website, inquiryEmail).",
            "items": {
              "type": "string"
            }
          },
          "maxConcurrency": {
            "title": "Councils in parallel",
            "minimum": 1,
            "maximum": 16,
            "type": "integer",
            "description": "Councils searched at the same time.",
            "default": 4
          },
          "detailConcurrency": {
            "title": "Detail pages in parallel (per council)",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Council servers are slow; keep this low to be polite and avoid errors.",
            "default": 2
          },
          "minRequestIntervalMs": {
            "title": "Min gap between requests per council (ms)",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Politeness delay per council server. Doubles automatically if a council answers 'too many requests'.",
            "default": 600
          },
          "dateChunkDays": {
            "title": "Date window (days)",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "Long ranges are searched in windows of this size. Windows that hit a council's result cap are split automatically.",
            "default": 14
          },
          "maxRequestRetries": {
            "title": "Max retries per request",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Retries with exponential backoff on timeouts, 429, and 5xx responses.",
            "default": 4
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 5,
            "maximum": 300,
            "type": "integer",
            "description": "Council portals can be slow.",
            "default": 60
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Not needed for most councils. A few block non-UK traffic; use Apify Proxy with country GB for those.",
            "default": {
              "useApifyProxy": false
            }
          },
          "proxyEscalation": {
            "title": "Auto-escalate proxies when blocked",
            "type": "boolean",
            "description": "If the site blocks the run, automatically step up from a direct connection to Apify datacenter proxy, then residential proxy, only for the blocked site. Turn off to use exactly the proxy above.",
            "default": true
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}