CityScroll
NYC’s public record, linked

API and feeds

← Back to CityScroll

Every view on CityScroll has a machine-readable twin. No key and no account are required. Endpoints are rate-limited and cached, and none touches a paid service. Base URL: https://api.cityscroll.org.

Research read IDs and scope

These reads show the public records CityScroll holds. No search hits does not mean no record exists. A record may lack a detail page or source document. Check each state on its own.

  • Contract analysis: first ask for the list of accepted agency labels. Use one of those labels, with the same case. If a label is not known, the response suggests a match. It does not prove zero awards. Retry with the suggested label. For Parks, use Department of Parks and Recreation. The fiscal year uses the date a contract was registered. FY2026 runs from July 1, 2025 to June 30, 2026. It is not the year of an award or payment. The year used to split source files may also differ.
  • Agency leaders: a published agency graph says which leader details are held. Keep the ID as given, including its encoded text. The record says if a separate dossier exists. It can link to the agency dossier's leadership record. That link is given only when the same person is named there. The node gives the source date and confidence. It also states the source's limits. A dated roster does not prove who holds the role today.
  • Meetings: the meeting record keeps the source ID and the board it refers to. Check four things on their own: whether the source meeting is held, when it was observed, whether minutes were published, and whether a City Record notice is linked. A meeting can be present while its minutes are not published. It may have no linked notice. If there is too little evidence to tell, the link state stays unknown. Neither state removes the source meeting.
  • Passage search: each result states the search scope, even with no hits. It gives the date the corpus was observed. Counts show how many records and passages it holds. Each source type has its own date and scope. Date bounds show the first and last source dates held. They do not mean all dates in that span are covered. Semantic search gives the same scope. A source's date is not the date the corpus was observed. A search covers only this retained set. No hit does not prove that CityScroll or a source has no such record.

Existing reads still work. Read the scope and dates sent with each result. For exact field names and values, see the schema catalog below.

Capability API contracts

This list uses the runtime registry. The JSON catalog has schemas, limits, examples, source, freshness, and delivery details.

See the JSON catalog for contracts. HTTP, feeds, bulk exports, and model tools use separate paths.

Feeds — any search as RSS / JSON / calendar

GET /feed.xml (Atom) · GET /feed.json (JSON Feed 1.1) · GET /feed.ics (subscribable calendar — one event per dated notice). Edge-cached 15 minutes.

ParamMeaning
lensmoney · land · property · rules · meetings · entity
qkeywords (up to 4)
agencyagency name as printed in the record
minminimum award $ (money lens → award feed)
kind + nameentity lens: kind=vendor|agency, name=… — vendor names are matched by normalized stem, so suffix/case variants are included
https://api.cityscroll.org/feed.xml?lens=rules&agency=Buildings
https://api.cityscroll.org/feed.ics?lens=meetings&q=community%20board
https://api.cityscroll.org/feed.json?lens=entity&kind=vendor&name=Sinergia%20Inc

Property locations

GET /property-locations returns the latest Property Disposition notices with extracted site addresses, boroughs, tax lots, BBLs, and resolved map geometry where available. The daily view is cached at the edge for 30 minutes. City Record Online remains the source of truth.

JSON

Agency-name crosswalk

GET /agencies lists each agency name as written in City Record Open Data and connects it to one name used by this site. Add ?format=csv for CSV. The endpoint needs no key, allows cross-site requests, and is cached for one day.

JSON · CSV

ParamMeaning
raw_stringexact text in agency_name. One row for each distinct source string
canonical_idstable text id assigned by the crosswalk
canonical_namename this site uses for the group
variantsevery source spelling connected to the same id

Matches use case, punctuation, known short forms, and administrative families. New spellings may start with their own id until the crosswalk is updated. The crosswalk helps connect records. It is not an official agency registry.

Batch cross-reference

POST /batch with {"names": ["…", …]} (≤10 names/request, 30 requests/day/IP). For each name, awards means award/intent notices naming that vendor (name-stem matched, all years). Mentions means full-text hits in the last two years of editions. Entity means the vendor-profile permalink when awards exist.

Permalinks

Everything on the site has a stable address you can link or cite:

/#notice/<request_id>one notice — at-a-glance summary, flags, Checkbook dollars, full text
/vendors/<stem>/vendor profile (name variants resolved by stem)
/agencies/<id>/agency profile
/#matter/<pin>a procurement matter as a timeline, Checkbook payments included
/#money?agency=…&q=…&m=…any filtered view — the URL is the state

Shared investigations

POST /inv stores a pin-list snapshot (structured fields only, ≤32KB, 90-day TTL, 10/day/IP) and returns an id. GET /inv/<id> reads it back. The site renders these at /#investigation/shared/<id>.

Public stats

GET /stats — served-product coverage as aggregate counts (record sets by section, each with its record type, counting rule and its own evidence date). It's cached about 15 minutes. Human-readable version: stats. Related: digest emails link notices via GET /r/<kind>/<request_id>, which checks the id against known notices, redirects to the matching permalink, and records a per-day count.

MCP — for AI assistants

POST /mcp (Streamable HTTP, JSON-RPC) — point an MCP client at https://api.cityscroll.org/mcp. The generated catalog below is the authoritative tool inventory. It distinguishes each tool's name, read, and mutation class. Created watches start immediately and send a welcome email stating their scope. Watch management stays behind the emailed manage and unsubscribe links — knowing an address never reveals or controls its subscriptions. Per-IP and daily model-call ceilings apply. Machine-readable catalog: JSON.

Available tools (generated from the runtime declarations):

  • search_federated read — Search the registered public CityScroll lenses in one bounded result set. Optional scope selects only allowlisted registered lenses. Preserves per-lens coverage, source observations, exact object routes, and federated ranking. It does not expose a raw store or arbitrary query language.
  • search_notices read — Search NYC City Record notices (the daily-refreshed mirror). Keyword terms are OR-matched. Add structured filters to narrow. Amounts are validity-filtered (data-entry errors excluded). Rolling placeholder deadlines are labeled, never shown as dates.
  • get_notice read — Get one public City Record notice by its exact RequestID. The result preserves materialized-source freshness and distinguishes a missing public notice from a read that cannot be served.
  • get_entity_dossier read — Get the bounded public dossier for one exact canonical CityScroll entity. Preserves attributed disagreements, availability, provenance, and public redaction.
  • get_entity_relationships read — Explore the public links for one exact CityScroll entity. Agency leaders link to the same person's published leadership record when held. The result states if a separate dossier exists, gives the source date and confidence, and explains the source's limits.
  • retrieve_cited_passages read — Find source passages with stable citations and exact source links. Results include the corpus date, source types, counts, and date bounds, even with no hits. The search returns source text and its scope. It does not write an answer or infer civic links.
  • get_contract read — Get one public contract by its exact ID. Uses the same Contracts record as CityScroll. Includes source links, coverage, freshness, amount validity, and lifecycle facts when available.
  • browse_contracts read — List contracts in bounded pages. Each row keeps its exact identity, even when records share a PIN. Follow an analysis group to page through every registration, including those with no individual detail record.
  • analyze_contracts read — Rank agencies, vendors, fiscal years, or amount bands by registered contract value or count. Each group links to its contracts when held. Start with no agency filter to get the accepted labels. An unknown label gets suggestions. The fiscal year uses the registration date, from July 1 through June 30. These totals do not measure payments or spending.
  • get_person_or_organization read — Get one exact typed person or organization row from the published People and organizations read model. Display names never create identity. Relation states and source fields are preserved.
  • browse_organizations read — Browse the bounded typed People and organizations snapshot with exact row-kind and token filters. Results retain published, empty, or unknown relation states and read-model freshness.
  • get_meeting read — Read one exact source meeting, with its ID, board, source date, and documents intact. The record states whether the meeting is held, whether minutes were published, and whether a City Record notice is linked. A missing notice link does not mean the source meeting is absent.
  • get_land_project read — Get one exact Land (ZAP) project by its ZAP project id. Includes its deep link, status, geography, applicant, review procedure, exact actions and ids, environmental facts, milestones, outcomes, sources, and any conflicts, when known.
  • browse_land_projects read — List public Land (ZAP) projects using the same filters as the Land page: review procedure, action type, stage, effect, and geography. Reads the full warehouse, not just active projects, so completed and past projects stay reachable too.
  • get_land_decision_path read — Get the typed Land decision path for one exact project. Observed milestones and events remain separate from the reviewed normative procedure stages, actors, effects, and parallel review groups. Absent and unknown stages stay explicit.
  • preview_watch read — Preview what a standing watch would deliver, without subscribing. Lens: money (procurement), land (rezonings), property, rules, meetings, people. Pass a structured filter to keep alternatives, phrases, and exclusions. Plain English remains optional.
  • create_watch mutation — Create a standing email watch. The watch starts immediately. The welcome email states its scope and includes manage and unsubscribe links. Pass a structured filter to keep alternatives, phrases, and exclusions. Plain English remains optional.
  • list_capability_gaps read — List the capability gaps CityScroll declares about itself, so a caller can name what this endpoint does not answer instead of assuming a tool for it exists. Declared gaps: civic.outcome.prediction (What outcome will a public decision definitely produce? — nearest tools: get_land_project, get_land_decision_path). Takes no input, reads no records, and returns only this published declaration.

Machine-readable inventory: JSON catalog.

Upstream data

CityScroll republishes and joins public datasets — for bulk work, go straight to the sources: City Record Online (dg92-zbpx, Socrata SODA) (opens in new tab) · Checkbook NYC API (opens in new tab) · Citywide Payroll (opens in new tab) · Civil Service List (opens in new tab) · ZAP (opens in new tab).