Skip to content

Workspace API

Projects

Save and annotate the global projects you care about. Search returns only the ones you have saved to your workspace.

You save global Parcel projects to your workspace and annotate them with your own data. Workspace project search returns only the projects you have saved, not the full global dataset. To start tracking a new project, find it via the Data API and then upsert it by id.

Fields you set

These fields are written by your team via the upsert endpoint.

FieldTypeNotes
workspace_statusstring | nullYour workflow state for this project (for example, "watching", "bid_submitted"). Any string value or null.
notesstring | nullFree-text notes for your team. Explicit null clears the value.
tagsstring[]Arbitrary labels. Full-replace on every write (sending ["boston"] replaces the entire tag set).

Fields Parcel computes (read-only)

These fields are computed by Parcel from permit records and market signals. You cannot set them directly.

FieldTypeNotes
stagestring | nullCurrent lifecycle stage of the project (for example, "filed", "permitted", "under_construction", "completed").
last_signal_atstring | nullISO 8601 timestamp of the most recent signal on this project.
primary_usestring | nullPrimary building use type (for example, "residential", "commercial", "mixed_use").
residential_unitsinteger | nullNumber of residential units, when applicable.
gross_floor_area_sfnumber | nullTotal gross floor area in square feet.
cost_of_construction_usdnumber | nullEstimated construction cost in US dollars.
storiesinteger | nullStoreys a filing or the project’s own site states. Null means no source states it, not a one-storey building
parking_spacesinteger | nullParking spaces stated. 0 is a stated zero; null means no source states it
gc_statusstringnamed (a general contractor is linked), not_yet_selected (a filing states none is chosen yet), or unknown (no source says). Derived when read

Detail fields (GET only)

A single-project GET also returns these. Search results leave them out to keep rows small.

FieldTypeNotes
height_ftinteger | nullBuilding height in whole feet. Null means no source states it
hotel_roomsinteger | nullHotel rooms stated. 0 is a stated zero; null means no source states it
land_area_sfinteger | nullSite area in square feet. Null means no source states it
unit_mixobject | null{ studio_or_1br, two_br, three_br_plus }. Null when no bedroom count is known; a null member is a count no source states
affordable_unitsobject | nullIncome-restricted units by area-median-income band: { ami_0_30, ami_30_50, ami_50_80, ami_80_120, ami_unknown }. Null when no band is known; a null member is a band no source states
use_areasobject[]{ use_type, floor_area_sf } for each non-residential use a source states, largest first. Empty means none is stated, not that there is none
structure_typesstring[]Construction types a source names: wood_frame, podium, steel, concrete, mass_timber, masonry, modular. Empty means none is stated
regulatory_flagsstring[]Review paths the project went through: chapter_40b, special_permit, site_plan_review, variance, pud, design_review, wetlands_notice_of_intent, large_project_review, small_project_review
farobject | nullFloor area ratio, { value, derived_from: "gross_floor_area_sf/land_area_sf" }. Derived when read; no source states it. Null unless both areas are known
updates_last_30_daysintegerSignals filed in the last 30 days, counted by filing date rather than when Parcel found them

Filters

Default sort: updated_at desc

Filter keyTypeNotes
workspace_statusfieldYour workflow status string. Exact match.
tagsfieldTag value. Array value = OR.
namefieldProject name. Supports fuzzy match.
stagefieldProject stage value. Array value = OR.
primary_usefieldBuilding use type. Array value = OR.
cityfieldCity name. exact_match: false (default) = fuzzy.
statefieldState code, for example "MA".
gc_statusfieldnamed, not_yet_selected or unknown. Array value = OR
stories_knownfieldknown or unknown: whether any source states a storey count. REST only; the MCP search tools leave it out

Sort keys: updated_at, last_signal_at, name, created_at

Range keys: stories, residential_units, gross_floor_area_sf, cost_of_construction_usd, last_signal_at

A range never matches a project whose value is unknown (null). To find projects with no stated storey count, filter stories_known to unknown.

stage and primary_use are enum-backed: a value outside the allowed set returns 400 (not zero rows), and they do not accept exact_match since a closed vocabulary is always exact. See Errors.

Relational filters

Use relational filters to match projects based on properties of their related records.

KeyInner filter fields
has_accountrole, name, account_type
without_accountrole, name, account_type
has_signalsignal_type, filed_at (range)
without_signalsignal_type, filed_at (range)
has_contactrole, title
without_contactrole, title

Each without_* key takes the same inner fields as its has_* twin, but matches your saved projects with NO related record satisfying the inner criteria (NOT EXISTS) instead of at least one. See Filtering for the semantics.

Includes

Valid include keys for GET /workspace/projects/{id}: accounts, contacts, signals.

Example: GET /workspace/projects/<id>?include=accounts&include=signals

Search example

The query below finds your saved projects currently under construction in Massachusetts, sorted by most recent signal.

Search workspace projects
curl -X POST https://api.parcelengineering.com/api/v1/workspace/projects/search \
-H "Authorization: Bearer pcl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"filters": {
"stage": { "value": "under_construction" },
"state": { "value": "MA" }
},
"sort": { "field": "last_signal_at", "order": "desc" },
"limit": 25
}'
Response
{
"data": [
{
"id": "7b2e4d1f-0001-4c8e-af6b-000000000001",
"name": "100 Seaport Boulevard",
"city": "Boston",
"state": "MA",
"stage": "under_construction",
"primary_use": "mixed_use",
"residential_units": 120,
"gross_floor_area_sf": 180000,
"cost_of_construction_usd": 42000000,
"stories": 9,
"parking_spaces": 40,
"gc_status": "unknown",
"last_signal_at": "2026-06-01T00:00:00Z",
"workspace_status": "watching",
"notes": "GC bid due Q3",
"tags": ["seaport", "mixed-use"]
}
],
"metadata": {
"total": 11,
"total_is_capped": false,
"credits": 11
}
}

The data array is trimmed to one record above. A page returning 11 projects costs 11 credits (1 per row returned).

See also