---
title: "Run a plan of searches"
method: POST
path: "/public/run-searches"
tags: ["public"]
---

# Run a plan of searches

`POST /public/run-searches`

## Request

- Base URL: `https://api.bereach.ai`
- URL: `https://api.bereach.ai/public/run-searches`
- Auth: HTTP bearer

Run a ready plan returned by plan-searches, in the background, and save the people it finds into the conversation's list, or your contacts outside one. Answers within about 25 seconds with a receipt: people added so far, credits used, and each search's state. A run answers in about 6 seconds, and one in ten takes about 10 or more; the people come from our index, about 3 weeks old at the median, so a recent job move can be missing. A plan runs once: calling again with the same plan_id answers where its run stands and spends nothing more. Every search is charged to the workspace credit pool like a people search, and the run never spends more than the plan's cost_estimate_credits.

## Request body

- object
  - `plan_id` string, required: The plan_id of a plan the user agreed to, exactly as it was returned. A plan runs once: calling again with the same plan_id answers where its run stands and spends nothing more.

## Response `200`

The run's receipt

- object
  - `plan_id` string, required
  - `state` 'running' | 'done' | 'stopped' | 'failed' | 'not_started' | 'busy', required
  - `stopped_because` 'plan_done' | 'reached_target' | 'out_of_credits' | 'daily_limit' | 'search_paused' | 'market_not_reachable' | 'round_limit' | 'ceiling_reached' | 'search_unavailable'
  - `added` integer, required: New rows in this list.
  - `already_known` integer, required: People found again who are already in this list.
  - `removed` integer: People found whom the user removed from this list earlier: left out and not added back.
  - `list_total` integer: The list's size after this run, the only running total.
  - `not_saved` object: People found but not saved.
    - `unreadable` integer, required
    - `credits_ran_out` integer, required
  - `credits_used` integer, required: Credits this run has spent so far, over every call on this plan_id.
  - `cost_estimate_credits` integer, required: The most this run may spend: the plan's ceiling.
  - `searches` object[], required
    - `id` string, required
    - `icp` string, required
    - `rank` integer, required
    - `label` string, required
    - `state` 'queued' | 'searching' | 'done' | 'not_reachable' | 'stopped' | 'failed', required
    - `added` integer, required
    - `queries_run` integer, required
    - `queries_planned` integer, required
    - `note` string
  - `icps` object[]
    - `id` string, required
    - `added` integer, required
  - `not_applied` string[]: Plan fields kept for verification later, which nothing checked.
  - `notes` string[]: The searches' own sentences, to relay as written.
  - `running_plan_id` string: On busy: the plan whose run is going in this list.
  - `next` string, required

## Other responses

- `400`: The server cannot or will not process the request due to something that is perceived to be a client error. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `401`: Although HTTP specifies "unauthorized", this response means "unauthenticated". Authenticate to continue. NOTE: 401 is also returned with code "linkedin_not_connected" on an endpoint that acts from your account (invitations, messages, your own network or inbox) when the caller IS authenticated but has no connected LinkedIn account: connect LinkedIn (not re-authenticate) to continue. Every other read never returns it. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `403`: The caller is authenticated but not allowed. Read code: subscription_required (API key or connector whose plan is not active), free_draft_limit (a free-plan limit was reached), sales_nav_seat_inactive (no active Sales Navigator seat), or forbidden (not permitted). The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `404`: The server cannot find the requested resource. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `409`: The request conflicts with the current state of the server. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `410`: The requested content has been permanently deleted from the server. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `422`: The request was well-formed but was unable to be followed due to semantic errors. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `429`: Rate limit exceeded. Read retryAfter for the wait time in seconds. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `500`: The server encountered a situation it does not know how to handle. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `502`: An upstream service returned an error. Retry after a few seconds. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.
- `503`: Capacity is temporarily exceeded. Retry after a few seconds. The body is the flat `{ error: "<text>" }` form, with `code` when the answer carries one; a few answers use the envelope.

## Changes

> 39 revisions in range; 1 not diffed.

- **2026-10-22** `549f4adbbfcf`: 33 breaking, 12 info
  - the response's body type changed from `object` to no type for status `400`
  - the response's body type changed from `object` to no type for status `401`
  - the response's body type changed from `object` to no type for status `403`
  - the response's body type changed from `object` to no type for status `404`
  - …41 more
- **2026-10-22** `bdaed6984b20`: 1 warning
  - removed the optional property `credits_left` from the response with the `200` status
- **2026-10-16** `a797d757efbd`: 3 info
  - added the optional property `icps` to the response with the `200` status
  - added the required property `searches/items/icp` to the response with the `200` status
  - added the required property `searches/items/rank` to the response with the `200` status
- **2026-10-15** `426eb2a9e61b`: 1 warning
  - removed the optional property `left_out` from the response with the `200` status
- **2026-10-03** `e8a9550eb535`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/berea/apis/bereach-api/changes/public/run-searches/post.md)

---

[API](https://skmtc.dev/berea/apis/bereach-api.md) · [All operations](https://skmtc.dev/berea/apis/bereach-api/llms.txt) · [OpenAPI document](https://skmtc.dev/berea/apis/bereach-api/revisions/b657f915ce03?raw)
