{
  "openapi": "3.0.1",
  "info": {
    "title": "US Building Permits - Contractor Leads with Delta Mode",
    "description": "Call the contractor the week the permit is issued. Permits from 17 US city registers via official open-data APIs: contractor, license and phone, job value, GPS, trade and a lead score. New York and Mesa: is the license still active? Delta mode charges only new permits.",
    "version": "1.0",
    "x-build-id": "NlIPBTpha5lZI78yd"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/wellbuilt_zythem~us-building-permits/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-wellbuilt_zythem-us-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/wellbuilt_zythem~us-building-permits/runs": {
      "post": {
        "operationId": "runs-sync-wellbuilt_zythem-us-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/wellbuilt_zythem~us-building-permits/run-sync": {
      "post": {
        "operationId": "run-sync-wellbuilt_zythem-us-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": {
          "cities": {
            "title": "Cities",
            "type": "array",
            "description": "Leave empty for all seventeen. Each city comes from its own official open-data API, so it never breaks because a website changed its layout. Only Orlando, Austin, Mesa and the New York legacy register publish the contractor's phone; the others give the business name, and some the licence number.",
            "items": {
              "type": "string",
              "enum": [
                "orlando",
                "austin",
                "new_orleans",
                "seattle",
                "cincinnati",
                "baton_rouge",
                "marin_county",
                "new_york",
                "chicago",
                "new_york_electrical",
                "new_york_phone",
                "new_york_elevator",
                "new_york_street_construction",
                "somerville_ma",
                "everett",
                "mesa",
                "delaware_wells"
              ],
              "enumTitles": [
                "Orlando, FL (contractor + phone, ~2,500 permits/month)",
                "Austin, TX (contractor + phone + trade, ~4,700/month)",
                "New Orleans, LA (contractor + licence, ~1,500/month)",
                "Seattle, WA (contractor on trade permits, ~1,800/month)",
                "Cincinnati, OH (contractor, ~800/month)",
                "Baton Rouge, LA (contractor, ~560/month, published about 2 weeks late: use 30 days or more)",
                "Marin County, CA (contractor + licence, ~390/month)",
                "New York City (DOB NOW: business + licence + job cost, no phone)",
                "Chicago, IL (contractor contacts, ~3,000/month)",
                "New York City electrical permits (business + licence, no phone, no job value, ~4,100/month)",
                "New York City legacy register (business + PHONE + licence, no job value, no description, ~450/month)",
                "New York City elevators (business + licence + job cost, no phone, ~420/month)",
                "New York City street, sidewalk and utility work (business only, no phone, no job value, no GPS, ~59,000/month)",
                "Somerville, MA (contractor + job value, no phone, no licence, ~610/month)",
                "Everett, WA (contractor + job value, no phone, no licence, ~600/month)",
                "Mesa, AZ (contractor + phone + licence, but only on 43 % of permits, mostly commercial, ~450/month)",
                "Delaware statewide water wells (contractor + licence, no phone, no job value, ~220/month)"
              ]
            }
          },
          "discover": {
            "title": "Other cities (Socrata auto-discovery)",
            "type": "array",
            "description": "Any other US city with a Socrata open-data portal, by name (\"Fort Worth, TX\") or by portal domain (\"data.lacity.org\"). The run searches the Socrata catalog for that city's building-permit dataset, recognises its columns by name and reads it like the seventeen verified cities. Rows from these cities carry discovered: true, and the run summary lists the dataset it picked and which columns it recognised. Not measured like the seventeen: contractor and phone come only when the city publishes them under a recognisable column name, and a dataset with no recognisable issue date is refused rather than guessed. With this set and \"Cities\" empty, only the discovered cities run.",
            "items": {
              "type": "string"
            }
          },
          "trades": {
            "title": "Trades",
            "type": "array",
            "description": "Keep only permits for these trades, classified from the permit type and description. Leave empty for all.",
            "items": {
              "type": "string",
              "enum": [
                "roofing",
                "solar",
                "hvac",
                "electrical",
                "plumbing",
                "remodel",
                "new_construction",
                "demolition",
                "pool",
                "fence",
                "well_water",
                "elevator",
                "street_work",
                "other"
              ],
              "enumTitles": [
                "Roofing",
                "Solar / PV / battery",
                "HVAC / mechanical",
                "Electrical",
                "Plumbing / sewer / water heater",
                "Remodel / alteration / addition",
                "New construction",
                "Demolition",
                "Pool / spa",
                "Fence",
                "Water wells and boreholes (Delaware only)",
                "Elevators and escalators (New York only)",
                "Street, sidewalk and utility work (New York only)",
                "Other"
              ]
            }
          },
          "stage": {
            "title": "Stage",
            "enum": [
              "issued",
              "applied",
              "completed"
            ],
            "type": "string",
            "description": "Issued permits (default), permit applications, or completed work. An application not yet issued is a job starting in 4 to 10 weeks: the earliest lead there is. A completed permit is a finished job: the house is being lived in again, which is the lead for furniture, home insurance, alarms, cleaning and solar. Applications: Orlando, New Orleans, New York (electrical, elevator, BIS), Cincinnati, Seattle, Somerville, Everett, Mesa and Marin County. Completions: Austin, Orlando, New Orleans, Seattle, Cincinnati, Mesa, New York electrical and Delaware wells (the other cities publish no completion date and return nothing in this stage). In delta mode, use a different store name per stage.",
            "default": "issued"
          },
          "onlyPending": {
            "title": "Applications: only those not issued yet",
            "type": "boolean",
            "description": "In the applications stage, drop applications that already got their permit (those show up in the issued stage). Filtered-out rows cost nothing.",
            "default": true
          },
          "lastNDays": {
            "title": "Issued in the last N days",
            "minimum": 1,
            "maximum": 3650,
            "type": "integer",
            "description": "Permits issued (or, in the applications stage, applied for) in this many days before today. Ignored when \"Issued from\" is set, and in delta mode once a first run has stored its watermark.",
            "default": 7
          },
          "dateFrom": {
            "title": "Issued from (YYYY-MM-DD)",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string",
            "description": "Optional exact start date, overrides \"last N days\"."
          },
          "dateTo": {
            "title": "Issued to (YYYY-MM-DD)",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "type": "string",
            "description": "Optional exact end date, inclusive."
          },
          "onlyWithContractor": {
            "title": "Only permits with a contractor name",
            "type": "boolean",
            "description": "Drop permits pulled by the owner or with no contractor on file. Filtered-out rows cost nothing.",
            "default": true
          },
          "onlyLicenseIssues": {
            "title": "Only permits pulled with a license that is not active",
            "type": "boolean",
            "description": "New York City and Mesa only, the two places where the permit carries the contractor license number and the license register is public. Keeps the permits whose license the register shows as expired, on hold, inactive or not in the register (New York), or not in the active list (Mesa). Other cities are skipped. Every New York and Mesa permit carries licenseStatus anyway.",
            "default": false
          },
          "minValuation": {
            "title": "Minimum job value (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Keep permits with a declared job value at or above this. 0 keeps everything, including permits with no value declared.",
            "default": 0
          },
          "keyword": {
            "title": "Keyword in description",
            "type": "string",
            "description": "Case-insensitive match on the permit description, type or work class, e.g. \"re-roof\" or \"generator\"."
          },
          "onlyNew": {
            "title": "Delta mode: only permits not delivered before",
            "type": "boolean",
            "description": "Remembers what each run delivered (per city, in a key-value store on your account) and next time returns only new permits. Schedule the actor daily and you get a clean feed of fresh leads, paying only for the new ones. Keep the filters below stable while a feed runs: a permit skipped by a filter is not remembered, so widening the filters later will not bring back permits older than the feed's current position. To change filters, use a new store name or tick \"Reset delta state\".",
            "default": false
          },
          "stateStoreName": {
            "title": "Delta state store name",
            "type": "string",
            "description": "Name of the key-value store that keeps the delta watermark. Use different names to run independent feeds (one per client, one per trade).",
            "default": "us-permits-seen"
          },
          "resetState": {
            "title": "Reset delta state",
            "type": "boolean",
            "description": "Forget what was delivered before and start the feed again from \"last N days\".",
            "default": false
          },
          "geocodeMissing": {
            "title": "Fill in missing GPS and ZIP from the US Census geocoder",
            "type": "boolean",
            "description": "Some cities publish the address without coordinates (Orlando, New Orleans) or without a ZIP (Chicago). When on, those rows are sent to the free US Census batch geocoder and come back with latitude, longitude and ZIP where the address matches (about 55% on Orlando, measured). Adds a few seconds per thousand rows. Rows that do not match are delivered as the city publishes them.",
            "default": true
          },
          "enrichWithGoogleMaps": {
            "title": "Contractor phone, website and reviews from Google Maps ($)",
            "type": "boolean",
            "description": "Looks each contractor up on Google Maps (one search per contractor, not per permit) and adds googlePhone, googleWebsite, googleRating, googleReviewCount, googleCategory, googleAddress and googleMapsUrl. When the permit has no phone, contractorPhone is filled from Google Maps and contractorPhoneSource says so. Only a result whose name matches the contractor is used (googleNameMatch: exact or close). Charged per contractor found, as the enrich_contractor event; searches that find nothing cost nothing.",
            "default": false
          },
          "enrichMaxContractors": {
            "title": "Max contractors to look up on Google Maps",
            "minimum": 1,
            "maximum": 2000,
            "type": "integer",
            "description": "Cap on Google Maps searches per run, across all cities. Contractors without a phone in the permit go first.",
            "default": 200
          },
          "enrichEmailFromWebsite": {
            "title": "Contractor email from their website ($)",
            "type": "boolean",
            "description": "Reads the contractor's website found on Google Maps (home page and the usual contact pages) and delivers the email it finds, with the page it was found on (emailFoundOn). Needs the Google Maps enrichment on. Charged per email found, as the email_found event; a website with no email costs nothing.",
            "default": false
          },
          "enrichWithCensus": {
            "title": "Neighbourhood income and home value by ZIP (free)",
            "type": "boolean",
            "description": "Adds to every row the Census ACS 5-year figures for its ZIP code: median household income (zipMedianHouseholdIncome), median home value (zipMedianHomeValue), owner-occupied share (zipOwnerOccupiedShare) and population (zipPopulation). One request per run, no extra charge. Needs a free Census API key (censusApiKey below, or the Actor's CENSUS_API_KEY).",
            "default": false
          },
          "censusApiKey": {
            "title": "Census API key",
            "type": "string",
            "description": "Free key from api.census.gov/data/key_signup.html. Only needed with the Census enrichment on; leave empty to use the key configured on the Actor."
          },
          "maxResults": {
            "title": "Max results",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many permits across all cities. 0 = no limit. The prefilled 100 makes a first test run cost cents; clear it for a full pull.",
            "default": 0
          },
          "socrataAppToken": {
            "title": "Socrata app token (optional)",
            "type": "string",
            "description": "Free token from any Socrata portal. Without it the run shares the public rate limit; with it you get your own. Only needed for very large pulls."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}