Runs
Run kinds, statuses, progress, results, credits, polling and cancellation.
A run is one asynchronous job: discovery, import, monitor or export. A start operation returns 202 with a run in the status queued. The work continues after the response. Read the run with get_run until it has a final status. A queued or running status does not mean that the work is complete.
Runs can start paid research
Discovery runs and import runs start paid research and use credits. The scheduled runs of a monitor and of a campaign discovery also use credits. Export runs use no credits. Do not start a paid run to test a client: use read operations for tests.
The run object
| Field | Type | Description |
|---|---|---|
id | UUID | Required. ID of the run. |
kind | enum | Required. discovery, import, monitor or export. See Run kinds. |
campaign_id | UUID | Nullable. ID of the campaign of the run. |
monitor_id | UUID | Nullable. ID of the monitor of a monitor run. Null for the other kinds. |
status | enum | Required. See Run statuses. |
skipped_reason | string | Nullable. Why a skipped run did not start, for example insufficient_credits. Null when the status is not skipped. |
trigger | enum | Required. scheduled when a schedule started the run, else manual. |
created_at | timestamp | Required. Time when the run was created. |
started_at | timestamp | Nullable. Time when the run started to work. Null when it is not known. |
finished_at | timestamp | Nullable. Time when the run finished. Null while the run is not finished, and while a canceled run stops. |
progress | object | Nullable. The queue counts. See Progress and result. Null before the queue starts, and after the queue data expires at 30 days. |
result | object | Nullable. The result of a finished run. Null while the run is not finished, for a skipped run, and when the counts are not known. |
error_code | enum | Nullable. Stable reason code of a failed, canceled or skipped run. See Error codes. Null for a run that is queued, running or succeeded. |
error | string | Nullable. Error text of a failed, canceled or skipped run, for a person. The text can change: do not parse it. Use error_code in your code. |
Run kinds
| Kind | Started by | Uses credits | result.completed |
|---|---|---|---|
discovery | start_discovery, or the discovery schedule of a campaign | Yes | Accounts that the run added. The count does not include the people of the accounts. |
import | start_import (JSON rows) or upload_import (CSV file) | Yes | Rows that the run added. |
monitor | The schedule of a monitor, or run_monitor | Yes | Signals that the run processed. |
export | start_export | No | Accounts or people in the file. |
Credits
Signal charges credits for each action that a run takes, not for each run. These are the prices:
| Action | Credits |
|---|---|
| Create an account or a person | 1 |
| Update an account or a person with research data | 1 |
| Find the phone number of a person | 0.5 for each phone number |
| Create a signal | 1 |
| Send one monitor search query | 0.1 |
A monitor sends one search query for each watched record and each signal type in its config.
| Example | Estimate |
|---|---|
start_discovery with count 25 and contacts_per_account 2 | Up to 25 accounts and 50 people: 75 credits to create them, plus 1 credit for each research update. |
start_import with 100 rows | 1 credit for each record that the import creates, plus 1 credit for each research update. |
| A monitor run that watches 200 accounts for 2 signal types | 400 queries: 40 credits, plus 1 credit for each signal that the run creates. |
start_export | 0 credits. |
Send get_me to read the balance before you start a run. Signal also checks the balance while a run works, and stops the run when the credits run out. A start with no credits gives 402. Read Start rules.
Run statuses
A run has one of six statuses. succeeded, failed, canceled and skipped are final.
| Status | Description |
|---|---|
queued | The run waits to start. Every start operation returns this status. |
running | The run does its work. |
succeeded | The run finished. result holds the counts. |
failed | The run stopped with an error. error_code and error give the reason. |
canceled | The run was canceled with cancel_run, delete_monitor or delete_campaign, or Signal stopped a stuck run. |
skipped | A scheduled run that did not start because the organization had no credits. skipped_reason is insufficient_credits. |
Signal stops a discovery, import or monitor run that stays queued for 2 hours after its start time, or that shows no activity for 2 hours. The run then gets the status canceled, or succeeded when it produced output. A canceled run keeps the records that it added before the cancel.
Cancellation keeps completed records and the credits already used. While cancellation stops the worker, finished_at can remain null. Deleting a campaign or monitor removes API access to its run history. See Cancel rules.
Error codes
error_code is a stable value. Use it in your code.
error_code | Status | Meaning |
|---|---|---|
insufficient_credits | skipped | The organization had no credits when the scheduled run was due. |
canceled_by_user | canceled | A request canceled the run: cancel_run, delete_monitor or delete_campaign. |
canceled_stuck | canceled | Signal stopped the run because it did not start, or showed no activity, for 2 hours. |
worker_crashed | failed | The worker that ran the run stopped. Start the run again. |
run_failed | failed | The run stopped with an error. |
Progress and result
progress holds the queue counts while the run works:
| Field | Description |
|---|---|
target | Number of items that the run put in its queue. |
queued | Number of items that wait in the queue. |
completed | Number of items that the run finished. |
discarded | Number of items that the run rejected. A monitor run has none. |
result holds the final counts of a finished run. The fields that apply depend on the kind:
| Field | Type | Description |
|---|---|---|
completed | integer | Nullable. The meaning depends on the kind. See Run kinds. |
discarded | integer | Nullable. Discovery and import: items that the run rejected. Null for the other kinds. |
download_url | string | Nullable. Export: URL of the CSV file. Null for the other kinds. |
download_expires_at | timestamp | Nullable. Export: time when download_url stops working. |
Start rules
A start returns 202 with a queued run. Each job reference owns its request and result rules:
- Discovery:
start_discovery. - Import:
start_importandupload_import. - Export:
start_export. - Monitors:
run_monitor.
A paid start with no credits gives 402 and starts no run. See Errors.
Cancel rules
cancel_runcancels a run that isqueuedorrunning. The run gets the statuscanceled.- A run that is already finished gives 409.
- An export run cannot be canceled.
cancel_runon an export run gives 409. - After
cancel_run,finished_atstays null until the run stops. Read the run again withget_runto get the end time. delete_monitorcancels the active runs of the monitor.delete_campaigncancels active runs of discovery and import configurations that it removes. Independent monitors continue.- Explicit monitor deletion makes its runs unreadable. Source campaign deletion retains monitors and their runs.
Export download
See the Export reference.
List and poll
list_runs lists the runs of the organization, newest first. It takes the filters campaign_id, kind, status, created_after (at or after) and created_before (before). The time filters are RFC 3339 strings. The list shows the stored status. get_run gives the current status of one run.
Poll get_run every 15 seconds, for at most 240 attempts (60 minutes). If the run stays active, send cancel_run when supported and contact support with its ID. Stop when the status is final. The campaign field active_run_ids lists the discovery, import and monitor runs that are queued or running.
Operations
Each path below follows $LINKT_API_URL/v2. Set LINKT_API_URL to the origin only, for example https://api.signal.linkt.ai.
| Operation | Method and path | Purpose |
|---|---|---|
list_runs | GET /runs | List the runs of the organization, newest first. |
get_run | GET /runs/{run_id} | Get one run with its current status, progress and result. |
cancel_run | POST /runs/{run_id}/cancel | Cancel a queued or running run. |
start_discovery | POST /runs/discovery | Start a discovery run. Uses credits. |
start_import | POST /runs/import | Import accounts or people from JSON rows. Uses credits. |
upload_import | POST /runs/import/upload | Import accounts or people from a CSV file. Uses credits. |
start_export | POST /runs/export | Export accounts or people to a CSV file. Uses no credits. |
curl --fail-with-body --request GET "$LINKT_API_URL/v2/runs/$RUN_ID" \
--header "x-api-key: $LINKT_API_KEY"curl --fail-with-body --request GET "$LINKT_API_URL/v2/runs?limit=5" \
--header "x-api-key: $LINKT_API_KEY"Related
- Create a campaign and discover accounts
- Import accounts or people
- Export data
- Paginate and handle errors
- API reference
Correlate import rows
POST /v2/runs/import accepts 1 to 1,000 JSON rows. Import research and qualification
use the campaign criteria. Each row has a zero-based index. Optional external_id
keeps your original string, including leading zeroes. Duplicate and empty external IDs
are valid. Use row_index to distinguish repeated rows.
Accounts accept name, website, domain, and linkedin_url. People also accept
first_name, last_name, email, and title. Extra fields remain research input.
linkedin_url maps to the stored LinkedIn field. external_id never affects identity
matching. Server-owned fields such as row_index, signal_id, and parent_id do not
set internal context.
A person can name an existing account with account_id. The account must belong to
your organization. Signal adds an account copy to the campaign when needed and keeps
that account as the person's parent during research. A missing, foreign, deleted, or
unavailable account produces account_not_found.
Missing names, invalid field types, malformed CSV, and invalid file envelopes return 422 before a run starts. These requests have no row outcomes. Research, qualification, account lookup, and persistence failures after admission produce row outcomes.
Retrieve outcomes
Read GET /v2/runs/{run_id} until result.import_rows.availability is ready.
Then call list_import_rows with GET /v2/runs/{run_id}/rows?limit=25. Pages contain at most 100 rows,
in ascending row_index order. Send next_cursor to retrieve the next page. A cursor
belongs to one run and one organization.
curl --fail-with-body --request GET "$LINKT_API_URL/v2/runs/$RUN_ID/rows?limit=5" \
--header "x-api-key: $LINKT_API_KEY"created means the row creates a public identity. matched means the row resolves to
an existing public identity. Both return signal_id. Identity matching uses the current
name and secondary-identifier rules across campaigns. A repeated row can match an
identity created by an earlier row. Additional researched records cannot replace the
input record's result. Conflicting input candidates produce ambiguous_input_entity.
rejected returns signal_id: null and a stable reason_code:
| Code | Condition |
|---|---|
account_not_found | The explicit account cannot supply a scoped campaign copy. |
account_mismatch | The saved person's parent does not resolve to the explicit account. |
not_qualified | The analyst rejects the row before saving its input record. |
ambiguous_input_entity | Multiple saved candidates correspond to the input. |
processing_failed | Processing produces no recoverable input record. |
credits_exhausted | Credits stop processing before the row is processed. |
run_canceled | The worker stops after cancellation before processing the row. |
run_failed | The worker fails before processing the row. |
A saved copy whose identity is temporarily unresolved keeps outcomes pending for
recovery. GET /rows returns 409 import_rows_pending while the import runs or outcomes
are incomplete. A cancellation flag alone does not finalize rows. Failed and canceled
imports retain saved successes after worker termination is confirmed. Retries recover
saved copies and preserve final outcomes. Row outcomes survive queue expiry.
Historical imports have availability: "unavailable". Their row endpoint returns
409 import_rows_unavailable. Signal does not invent historical row mappings. A run
of another kind returns 422 not_import_run. Final import counts come from row outcomes:
completed equals created plus matched; discarded equals rejected.