{
  "openapi": "3.0.1",
  "info": {
    "title": "Building Permit Scraper: Contractor Leads & Status (Accela)",
    "description": "Building permit data and leads from any Accela Citizen Access city or county: permit type, status, address, valuation and contractor details, with status change alerts.",
    "version": "0.1",
    "x-build-id": "iZ6He5TVzXu7vdnQb"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/finaldynamics~building-permit-lookup-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-finaldynamics-building-permit-lookup-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/finaldynamics~building-permit-lookup-scraper/runs": {
      "post": {
        "operationId": "runs-sync-finaldynamics-building-permit-lookup-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/finaldynamics~building-permit-lookup-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-finaldynamics-building-permit-lookup-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": {
          "agency": {
            "title": "Agency key",
            "type": "string",
            "description": "Accela agency code, for example ATLANTA_GA, HCFL or SACRAMENTO; the README's Coverage table lists the 24 bundled ones. A bundled city name such as Atlanta or Hillsborough County also works. For another portal on aca-prod.accela.com, use the code after aca-prod.accela.com/ in its address.",
            "default": "ATLANTA_GA"
          },
          "portalUrl": {
            "title": "Agency portal URL",
            "type": "string",
            "description": "Only needed for a portal that is not bundled: its address on aca-prod.accela.com, for example https://aca-prod.accela.com/CITYNAME/. An address copied from its search page also works. The code in it must match the agency key. For a bundled agency, leave it empty or as it is.",
            "default": "https://aca-prod.accela.com/ATLANTA_GA/"
          },
          "module": {
            "title": "Module",
            "type": "string",
            "description": "Which part of the portal to search: Building (permits), Enforcement (code enforcement cases) or Planning (planning and zoning cases). Not every agency offers every module; the run says so when one is missing.",
            "default": "Building"
          },
          "dateFrom": {
            "title": "Applied date from",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2})?$",
            "type": "string",
            "description": "First applied date to search, YYYY-MM-DD, inclusive. Used when Last N days is 0. Leave both dates empty to search the last 7 days."
          },
          "dateTo": {
            "title": "Applied date to",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2})?$",
            "type": "string",
            "description": "Last applied date to search, YYYY-MM-DD, inclusive. Used when Last N days is 0. Leave both dates empty to search the last 7 days."
          },
          "lastDays": {
            "title": "Last N days",
            "minimum": 0,
            "maximum": 366,
            "type": "integer",
            "description": "Search the last N calendar days ending today (UTC), including today, so a saved task stays current. Set it to 0 to use the fixed dates above."
          },
          "recordTypes": {
            "title": "Portal permit types",
            "type": "array",
            "description": "Names from the module's Record Type menu on the portal's search page, for example \"Commercial Demolition\" in Atlanta. The portal then returns only those types, which is much faster. Up to 25; a name the portal does not offer stops the run and lists examples. Leave empty to let the actor pick the types matching Permit type contains; when it cannot, it reads every permit in the date range.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "permitTypeContains": {
            "title": "Permit type contains",
            "type": "array",
            "description": "Keep only permits whose type contains any of these words or phrases, ignoring case. Leave empty for every type. It still applies when Portal permit types is set.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "minValuation": {
            "title": "Minimum valuation (USD)",
            "minimum": 0,
            "type": "number",
            "description": "Keep only permits with a declared valuation of at least this amount; 0 keeps all. Valuation comes from each permit page, so turn on Include permit details; permits with no published valuation are dropped.",
            "default": 0
          },
          "maxResults": {
            "title": "Maximum permits delivered",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "The most rows one run delivers, and so the most rows you pay for. A run that stops here does not update the \"only new permits\" memory: nothing is skipped, but rows it delivered may come again, and be charged again, next time. For status tracking, set it above the number of permits in your date window: a tracking run that reaches it saves nothing.",
            "default": 200
          },
          "maxPages": {
            "title": "Maximum result pages read",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "The most search result pages one run reads, counting every record type it searches. A run that reaches it stops and says what to change: narrow the dates, choose Portal permit types or raise this limit. It keeps the rows found so far, except a status-tracking run, which saves nothing and leaves saved statuses unchanged. An \"only new permits\" run that stops here does not move its marker, so some rows may come again, and be charged again, next run.",
            "default": 60
          },
          "includeDetails": {
            "title": "Include permit details",
            "type": "boolean",
            "description": "Open each permit's own page to add the contractor, parcel, issue and final dates and valuation. Costs $0.004 per page fetched, even if Minimum valuation then drops the row. Rows are saved when the run ends: a run that is aborted or times out saves none, and so does one where more than 25 permit pages, or over 20% of those tried, fail to load. Owner names also need Include owner name.",
            "default": false
          },
          "includeOwnerName": {
            "title": "Include owner name",
            "type": "boolean",
            "description": "Add the property owner's name from the permit page, where published. Needs Include permit details. Off by default because owners are usually private individuals.",
            "default": false
          },
          "sinceLastRun": {
            "title": "Only permits newer than previous run",
            "type": "boolean",
            "description": "Deliver only permits with a newer applied date than the newest one a previous run delivered, and never the same permit twice. Needs a key-value store in the next field; give each schedule its own. A run that stops early does not move the marker: nothing is skipped, but rows it delivered may come again, and be charged again, next run. Cannot be combined with status tracking.",
            "default": false
          },
          "stateStoreId": {
            "title": "Store for new-only runs",
            "type": "string",
            "description": "Key-value store where \"only new permits\" runs remember what they delivered. Create one in Apify Console and select it here; use one per schedule."
          },
          "statusBaseline": {
            "title": "Previous permit statuses",
            "type": "array",
            "description": "Optional permit numbers with the status each had in an earlier run. Matching rows get previousStatus and statusChanged filled in. For scheduled tracking, the status tracking store below is simpler; the two cannot be combined.",
            "items": {
              "type": "object",
              "properties": {
                "permitNumber": {
                  "title": "Permit number",
                  "type": "string",
                  "description": "Permit number as an earlier run delivered it."
                },
                "status": {
                  "title": "Status",
                  "type": "string",
                  "description": "Status as that run delivered it."
                }
              },
              "required": [
                "permitNumber",
                "status"
              ],
              "additionalProperties": false
            },
            "default": []
          },
          "statusChangesOnly": {
            "title": "Only status changes",
            "type": "boolean",
            "description": "Deliver only permits from the list above whose status is different now. Needs at least one entry in the list. Cannot be combined with Only permits newer than previous run.",
            "default": false
          },
          "statusStateStoreId": {
            "title": "Status tracking store",
            "pattern": "^[A-Za-z0-9_-]{1,128}$",
            "type": "string",
            "description": "A key-value store where the actor remembers every permit's status between scheduled runs. The first complete run delivers everything and saves the statuses; later runs deliver only permits whose status changed. Use one store per schedule and let runs finish one at a time."
          },
          "statusMonitorMaxPages": {
            "title": "Maximum status-tracking pages",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Safety limit on search result pages a status-tracking run reads, counting every record type. A run that reaches it saves nothing and leaves saved statuses as they were. Maximum result pages read also applies; the lower limit wins.",
            "default": 100
          },
          "statusMonitorMaxRecords": {
            "title": "Maximum status-tracking records",
            "minimum": 1,
            "maximum": 50000,
            "type": "integer",
            "description": "Safety limit on permits a status-tracking run reads. A run that reaches it saves nothing and leaves saved statuses as they were.",
            "default": 5000
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}