{"openapi":"3.1.0","info":{"title":"Shovels API","description":"Pay-per-call access to the Shovels building-permits search API. Search US building permits by date, location, and rich permit/property/contractor filters. No accounts, no subscriptions — pay per request with x402 or MPP.","version":"1.0.0","x-guidance":"Permit search needs a geo_id. If you only have a place name, first resolve it: POST /api/cities/search, /api/counties/search, or /api/jurisdictions/search with { \"q\": string } to get a geo_id (a state code like \"CA\" or a ZIP also work directly). POST /api/permits/search with { \"permit_from\": \"YYYY-MM-DD\", \"permit_to\": \"YYYY-MM-DD\", \"geo_id\": string } plus any optional filters to search building permits. POST /api/tags lists valid permit_tags values. POST /api/contractors/search (same required fields) to find contractors; POST /api/contractors/permits with { \"contractor_id\": string } for one contractor's permits. POST /api/addresses/search with { \"q\": string } to find permitted addresses. POST /api/decisions/search with { \"decision_from\", \"decision_to\", \"geo_id\" } for zoning/land-use decisions (ZIP not supported there). All list endpoints are cursor-paginated: pass the returned next_cursor back as \"cursor\". Price tracks the requested \"size\" (one credit per record). GET /api/health is unprotected. See /openapi.json for full request/response schemas.","guidance":"Permit search needs a geo_id. If you only have a place name, first resolve it: POST /api/cities/search, /api/counties/search, or /api/jurisdictions/search with { \"q\": string } to get a geo_id (a state code like \"CA\" or a ZIP also work directly). POST /api/permits/search with { \"permit_from\": \"YYYY-MM-DD\", \"permit_to\": \"YYYY-MM-DD\", \"geo_id\": string } plus any optional filters to search building permits. POST /api/tags lists valid permit_tags values. POST /api/contractors/search (same required fields) to find contractors; POST /api/contractors/permits with { \"contractor_id\": string } for one contractor's permits. POST /api/addresses/search with { \"q\": string } to find permitted addresses. POST /api/decisions/search with { \"decision_from\", \"decision_to\", \"geo_id\" } for zoning/land-use decisions (ZIP not supported there). All list endpoints are cursor-paginated: pass the returned next_cursor back as \"cursor\". Price tracks the requested \"size\" (one credit per record). GET /api/health is unprotected. See /openapi.json for full request/response schemas."},"servers":[{"url":"https://stable-shovels.dev"}],"tags":[{"name":"Addresses"},{"name":"Cities"},{"name":"Contractors"},{"name":"Counties"},{"name":"Decisions"},{"name":"Health"},{"name":"Jurisdictions"},{"name":"Permits"},{"name":"States"},{"name":"Tags"},{"name":"Zipcodes"}],"paths":{"/api/health":{"get":{"operationId":"health","summary":"health","tags":["Health"],"security":[],"responses":{"200":{"description":"Successful response"}}}},"/api/permits/search":{"post":{"operationId":"permits_search","summary":"Shovels Permit Search — search US building permits by date range and location, with optional permit, property, and contractor filters. Cursor-paginated: pass the returned next_cursor back as `cursor` for the next page.","tags":["Permits"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"permit_from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Return permits that started on or after this date (YYYY-MM-DD)."},"permit_to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Return permits that started on or before this date (YYYY-MM-DD)."},"geo_id":{"type":"string","minLength":1,"description":"Geographic filter: a state code (e.g. \"CA\"), a ZIP code, or a Shovels geolocation id (resolve one via the city/county/jurisdiction search endpoints)."},"permit_q":{"description":"Substring search over permit text (max 50 chars).","type":"string","maxLength":50},"permit_tags":{"description":"Filter by permit classification tags (e.g. \"solar\", \"roofing\"). Prefix a tag with '-' to exclude it.","type":"array","items":{"type":"string"}},"permit_status":{"description":"Filter by permit status: one or more of final, in_review, inactive, active.","type":"array","items":{"type":"string"}},"permit_has_contractor":{"description":"Only return permits that have an associated contractor.","type":"boolean"},"permit_min_job_value":{"description":"Only return permits with at least this job value (USD).","type":"number","minimum":0},"property_type":{"description":"Filter by property type (e.g. \"residential\", \"commercial\").","type":"array","items":{"type":"string"}},"contractor_name":{"description":"Filter by contractor name (min 3 chars).","type":"string","minLength":3},"contractor_license":{"description":"Filter by contractor license number.","type":"string"},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100},"include_count":{"description":"Include a `total_count` of matching permits (first page only).","type":"boolean"}},"required":["permit_from","permit_to","geo_id"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/contractors/search":{"post":{"operationId":"contractors_search","summary":"Shovels Contractor Search — find contractors active in a location and date range, filtered by permit, property, and contractor characteristics. Cursor-paginated.","tags":["Contractors"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"permit_from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Include contractors active on permits starting on or after this date (YYYY-MM-DD)."},"permit_to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Include contractors active on permits starting on or before this date (YYYY-MM-DD)."},"geo_id":{"type":"string","minLength":1,"description":"Geographic filter: a state code (e.g. \"CA\"), a ZIP code, or a Shovels geolocation id."},"permit_q":{"description":"Substring search over permit text (max 50 chars).","type":"string","maxLength":50},"permit_tags":{"description":"Permit tags to include/exclude (prefix with '-' to exclude).","type":"array","items":{"type":"string"}},"permit_status":{"description":"One or more of: final, in_review, inactive, active.","type":"array","items":{"type":"string"}},"permit_min_job_value":{"description":"Minimum job value on a permit (USD).","type":"number","minimum":0},"property_type":{"description":"Property type (e.g. residential, commercial, industrial).","type":"string"},"contractor_classification_derived":{"description":"Derived contractor classifications (must match ALL).","type":"array","items":{"type":"string"}},"contractor_name":{"description":"Contractor name, partial match (min 3 chars).","type":"string","minLength":3},"contractor_website":{"description":"Contractor website.","type":"string"},"contractor_license":{"description":"Contractor license number.","type":"string"},"contractor_min_total_job_value":{"description":"Minimum lifetime job value across all permits (USD).","type":"number","minimum":0},"contractor_min_total_permits_count":{"description":"Minimum lifetime permit count.","type":"integer","minimum":0,"maximum":9007199254740991},"contractor_min_inspection_pr":{"description":"Minimum lifetime inspection pass rate.","type":"number"},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100},"include_count":{"description":"Include a `total_count` of matching contractors (first page).","type":"boolean"},"include_tallies":{"description":"Include tag/status tallies per contractor (default true).","type":"boolean"}},"required":["permit_from","permit_to","geo_id"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/contractors/permits":{"post":{"operationId":"contractors_permits","summary":"Shovels Contractor Permits — list all permits linked to a single contractor id. Cursor-paginated.","tags":["Contractors"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contractor_id":{"type":"string","minLength":1,"description":"The Shovels contractor id to list permits for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100},"include_count":{"description":"Include a `total_count` of the contractor’s permits.","type":"boolean"}},"required":["contractor_id"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/decisions/search":{"post":{"operationId":"decisions_search","summary":"Shovels Decision Search — search zoning and land-use decisions by date range and location (state code or geo id; ZIP not supported). Cursor-paginated.","tags":["Decisions"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision_from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Return decisions on or after this date (YYYY-MM-DD)."},"decision_to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Return decisions on or before this date (YYYY-MM-DD)."},"geo_id":{"type":"string","minLength":1,"description":"A state code or Shovels geolocation id. Note: ZIP codes are NOT supported for decisions."},"decision_q":{"description":"Full-text search on decision title/description (max 100 chars).","type":"string","maxLength":100},"asset_class":{"description":"Asset class filters (e.g. \"Residential\", \"Commercial\").","type":"array","items":{"type":"string"}},"category":{"description":"Decision category filters.","type":"array","items":{"type":"string"}},"subcategory":{"description":"Decision subcategory filters.","type":"array","items":{"type":"string"}},"property_type":{"description":"Property type filters.","type":"array","items":{"type":"string"}},"min_project_value":{"description":"Minimum project value, in cents.","type":"integer","minimum":0,"maximum":9007199254740991},"max_project_value":{"description":"Maximum project value, in cents.","type":"integer","minimum":0,"maximum":9007199254740991},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100},"include_count":{"description":"Include a `total_count` of matching decisions (first page).","type":"boolean"}},"required":["decision_from","decision_to","geo_id"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/addresses/search":{"post":{"operationId":"addresses_search","summary":"Shovels Address Search — find US addresses that have at least one associated permit, with their `geo_id`.","tags":["Addresses"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"description":"The term to search for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}},"required":["q"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/cities/search":{"post":{"operationId":"cities_search","summary":"Shovels City Search — find cities by name and resolve them to a `geo_id` for use in permit/contractor/decision search.","tags":["Cities"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"description":"The term to search for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}},"required":["q"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/counties/search":{"post":{"operationId":"counties_search","summary":"Shovels County Search — find counties by name and resolve them to a `geo_id` for use in permit/contractor/decision search.","tags":["Counties"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"description":"The term to search for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}},"required":["q"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/jurisdictions/search":{"post":{"operationId":"jurisdictions_search","summary":"Shovels Jurisdiction Search — find permitting jurisdictions by name and resolve them to a `geo_id` for use in permit/contractor/decision search.","tags":["Jurisdictions"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"description":"The term to search for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}},"required":["q"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/states/search":{"post":{"operationId":"states_search","summary":"Shovels State Search — find US states by name and resolve them to a `geo_id`.","tags":["States"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"description":"The term to search for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}},"required":["q"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/zipcodes/search":{"post":{"operationId":"zipcodes_search","summary":"Shovels Zipcode Search — find ZIP codes that have Shovels data and resolve them to a `geo_id`.","tags":["Zipcodes"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"description":"The term to search for."},"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}},"required":["q"]}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}},"/api/tags":{"post":{"operationId":"tags","summary":"Shovels Tags — list all available permit classification tags (and their descriptions) for use as `permit_tags` filters.","tags":["Tags"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"0.50"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cursor":{"description":"Pagination cursor — pass the `next_cursor` from a prior page.","type":"string"},"size":{"description":"Records to return per page (1–100, default 50). Determines the price — each record returned costs one credit.","type":"integer","minimum":1,"maximum":100}}}}}},"responses":{"200":{"description":"Successful response"},"402":{"description":"Payment Required"}}}}}}