Workspace API
Search Contacts
Search the contacts you have saved in your workspace with POST /workspace/contacts/search.
POST https://api.parcelengineering.com/api/v1/workspace/contacts/searchThis endpoint searches only the contacts you have saved and annotated in your workspace (your book), not the global Parcel dataset. It does not accept view_id. For Dynamic or Static View execution (including Static Contact follow visibility), use POST /workspace/views/{id}/records/search. To find new contacts to track, use the Data API contacts search first, then upsert them into your workspace.
The Workspace API requires the Pro plan. A request from a non-Pro workspace or a non-member receives 403 forbidden.
Query parameters
| Parameter | Description |
|---|---|
workspace_id | Attribution. Required when authenticating with a user JWT (for example, via the MCP server). Optional for API keys. Omitting it on a user-token request returns 400 bad_request. |
Request body
All fields are optional. An empty body returns the first 25 contacts sorted by updated_at descending.
| Field | Type | Default | Description |
|---|---|---|---|
query | string (min 1) | (none) | Fuzzy search over contact name, title, email, phone, and associated account name. |
filters | object | (none) | Field and relational filters. |
sort.field | string | updated_at | Sort field. Must be a valid sort key (see below). Required when sort is present. |
sort.order | asc | desc | desc | Sort direction. |
limit | integer 1..100 | 25 | Records per page. |
offset | integer 0..10000 | 0 | Zero-based record offset for pagination. |
search_after | string | (none) | Opaque keyset cursor from the previous response’s metadata.search_after. Pass it to fetch the next page. |
Sort keys
| Valid sort fields | Default |
|---|---|
updated_at, name, created_at | updated_at (desc) |
Workspace filters
| Filter key | Type | Notes |
|---|---|---|
workspace_status | field | Your workflow status string. Exact match. |
tags | field | Tag value. Array value = OR. |
name | field | Contact name. Supports fuzzy match. |
title | field | Job title. Supports fuzzy match. |
email | field | Email address. Exact match. |
account_id | field | UUID of the associated account. |
Relational filters
| Key | Inner filter fields |
|---|---|
at_account | account_type, name |
on_project | stage, primary_use, city |
Example
curl -X POST https://api.parcelengineering.com/api/v1/workspace/contacts/search \ -H "Authorization: Bearer pcl_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "filters": { "title": { "value": "Project Manager" }, "on_project": { "stage": { "value": "under_construction" } } }, "sort": { "field": "name", "order": "asc" }, "limit": 25 }'const response = await fetch( 'https://api.parcelengineering.com/api/v1/workspace/contacts/search', { method: 'POST', headers: { 'Authorization': 'Bearer pcl_your_api_key', 'Content-Type': 'application/json', }, body: JSON.stringify({ filters: { title: { value: 'Project Manager' }, on_project: { stage: { value: 'under_construction' }, }, }, sort: { field: 'name', order: 'asc' }, limit: 25, }), });
const { data, metadata } = await response.json();Response
{ "data": [ { "id": "3c7a9f2d-0001-4e1b-bc4a-000000000001", "name": "Jordan Rivera", "title": "Project Manager", "email": "jrivera@acmedev.com", "account_id": "8a1f3c2e-0001-4b7d-9e5a-000000000001", "workspace_status": "prospect", "notes": "Met at Boston Planning Forum 2026", "tags": ["vip", "developer"] } ], "metadata": { "total": 7, "total_is_capped": false, "limit": 25, "offset": 0, "search_after": null, "credits": 7 }}The data array is trimmed to one record above. A page returning 7 contacts costs 7 credits.
Metadata fields
| Field | Description |
|---|---|
total | Match count, capped at 1,000. When more than 1,000 contacts match, total reports 1000 and total_is_capped is true. |
total_is_capped | true when the actual count exceeds the cap. |
limit | Page size, echoed back from the request. |
offset | Echoed back from the request, or 0 when paging with search_after. |
search_after | Opaque cursor for the next page, or null on the last page. |
credits | Credits consumed by this request. Equals the number of contacts returned. |
Each contact returned costs 1 credit toward your workspace’s rolling 24-hour ceiling of 250,000 credits. See Credits.