---
title: "Search canonical places with evidence and monitoring context"
method: GET
path: "/api/places"
---

# Search canonical places with evidence and monitoring context

`GET /api/places`

## Request

- Base URL: `https://chinafootnotes.com`
- URL: `https://chinafootnotes.com/api/places`
- Auth: none declared

## Query parameters

- `q` string
- `category` string
- `district` string
- `type` string
- `tag` string
- `city` string

## Response `200`

Search canonical places with evidence and monitoring context

- PlaceList
  - `schemaVersion` string
  - `version` string
  - `generatedAt` string, date-time
  - `notice` string
  - `total` integer, required
  - `places` Place[], required
    - `id` string, required
    - `name` string, required
    - `localName` string, required
    - `district` string, nullable: District name; null where not collected yet.
    - `summary` string, required
    - `number` integer: 1–50 are Shanghai; other cities are numbered from 51.
    - `category` 'Landmarks' | 'Museums' | 'Neighborhoods' | 'Gardens' | 'Temples' | 'Water towns', required
    - `aliases` string[]
    - `highlights` string[], required
    - `visitDuration` string, nullable: Editorial planning suggestion, not a venue rule.
    - `researchedAt` string, date, required
    - `sources` Source[], required
      - `id` string, required
      - `url` string, uri, nullable, required: null only for our own checks, which have no web page: kind owner_tested (we tried it ourselves; first-hand, not official) or owner_official (the venue's own answer: method phone, onsite_sign or onsite_notice; official). accessedAt is the day we checked.
      - `title` string, required
      - `publisher` string, required
      - `kind` 'official' | 'government', required
      - `method` 'phone' | 'onsite_sign' | 'onsite_notice' | 'null', nullable: Only for kind owner_official: how we got the venue’s answer (by phone, a standing sign on site, or a temporary notice on site).
      - `contact` string, nullable: Only for method phone: who we called (venue and number).
      - `accessedAt` string, date, required
      - `publishedAt` string, date, nullable
    - `tips` Tip[], required
      - `text` string, required
      - `topic` string
      - `kind` 'traveler_report', required
      - `sourceUrl` string, uri, required
      - `sourceTitle` string
      - `author` string
      - `observedDate` string, date, nullable
      - `observedDateRaw` string, nullable: Original visible date label. It can lack a year or include locale text; never manufacture a year.
      - `visitDate` string, date, nullable
      - `accessedAt` string, date, required
      - `caveat` string
      - `commercial` boolean
    - `photos` Photo[], required
      - `url` string, required
      - `sourceUrl` string, required
      - `author` string, required
      - `license` string, required
      - `licenseUrl` string
      - `caption` string
      - `alt` string
      - `accessedAt` string, date
    - `updates` Update[], required
      - `id` string, required
      - `text` string, required
      - `publishedAt` string, date, nullable, required
      - `reviewedAt` string, date, required
      - `startsAt` string, date, required
      - `expiresAt` string, date, required
      - `sourceIds` string[], required
      - `placeId` string
      - `sources` Source[]
        - `id` string, required
        - `url` string, uri, nullable, required: null only for our own checks, which have no web page: kind owner_tested (we tried it ourselves; first-hand, not official) or owner_official (the venue's own answer: method phone, onsite_sign or onsite_notice; official). accessedAt is the day we checked.
        - `title` string, required
        - `publisher` string, required
        - `kind` 'official' | 'government', required
        - `method` 'phone' | 'onsite_sign' | 'onsite_notice' | 'null', nullable: Only for kind owner_official: how we got the venue’s answer (by phone, a standing sign on site, or a temporary notice on site).
        - `contact` string, nullable: Only for method phone: who we called (venue and number).
        - `accessedAt` string, date, required
        - `publishedAt` string, date, nullable
    - `dataQuality` object
      - `knownFields` integer
      - `totalFields` integer
      - `method` string
      - `reviewDue` string, date
    - `sourceMonitoring` SourceMonitoring[]
      - `sourceId` string, required
      - `status` 'not_checked' | 'baseline' | 'unchanged' | 'changed' | 'failed' | 'alive', required
      - `lastSuccessAt` string, date-time, nullable
      - `lastAttemptAt` string, date-time, nullable
      - `pendingReviewIds` string[], required
    - `hasPendingSourceReview` boolean
    - `isReviewOverdue` boolean
    - `address` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `transport` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `hours` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `admission` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `booking` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `foreignVisitors` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `accessibility` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `lastAdmission` Field
      - `value` string, nullable, required: May contain explanation even when status is unknown or conflicting. Never infer confirmation from nonempty value.
      - `status` 'source_checked' | 'unknown' | 'conflicting' | 'not_applicable', required: source_checked = a published source was read, or we phoned the venue, read its sign on site or tried it ourselves (see the source kind); not confirmed for today. not_applicable means no single policy covers this scoped place; it does not mean free or no booking.
      - `sourceIds` string[], required
    - `city` string: City id, e.g. shanghai
    - `area` string, nullable: Area id within the city (see City.areas)
    - `group` 'town' | 'trips' | 'null', nullable: For cities split into In town and Day trips (see City.groups)
    - `distanceKm` number, nullable: Day trips only: rough distance from the centre; null when not checked
    - `shortName` string: Short label for maps and lists
    - `events` Event[]
      - `id` string, required
      - `kind` 'festival' | 'exhibition' | 'show' | 'performance' | 'seasonal' | 'other', required
      - `title` string, required
      - `startsAt` string, date
      - `endsAt` string, date, required: Exact end date unless endsAtLabel is present; then this is only the upper bound used for filtering, not a confirmed last day.
      - `when` string
      - `where` string
      - `ticket` 'free' | 'included' | 'paid' | 'unknown'
      - `price` string
      - `booking` string
      - `text` string, required
      - `sourceIds` string[], required
      - `placeId` string
      - `sources` Source[]
        - `id` string, required
        - `url` string, uri, nullable, required: null only for our own checks, which have no web page: kind owner_tested (we tried it ourselves; first-hand, not official) or owner_official (the venue's own answer: method phone, onsite_sign or onsite_notice; official). accessedAt is the day we checked.
        - `title` string, required
        - `publisher` string, required
        - `kind` 'official' | 'government', required
        - `method` 'phone' | 'onsite_sign' | 'onsite_notice' | 'null', nullable: Only for kind owner_official: how we got the venue’s answer (by phone, a standing sign on site, or a temporary notice on site).
        - `contact` string, nullable: Only for method phone: who we called (venue and number).
        - `accessedAt` string, date, required
        - `publishedAt` string, date, nullable
      - `dates` string[]: Specific dates when the event runs, inside startsAt..endsAt
      - `basisNotes` object[]
      - `endsAtLabel` string: Source-stated end period when the exact day is unknown. Use this label instead of presenting endsAt as an exact date.

## Other responses

- `400`: Invalid URL encoding
- `404`: City not found (not published)
- `500`: Local data/service unavailable

---

[API](https://skmtc.dev/chinafootnotes/apis/china-footnotes.md) · [All operations](https://skmtc.dev/chinafootnotes/apis/china-footnotes/llms.txt) · [OpenAPI document](https://skmtc.dev/chinafootnotes/apis/china-footnotes/revisions/b0050778a942?raw)
