{
  "openapi": "3.0.1",
  "info": {
    "title": "US Building Permits — Accela Citizen Access (Any City)",
    "description": "Get new building permits from any US city or county on Accela Citizen Access: roofing, solar, pool, HVAC, new construction and remodel permits with address, dates, status, valuation and contractor. Daily monitor mode with Telegram, Slack, webhook (n8n/Make) and email alerts.",
    "version": "1.0",
    "x-build-id": "htdfxX6JOaVtvumX8"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/egra_van~accela-building-permits/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-egra_van-accela-building-permits",
        "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/egra_van~accela-building-permits/runs": {
      "post": {
        "operationId": "runs-sync-egra_van-accela-building-permits",
        "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/egra_van~accela-building-permits/run-sync": {
      "post": {
        "operationId": "run-sync-egra_van-accela-building-permits",
        "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": {
          "agencies": {
            "title": "Cities / counties",
            "type": "array",
            "description": "Accela Citizen Access portals to search, by agency code (the part after aca-prod.accela.com/ in the portal address). Each one uses its usual permit module (Building, Permits or Development) unless you set \"Module\". Not in the list? Add it under \"Other agencies\".",
            "items": {
              "type": "string",
              "enum": [
                "PIMA",
                "LANCASTER",
                "OAKLAND",
                "ONT",
                "SACRAMENTO",
                "SANDIEGO",
                "SJCO",
                "SANTACLARA",
                "DENVER",
                "CLEARWATER",
                "FTL",
                "HCFL",
                "PASCO",
                "PINELLAS",
                "TAMPA",
                "WESTON",
                "ATLANTA_GA",
                "INDY",
                "LEXKY",
                "LJCMG",
                "AACO",
                "CABARRUS",
                "CLARKCO",
                "OKC",
                "CLACKAMAS",
                "DALLASTX",
                "FORTWORTH",
                "PHARR",
                "COSA",
                "SLCREF",
                "CVB",
                "COWLITZ"
              ],
              "enumTitles": [
                "Pima County, AZ (PIMA)",
                "Lancaster, CA (LANCASTER, Permits)",
                "Oakland, CA (OAKLAND)",
                "Ontario, CA (ONT)",
                "Sacramento, CA (SACRAMENTO)",
                "San Diego County, CA (SANDIEGO)",
                "San Joaquin County, CA (SJCO)",
                "Santa Clara, CA (SANTACLARA)",
                "Denver, CO (DENVER, Development)",
                "Clearwater, FL (CLEARWATER)",
                "Fort Lauderdale, FL (FTL, Permits)",
                "Hillsborough County, FL (HCFL)",
                "Pasco County, FL (PASCO)",
                "Pinellas County, FL (PINELLAS)",
                "Tampa, FL (TAMPA)",
                "Weston, FL (WESTON)",
                "Atlanta, GA (ATLANTA_GA)",
                "Indianapolis, IN (INDY, Permits)",
                "Lexington, KY (LEXKY)",
                "Louisville / Jefferson County, KY (LJCMG)",
                "Anne Arundel County, MD (AACO, Permits)",
                "Cabarrus County, NC (CABARRUS, Permits)",
                "Clark County, NV (CLARKCO)",
                "Oklahoma City, OK (OKC, Permits)",
                "Clackamas County, OR (CLACKAMAS)",
                "Dallas (DallasNow), TX (DALLASTX)",
                "Fort Worth, TX (FORTWORTH, Development)",
                "Pharr, TX (PHARR)",
                "San Antonio, TX (COSA)",
                "Salt Lake City, UT (SLCREF)",
                "Virginia Beach, VA (CVB, Permits)",
                "Cowlitz County, WA (COWLITZ, Permits)"
              ]
            }
          },
          "customAgencies": {
            "title": "Other agencies (code or portal URL)",
            "type": "array",
            "description": "Any other Accela Citizen Access portal: an agency code such as \"SPOKANE\" or \"KERNCO\", or the full URL of its search page, e.g. \"https://aca-prod.accela.com/TAMPA/Cap/CapHome.aspx?module=Building\" or a self-hosted one like \"https://accela.fortworthtexas.gov/CitizenAccess/Cap/CapHome.aspx?module=Development\". A module in the URL is used for that portal.",
            "items": {
              "type": "string"
            }
          },
          "module": {
            "title": "Module",
            "type": "string",
            "description": "ACA module to search, as in the portal address (…/CapHome.aspx?module=Building). Empty = each agency's usual permit module (Building for most; Permits or Development for some). Other modules such as Enforcement or Planning also work if the portal offers a public date search."
          },
          "lastNDays": {
            "title": "Last N days",
            "minimum": 1,
            "maximum": 3650,
            "type": "integer",
            "description": "Permits opened (applied/filed) in the last N days, today included. Used when \"Opened from\" is empty. For a daily monitor keep 3–7 so permits the city enters late are still caught.",
            "default": 7
          },
          "dateFrom": {
            "title": "Opened from",
            "type": "string",
            "description": "Start of the period (record opened/applied date, the date ACA's general search filters on), e.g. 2026-09-01 or \"30 days\". Overrides \"Last N days\"."
          },
          "dateTo": {
            "title": "Opened until",
            "type": "string",
            "description": "End of the period (inclusive). Empty = today."
          },
          "permitTypes": {
            "title": "Permit types / keywords",
            "type": "array",
            "description": "Keep only matching permits. Trade names match the permit's category: roofing (or \"roof\"), solar, pool, hvac, electrical, plumbing, new-construction (or \"new\"), addition, remodel, demolition, windows, fence, sign, accessory-structure, mobile-home. Any other word is searched in record type, description and project name (word start, case-insensitive). Empty = all permits.",
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Skip permits whose record type, description or project name contains any of these words, e.g. \"commercial\" or \"fence\".",
            "items": {
              "type": "string"
            }
          },
          "statuses": {
            "title": "Statuses",
            "type": "array",
            "description": "Keep only permits whose status contains one of these words, e.g. \"Issued\" or \"Finaled\" (case-insensitive). Statuses differ per city; see the \"status\" field of a first run. Empty = any status.",
            "items": {
              "type": "string"
            }
          },
          "recordTypes": {
            "title": "Portal record types (server-side filter)",
            "type": "array",
            "description": "Optional: search only these entries of the portal's \"Record Type\" dropdown (text contains, case-insensitive), e.g. \"Roof\" or \"Residential Solar\". Faster on busy portals because the portal filters. If nothing matches, the log lists the portal's record types and all types are searched.",
            "items": {
              "type": "string"
            }
          },
          "maxRecordsPerAgency": {
            "title": "Max permits per agency",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after saving this many matching permits per agency (newest first). 0 = no limit.",
            "default": 500
          },
          "includeDetails": {
            "title": "Include details (contractor, valuation, parcel)",
            "type": "boolean",
            "description": "Open each permit's detail page to add contractor name, license, phone and address, job valuation, parcel number, applicant company and extra fields. One extra request per permit and one extra \"permit details\" charge.",
            "default": false
          },
          "includePersonalNames": {
            "title": "Include owner and applicant names",
            "type": "boolean",
            "description": "With details on, also output the property owner's name and mailing address and the applicant's name when the portal publishes them. Off by default: these are private individuals; check the laws that apply to you (e.g. telemarketing and privacy rules) before using them for outreach.",
            "default": false
          },
          "monitorName": {
            "title": "Monitor name (only new permits)",
            "type": "string",
            "description": "Turns on monitor mode: the Actor remembers which permits it has seen under this name and each run saves (and alerts about) only new ones. Schedule it daily. The first run only remembers the current permits unless \"Report all on first run\" is on."
          },
          "reportAllOnFirstRun": {
            "title": "Report all on first run",
            "type": "boolean",
            "description": "In monitor mode, save and alert about all matching permits of the period on the first run too (normally the first run is a silent baseline).",
            "default": false
          },
          "resetState": {
            "title": "Start over",
            "type": "boolean",
            "description": "Forget everything this monitor has seen and create a new baseline.",
            "default": false
          },
          "telegramBotToken": {
            "title": "Telegram bot token",
            "type": "string",
            "description": "Token of your Telegram bot (from @BotFather). Alerts are sent in monitor mode."
          },
          "telegramChatId": {
            "title": "Telegram chat ID",
            "type": "string",
            "description": "Chat, group or channel ID that receives the alerts (the bot must be a member)."
          },
          "slackWebhookUrl": {
            "title": "Slack webhook URL",
            "type": "string",
            "description": "Slack Incoming Webhook URL (https://hooks.slack.com/services/…)."
          },
          "webhookUrl": {
            "title": "Webhook URL (n8n, Make, Zapier)",
            "type": "string",
            "description": "Receives a JSON POST with a summary and the new permits (event \"permits.new\"), ready for n8n, Make or Zapier."
          },
          "emailTo": {
            "title": "Email to",
            "type": "string",
            "description": "Email address(es) for alerts, comma-separated. Sent through the apify/send-mail Actor."
          },
          "emailSubject": {
            "title": "Email subject",
            "type": "string",
            "description": "Custom subject for email alerts. Empty = \"<monitor>: N new building permit(s)\"."
          },
          "notifyMaxItems": {
            "title": "Permits listed per alert",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "How many new permits are listed in Telegram, Slack and email messages (the rest is summarised).",
            "default": 10
          },
          "webhookMaxItems": {
            "title": "Permits sent to the webhook",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "How many new permits are included in the webhook JSON body.",
            "default": 100
          },
          "notifyOnNoChanges": {
            "title": "Alert when nothing is new",
            "type": "boolean",
            "description": "Also send a message when a monitor run finds no new permits (useful as a heartbeat).",
            "default": false
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Apify Proxy is recommended. If a portal refuses datacenter IPs, choose RESIDENTIAL with country US.",
            "default": {
              "useApifyProxy": true
            }
          },
          "exportMode": {
            "title": "How to read results",
            "enum": [
              "auto",
              "grid",
              "csv"
            ],
            "type": "string",
            "description": "\"grid\" reads the results table page by page (10 rows per request) and gives every permit a direct link. \"csv\" clicks the portal's \"Download results\" when available: one request for the whole list, but no per-permit links, so details cannot be fetched. \"auto\" uses CSV only for pulls above 100 permits without details and outside monitor mode, and falls back to the grid when the export does not work.",
            "default": "auto"
          },
          "searchWindowDays": {
            "title": "Days per search",
            "minimum": 1,
            "maximum": 366,
            "type": "integer",
            "description": "Long periods are searched in windows of this many days, newest first, so a portal's result limits are not hit.",
            "default": 7
          },
          "maxPagesPerAgency": {
            "title": "Max result pages per search",
            "minimum": 1,
            "maximum": 2000,
            "type": "integer",
            "description": "Safety limit of result pages (10 permits each) read per search window.",
            "default": 100
          },
          "browserFallback": {
            "title": "Use a real browser when blocked",
            "type": "boolean",
            "description": "If a portal blocks plain HTTP requests, retry with cookies from a real Chrome, then fully inside Chrome.",
            "default": true
          },
          "forceBrowser": {
            "title": "Always use a real browser",
            "type": "boolean",
            "description": "Do every request inside Chrome from the start (slower; for portals known to need JavaScript).",
            "default": false
          },
          "requestDelayMs": {
            "title": "Delay between requests (ms)",
            "minimum": 0,
            "maximum": 20000,
            "type": "integer",
            "description": "Pause between requests to one portal, to be polite to city servers.",
            "default": 700
          },
          "maxRetries": {
            "title": "Retries",
            "minimum": 0,
            "maximum": 8,
            "type": "integer",
            "description": "How often a failed request or blocked session is retried (with a new session and IP) before an agency is given up.",
            "default": 3
          },
          "saveDebugPages": {
            "title": "Save pages when something fails",
            "type": "boolean",
            "description": "Store unexpected portal pages in the key-value store (DEBUG-…) so problems can be diagnosed.",
            "default": true
          },
          "stateStoreName": {
            "title": "Monitor state store",
            "type": "string",
            "description": "Named key-value store that keeps monitor memory between runs.",
            "default": "accela-permits-monitor"
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}