# Place schema (/docs/schema/place) The unified SocialCrawl place or business schema. Every field, its type, per-platform availability, and a machine-readable JSON Schema, generated from the canonical Zod source. Every SocialCrawl endpoint that returns a place or business gives you this exact shape, whatever the source platform. Write your parser once and the same code reads place data from every platform below. That is the unified schema: one contract instead of a dozen raw upstream formats. ## Field reference | Field | Type | Nullable | Description | | ----- | ---- | -------- | ----------- | | `id` | `string` | No | Place ID (Google cid for a business, hotel_identifier for a hotel) | | `name` | `string` | Yes | Business / hotel name | | `url` | `string` | Yes | Website or canonical URL | | `category` | `string` | Yes | Primary category (e.g. "Coffee shop", "Hotel") | | `rating.value` | `number` | Yes | | | `rating.max` | `number` | Yes | | | `reviews_count` | `number` | Yes | Number of ratings | | `price_level` | `string` | Yes | Price band ("inexpensive" / "$$" / null) | | `address` | `string` | Yes | | | `phone` | `string` | Yes | | | `latitude` | `number` | Yes | | | `longitude` | `number` | Yes | | | `verified` | `boolean` | Yes | Claimed-business flag (Google is_claimed) | | `description` | `string` | Yes | | | `image_urls` | `string` or `string[]` | Yes | Union: string \| array \| null | | `categories` | `string[]` | Yes | | | `hotel.stars` | `number` | Yes | | | `hotel.stars_description` | `string` | Yes | | | `hotel.check_in_time` | `string` | Yes | | | `hotel.check_out_time` | `string` | Yes | | | `hotel.amenities` | `object[]` | Yes | | | `hotel.review_topics` | `object[]` | Yes | | | `hotel.prices` | `object[]` | Yes | | ## Extension fields (`ext`) Platform-specific passthrough. Each field is present only on the platforms that expose it and is absent everywhere else, so treat every `ext.*` field as optional. These carry the richer, per-platform signals the unified leaves cannot hold, and the join keys that chain endpoints together. | Field | Type | Nullable | Description | | ----- | ---- | -------- | ----------- | | `ext.distance` | `number` | Yes | | | `ext.status` | `string` | Yes | | | `ext.timezone` | `string` | Yes | | | `ext.hours` | `object[]` | Yes | | | `ext.place_id` | `string` | Yes | | | `ext.attributes` | `object` | Yes | | | `ext.rating_distribution` | `object` | Yes | | | `ext.people_also_search` | `object[]` | Yes | | | `ext.menu_url` | `string` | Yes | | | `ext.domain` | `string` | Yes | | | `ext.maps_url` | `string` | Yes | | | `ext.rank` | `number` | Yes | | | `ext.city` | `string` | Yes | | | `ext.postal_code` | `string` | Yes | | | `ext.region` | `string` | Yes | | | `ext.country_code` | `string` | Yes | | | `ext.posts_count` | `number` | Yes | `/v1/instagram/location` only: the number of public posts Instagram counts at the place. | | `ext.website` | `string` | Yes | `/v1/instagram/location` only: the venue's own website (`place.url` is its Instagram page). | | `ext.facebook_places_id` | `string` | Yes | `/v1/instagram/location` only: the Facebook Places id of the same place. | | `ext.business_username` | `string` | Yes | `/v1/instagram/location` only: the username of the Instagram business account linked to the place, or null when none is linked. | | `ext.is_ad` | `boolean` | Yes | | | `ext.ad_rank` | `number` | Yes | | | `ext.ad_description` | `string` | Yes | | | `ext.status_description` | `string` | Yes | | | `ext.visitor_reviews_count` | `number` | Yes | | | `ext.blog_reviews_count` | `number` | Yes | | | `ext.booking_url` | `string` | Yes | | | `ext.keywords` | `string[]` | Yes | | ## Platform availability 11 platforms return the `Place` shape. `id` are never null on any platform. The fields below vary: **yes** means the platform populates it (the value may still be null); a blank means the platform never provides it, so it is always null.
| Platform | `address` | `category` | `url` | `price_level` | `rating.value` | `reviews_count` | `categories` | `description` | `image_urls` | `phone` | `rating.max` | `verified` | | -------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Google | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | Gumtree | | | | | | | | | | | | | | H&M | | | | | | | | | | yes | | | | Home Depot | | yes | yes | | | | | | | yes | | | | Instagram | yes | yes | yes | yes | | | | | | yes | | | | Kohl's | | | yes | | | | | | | | | | | Naver | yes | yes | yes | | yes | yes | yes | yes | yes | yes | yes | | | Sephora | | | | | | | | | | yes | | | | Target | | | | | | | | | | yes | | | | Tripadvisor | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | Yelp | yes | | | yes | yes | yes | | | | | | |
## Machine-readable schema Validate responses programmatically against the JSON Schema (2020-12): [`/schemas/place.json`](/schemas/place.json) Point a validator (Ajv, `jsonschema`, or your framework's) at that URL, or hand it to an agent so it can check the shape without a live call. ## Returned by Endpoints with the `Place` / `PlaceList` archetype return this shape: [Google](/platforms/google) · [Gumtree](/platforms/gumtree) · [H&M](/platforms/hm) · [Home Depot](/platforms/home_depot) · [Instagram](/platforms/instagram) · [Kohl's](/platforms/kohls) · [Naver](/platforms/naver) · [Sephora](/platforms/sephora) · [Target](/platforms/target) · [Tripadvisor](/platforms/tripadvisor) · [Yelp](/platforms/yelp) See how the same fields map to each platform's raw upstream names in the [cross-platform field equivalence table](/docs/schema/field-equivalence.md).