About
Programmatic access to your deal flow: fetch and search deals, spot deals going cold, and create, update, move, or archive deals from your own code. Edit pipeline custom-field definitions and open or move Scraper Health cards with reasoning recorded alongside each move. Pipeline structure (creating pipelines, editing stages) and pipeline analytics have their own page — see the Pipelines API. All operations go through the developer API gateway — one endpoint, called byoperationId. If you haven’t set up a key yet, start with the
Developer API Overview.
Operations
Reading deals (READ scope)
findDeals, surveyDeals and listStalledDeals are paginated
findDeals and listStalledDeals return up to 50 rows per call;
surveyDeals returns up to 45 (default 16). All take an
offset and return totalCount + hasMore, so you can page through the full
set. Advance offset by the number of rows returned until hasMore is false.
For example, with limit: 16, request offsets 0, 16, and 32. Do not jump by 50
while using a smaller page size. See
Result limits & truncation.findDeals and surveyDeals return taskSummary.openTaskCount and
taskSummary.openAppointmentCount. These count open items linked to the deal,
not every task on its contacts. An openTaskCount of zero identifies a deal with
no open task without reading its whole activity feed.
Saved deal filters (READ scope)
A saved deal filter does not fix its pipeline: supply the pipeline on every
execution. Inline
filterTree is not accepted by filterDeals; save the
criteria first. Discover DEAL fields with listFilterFieldNames and
listFilterFields, and manage filter folders through the
Properties API.
Check the owner’s userId before editing or deleting a shared filter.
Which deal read to reach forThree reads, three shapes of question.
getDeal is one deal in full.
findDeals is a handful of deals with everything on them — money, contacts,
dates. surveyDeals gives a little on each row for grouping or “who owns what”
sweeps. Page through all matches before describing the whole board, and take
counts from totalCount, never from the length of one page.Custom fields in search results
findDeals.customFieldValues and surveyDeals.customFieldValues include each
recorded value and its field’s
name (dealCustomField.name), without definition ids or types. An absent
entry means the deal has no recorded value for that field; an empty list
does not mean the pipeline has no custom fields. Use listDealCustomFields
for definitions and ids before writing. Custom fields increase the response
size; use a smaller limit when you need smaller pages.Writing deals (WRITE scope)
Deal money fieldsCommission and team split each accept one source: a fixed
*AmountCents or a
*PercentBps, never both. commissionCents is the server-derived GCI to
report. Participant splits allocate what remains after the team fee. For deal
custom fields, use the value member that matches the definition type; DOLLAR
values are plain numbers, not cents, and dropdown values are option labels.Scraper Health cards
Benchmark keys are scoped to your organization. Akey contains 1–200
lowercase letters, digits, or : _ . -, starting with a letter or digit.
Concurrent upserts for the same key create one card. An upsert that finds an
existing card does not change it or append an event; use the move operation
for subsequent verdicts.
Both writes take an event with healthActor: MONITOR | DOCTOR | PERSON and
required why (1–4,000 characters). Optional checked, found, and nextTime
are limited to 4,000 characters each; handoffSummary is limited to 600.
Optional evidence fields are delivered, expected (fractional values
allowed), and windowDays. Malformed events are rejected before writing.
The server fills in the key owner and stage names.
Read the reasoning with listDealActivity, narrowed to
eventTypes: ["SCRAPER_HEALTH_MOVED"]. Its SuperJSON payload at json includes
healthActor (stored as monitor, doctor, or person), fromStage,
toStage, and the event’s reasoning and evidence. fromStage is null on the
creation event. Moving to the current stage records a verdict without changing
the stage; a different pipeline’s stage or a non-card deal is refused.
Creation and stage changes also trigger ordinary stage-entry workflows.
Guarding against a concurrent editPass
expectedUpdatedAt — the updatedAt you got from getDeal, findDeals,
or a previous write — to make the update conditional. The write applies only if
the deal hasn’t changed since; otherwise nothing is written and you get
CONFLICT. Use it whenever you decided what to write from a copy you read
earlier, so a concurrent edit fails loudly instead of being silently
overwritten.A guarded update is all-or-nothing: userIds, participantSplits, and
customFieldValues are part of the same transaction as the core deal
fields. A rejected value rolls back the whole edit, including title and
stage changes. A successful write advances updatedAt, so re-read before
using another concurrency guard.Without expectedUpdatedAt, the core write commits before the custom
fields: a later custom-field failure can leave the title or stage changed.
A deleted deal returns NOT_FOUND; an unparseable token returns
BAD_USER_INPUT.Organization guardDeal operations are org-guarded: the deal (and any destination stage) must
belong to a pipeline owned by or shared with your organization, or the call
returns
403 forbidden. Pipelines shared with your org through a
partnership work normally. See
Authorization for the full
owned-vs-shared model.Pipeline operations
The Pipelines API covers the rest of the deals domain:- Read structure with
listPipelineNames,listPipelines, andlistPipelineStages(READ). - Create and edit it with
createPipeline,updatePipeline,addPipelineStages,updatePipelineStage, andreorderPipelineStages(WRITE). - Preview dependencies with
getDeletionImpact(READ) beforedeletePipelineordeletePipelineStage(WRITE). Review the replacement options carefully: one permanently deletes the stage’s deals. - Read reporting with
getPipelineAnalyticsandlistPipelineTransitions(ADMIN, rate-limited).