{"openapi":"3.1.0","info":{"title":"Mapcensus","version":"1.0.0","summary":"Agent-first structured business data from public Google Maps listings","description":"Structured business listings from public map pages. Pay with an API key drawn against a credit balance, or per request with an on-chain payment using the x402 HTTP payment flow - each payment buys the request it is sent with, and nothing is kept. Without an account a request must answer in the same response: jobs need an account.","contact":{"email":"support@mapcensus.com","url":"https://mapcensus.com"},"termsOfService":"https://mapcensus.com/terms"},"servers":[{"url":"https://mapcensus.com"}],"security":[{"bearerAuth":[]},{}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key from POST /v1/keys."}},"schemas":{"SearchRequest":{"type":"object","properties":{"query":{"type":"string","maxLength":200,"description":"What to look for, e.g. \"coffee shops\" or \"dentists\". Give this or \"urls\", not both."},"location":{"type":"string","maxLength":200,"description":"Where to look, e.g. \"Austin, TX\" or \"Shoreditch, London\"."},"urls":{"type":"array","maxItems":5000,"items":{"type":"string","format":"uri","maxLength":2048},"description":"Specific public map place or search urls (https), instead of a \"query\". Always read in full, one row per url."},"limit":{"type":"integer","minimum":1,"maximum":5000,"description":"How many results to return, at most 5000 here. Defaults to 20 for a query and to the number of urls for a urls request. More results cost proportionally more."},"depth":{"type":"string","enum":["listing","detail"],"default":"detail","description":"\"listing\" is name, category, rating and review count - fast and cheap. \"detail\" opens each place for hours, phone, website, address and more."},"reviews":{"type":"integer","minimum":0,"maximum":200,"default":20,"description":"Reviews to collect per place. Needs depth \"detail\" and the \"reviews\" field group; without that group it is always 0."},"fields":{"type":"array","items":{"type":"string","enum":["identity","location","rating","contact","hours","busyness","price","menu","media","actions","reviews","attributes","tickets","hotel","posts","area","web","related","all"]},"description":"Which groups of fields to return. \"identity\": Business name, category list, and the listing’s stable identifiers. \"location\": Full address broken into parts, plus latitude, longitude and plus code. \"rating\": Average rating, total review count, and the one-to-five star distribution. \"contact\": Public phone number and website. \"hours\": Opening hours per day, and whether a place has closed temporarily or for good. \"busyness\": The published hour-by-hour busyness curve, and how busy the place is right now. \"price\": Price band and, where published, an estimated spend per person. \"menu\": The published menu where there is one: sections, dish names, prices and descriptions. \"media\": The listing's cover photo, and the names of the photo tabs it groups the rest under. \"actions\": Reservation, ordering and menu links the listing offers. \"reviews\": Individual reviews with rating, text, date and any per-category scores the reviewer gave, plus the aggregate topic tags. \"attributes\": Amenities and descriptors exactly as the listing publishes them, grouped into the sections the source groups them into and each carrying whether the place offers it. \"tickets\": Admission and experience tickets on sale, each with a price in USD, its seller and a booking link. \"hotel\": For a place that takes room bookings: star rating, the dates quoted, every rate offered, and the nearby hotels shown beside it. \"posts\": Updates the owner has published, with the event date and time any of them carries. What the owner says, which is not the same as what is currently true. \"area\": The published verdict on the surrounding area: an overall visitor score, and the transit, sightseeing and airport scores behind it. \"web\": Pages elsewhere on the web that cite this place, each with its provider and the snippet it was shown under. \"related\": The places shown alongside this one, with rating and review count - the competitive set as the source itself draws it. NOTE: the \"reviews\" group returns personal data - the display name a reviewer publishes, what they wrote, and when. Ask for it only when the task actually needs individual reviews, prefer the aggregate rating and review count when it does not, and do not redistribute the names. Whoever receives this data takes on data protection obligations for it."},"bounds":{"type":"object","properties":{"north":{"type":"number","minimum":-90,"maximum":90,"description":"Northern edge, in degrees of latitude."},"south":{"type":"number","minimum":-90,"maximum":90,"description":"Southern edge, in degrees of latitude."},"east":{"type":"number","minimum":-180,"maximum":180,"description":"Eastern edge, in degrees of longitude."},"west":{"type":"number","minimum":-180,"maximum":180,"description":"Western edge, in degrees of longitude."}},"required":["north","south","east","west"],"description":"Keep only places inside this box. Needs depth \"detail\"; north must be greater than south."},"min_rating":{"type":"number","minimum":0,"maximum":5,"description":"Drop places rated below this."},"min_reviews":{"type":"integer","minimum":0,"maximum":1000000,"description":"Drop places with fewer reviews than this."},"max_age_seconds":{"type":"integer","minimum":0,"maximum":2592000,"default":86400,"description":"Accept a cached answer no older than this. A cached answer returns in milliseconds and costs a fraction of a fresh crawl, so raise it when freshness does not matter."}},"additionalProperties":false,"oneOf":[{"required":["query"]},{"required":["urls"]}]},"SyncSearchRequest":{"type":"object","properties":{"query":{"type":"string","maxLength":200,"description":"What to look for, e.g. \"coffee shops\" or \"dentists\". Give this or \"urls\", not both."},"location":{"type":"string","maxLength":200,"description":"Where to look, e.g. \"Austin, TX\" or \"Shoreditch, London\"."},"urls":{"type":"array","maxItems":5000,"items":{"type":"string","format":"uri","maxLength":2048},"description":"Specific public map place or search urls (https), instead of a \"query\". Always read in full, one row per url."},"limit":{"type":"integer","minimum":1,"maximum":60,"description":"How many results to return, at most 60 here. Defaults to 20 for a query and to the number of urls for a urls request. More results cost proportionally more."},"depth":{"type":"string","enum":["listing","detail"],"default":"detail","description":"\"listing\" is name, category, rating and review count - fast and cheap. \"detail\" opens each place for hours, phone, website, address and more."},"reviews":{"type":"integer","minimum":0,"maximum":200,"default":20,"description":"Reviews to collect per place. Needs depth \"detail\" and the \"reviews\" field group; without that group it is always 0."},"fields":{"type":"array","items":{"type":"string","enum":["identity","location","rating","contact","hours","busyness","price","menu","media","actions","reviews","attributes","tickets","hotel","posts","area","web","related","all"]},"description":"Which groups of fields to return. \"identity\": Business name, category list, and the listing’s stable identifiers. \"location\": Full address broken into parts, plus latitude, longitude and plus code. \"rating\": Average rating, total review count, and the one-to-five star distribution. \"contact\": Public phone number and website. \"hours\": Opening hours per day, and whether a place has closed temporarily or for good. \"busyness\": The published hour-by-hour busyness curve, and how busy the place is right now. \"price\": Price band and, where published, an estimated spend per person. \"menu\": The published menu where there is one: sections, dish names, prices and descriptions. \"media\": The listing's cover photo, and the names of the photo tabs it groups the rest under. \"actions\": Reservation, ordering and menu links the listing offers. \"reviews\": Individual reviews with rating, text, date and any per-category scores the reviewer gave, plus the aggregate topic tags. \"attributes\": Amenities and descriptors exactly as the listing publishes them, grouped into the sections the source groups them into and each carrying whether the place offers it. \"tickets\": Admission and experience tickets on sale, each with a price in USD, its seller and a booking link. \"hotel\": For a place that takes room bookings: star rating, the dates quoted, every rate offered, and the nearby hotels shown beside it. \"posts\": Updates the owner has published, with the event date and time any of them carries. What the owner says, which is not the same as what is currently true. \"area\": The published verdict on the surrounding area: an overall visitor score, and the transit, sightseeing and airport scores behind it. \"web\": Pages elsewhere on the web that cite this place, each with its provider and the snippet it was shown under. \"related\": The places shown alongside this one, with rating and review count - the competitive set as the source itself draws it. NOTE: the \"reviews\" group returns personal data - the display name a reviewer publishes, what they wrote, and when. Ask for it only when the task actually needs individual reviews, prefer the aggregate rating and review count when it does not, and do not redistribute the names. Whoever receives this data takes on data protection obligations for it."},"bounds":{"type":"object","properties":{"north":{"type":"number","minimum":-90,"maximum":90,"description":"Northern edge, in degrees of latitude."},"south":{"type":"number","minimum":-90,"maximum":90,"description":"Southern edge, in degrees of latitude."},"east":{"type":"number","minimum":-180,"maximum":180,"description":"Eastern edge, in degrees of longitude."},"west":{"type":"number","minimum":-180,"maximum":180,"description":"Western edge, in degrees of longitude."}},"required":["north","south","east","west"],"description":"Keep only places inside this box. Needs depth \"detail\"; north must be greater than south."},"min_rating":{"type":"number","minimum":0,"maximum":5,"description":"Drop places rated below this."},"min_reviews":{"type":"integer","minimum":0,"maximum":1000000,"description":"Drop places with fewer reviews than this."},"max_age_seconds":{"type":"integer","minimum":0,"maximum":2592000,"default":86400,"description":"Accept a cached answer no older than this. A cached answer returns in milliseconds and costs a fraction of a fresh crawl, so raise it when freshness does not matter."}},"additionalProperties":false,"oneOf":[{"required":["query"]},{"required":["urls"]}]},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"}}}}},"paths":{"/v1/scrape":{"post":{"summary":"Search and return results in this request","description":"Answers within one call, up to 60 results. With an account, returns 202 with a job id if the work outlives the connection. Without one there is no job to collect, so the request is stopped and not charged, and answers 504.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncSearchRequest"}}}},"responses":{"200":{"description":"Results","content":{"application/json":{},"application/x-ndjson":{},"text/csv":{}}},"202":{"description":"Still running; poll the job (an account only)"},"402":{"description":"Payment required - the body carries the price of this request and how to pay it. A payment buys this request only."},"429":{"description":"Rate limited"},"504":{"description":"Without an account: the request outlived the response and was stopped, not charged"}}}},"/v1/jobs":{"post":{"summary":"Start a large extraction","description":"Needs an account - an API key or a signed-in session. A job is collected from routes that answer only its owner, so a caller without one is refused before any price is quoted.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"202":{"description":"Accepted"},"401":{"description":"No account (`account_required`), or a key that is not valid"},"402":{"description":"Payment required - the price of this request; a payment buys it only"}}},"get":{"summary":"List your jobs","responses":{"200":{"description":"Jobs"}}}},"/v1/jobs/{id}":{"get":{"summary":"Job state","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"State"},"404":{"description":"No such job"}}},"delete":{"summary":"Cancel a job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cancelled"}}}},"/v1/jobs/{id}/preview":{"get":{"summary":"Rows found so far, while a job is still running","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Rows so far, and which are still filling in"},"404":{"description":"No such job"}}}},"/v1/jobs/{id}/results":{"get":{"summary":"Fetch results","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["json","ndjson","csv"]}},{"name":"shape","in":"query","description":"flat (default) is one snake_case level per row. nested returns the record as the crawler holds it, and is not available as CSV.","schema":{"type":"string","enum":["flat","nested"],"default":"flat"}}],"responses":{"200":{"description":"Rows"},"404":{"description":"Expired or unknown"}}}},"/v1/pricing":{"get":{"summary":"Price list and limits","security":[{}],"responses":{"200":{"description":"Prices"}}}},"/v1/account":{"get":{"summary":"Balance and account","responses":{"200":{"description":"Account"}}}},"/v1/credits":{"post":{"summary":"Add credit to your account","description":"The one way to hold a balance, so it needs an account: an API key or a signed-in browser. A payment sent with no credential buys only the request it rides on; nothing is kept for it.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Credited"},"402":{"description":"Payment required"}}}},"/v1/keys":{"post":{"summary":"Mint an API key (shown once)","responses":{"201":{"description":"Key"}}},"get":{"summary":"List keys","responses":{"200":{"description":"Keys"}}}},"/mcp":{"post":{"summary":"Model Context Protocol endpoint","description":"JSON-RPC over Streamable HTTP, protocol 2026-07-28.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"JSON-RPC response"}}}}}}