Skip to content

Workspace API

Upsert Subscription

Subscribe to a signal type or update an existing subscription with POST /workspace/signal-subscriptions/upsert.

Endpoint
POST https://api.parcelengineering.com/api/v1/workspace/signal-subscriptions/upsert

Creates a signal subscription or updates an existing one. The operation is keyed by signal_type: if the workspace already has a subscription for the given type, the provided fields are merged in; fields not present in the body are left unchanged. The queue watermark is never reset on an update.

Creating a subscription starts queueing signals discovered from now on, with a short lookback so the queue is not empty on arrival.

Upsert costs 0 credits.

Request body

FieldTypeRequiredDescription
signal_typestringYesThe signal type to subscribe to. See Valid signal types below.
prioritystringNoQueue priority: high, medium, or low. Defaults to medium on create.
channelsstring[]NoDelivery channels: any combination of email, teams, slack. Email is the only channel that delivers today; Teams and Slack are coming soon. Defaults to [] on create.
notify_all_membersbooleanNoWhen true, email alerts go to every workspace member (including future members) and recipient_user_ids is ignored. Defaults to false on create.
recipient_user_idsstring[] (UUIDs)NoSpecific workspace members to notify. All IDs must be current workspace members. Maximum 100. Defaults to [] on create.
cadencestringNoDelivery cadence: immediate (send as signals arrive) or daily_digest (batched once per day). Defaults to immediate on create.

Valid signal types

The signal_type field accepts any value from the subscribable signal taxonomy:

project_announcement, pre_application, site_acquisition, demolition_permit, site_prep, entitlement_application, environmental_review, public_review, entitlement_approval, entitlement_denial, withdrawal, expiration, permit_filed, permit_issued, construction_loan, under_construction, team_update, completion

Note: rfp is a reserved type and is not subscribable.

Partial update semantics

  • Omitted fields are left unchanged on an existing subscription. You can update priority without touching channels or recipients.
  • channels, notify_all_members, and recipient_user_ids are always validated as a unit against the merged post-update state. If the result would have email selected with no recipients (and notify_all_members is false), the request returns 400 email_requires_recipients.

Recipient rules

  • Every UUID in recipient_user_ids must be a current workspace member. Non-members cause a 400 invalid_recipients error.
  • Setting notify_all_members: true emails all current and future workspace members and takes precedence over any explicit recipient_user_ids.

Example

Subscribe to permit_issued signals
curl -X POST https://api.parcelengineering.com/api/v1/workspace/signal-subscriptions/upsert \
-H "Authorization: Bearer pcl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"signal_type": "permit_issued",
"priority": "high",
"channels": ["email"],
"notify_all_members": false,
"recipient_user_ids": ["d1e2f3a4-0001-4b7c-9e5d-000000000001"],
"cadence": "immediate"
}'

Response

The response is the full list of the workspace’s subscriptions after the upsert, in the same shape as List Subscriptions.

Response
{
"data": {
"subscriptions": [
{
"id": "7c3f1a2b-0001-4e8d-bf6a-000000000001",
"signal_type": "permit_issued",
"priority": "high",
"channels": ["email"],
"notify_all_members": false,
"recipient_user_ids": ["d1e2f3a4-0001-4b7c-9e5d-000000000001"],
"cadence": "immediate",
"new_count": 14,
"created_at": "2025-06-01T12:00:00.000Z",
"updated_at": "2025-06-15T09:30:00.000Z"
}
],
"filed_floor_days": 90
},
"metadata": { "credits": 0 }
}

Upsert costs 0 credits.