---
title: "Turn any material into a plan of searches"
method: POST
path: "/public/plan-searches"
tags: ["public"]
---

# Turn any material into a plan of searches

`POST /public/plan-searches`

## Request

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

Read what someone sells and who they want to reach, from their own words, the text of documents or pages, or page addresses read by the server, and answer with a plan of people searches: what was said and what was inferred, the segments with their kinds of company, places and job titles, the searches a run would send and what they cost. While something blocking is missing the answer carries up to five questions and no searches; call again with plan_id and the answers. Free: nothing is searched, charged or saved. In a conversation the plan is that conversation's own, and a later call changes it.

## Request body

- object
  - `context` string: Everything known about who the user sells to and who they want to reach, as written: their own words, the text of their documents or pages, their answers to earlier questions. Pass texts whole, not summarised.
  - `urls` string[]: Pages the server reads itself: the user's own website, a page about their offer or their customers. Only addresses the user gave or a tool returned.
  - `plan_id` string: The plan_id of the plan this call answers or changes, as it was returned.
  - `edits` union[]: Changes to the plan of plan_id, applied without reading it again and sent with nothing else. icp is a segment id; pick adds a place, or a role or kind that segment offered; any other change goes in context.
    - union
      - object
        - `op` 'remove', required
        - `field` 'personas' | 'variants' | 'kinds' | 'places' | 'languages' | 'keywords' | 'size' | 'perCompany' | 'peopleWanted', required
        - `icp` string
        - `id` string
        - `value` string
      - object
        - `op` 'pick', required
        - `icp` string, required
        - `field` 'roles' | 'kinds' | 'places', required
        - `value` string, required
      - object
        - `op` 'first', required
        - `icp` string, required
      - object
        - `op` 'drop', required
        - `icp` string, required
      - object
        - `op` 'more', required

## Response `200`

Questions to ask, a ready plan, or nothing to search

- union
  - object
    - `plan_id` string, required
    - `version` integer, required
    - `ready` false, required
    - `assumptions` object[], required
      - `fact` string, required
      - `origin` 'said' | 'inferred' | 'confirmed', required
      - `source` string, required
      - `use` 'search' | 'verification', required
      - `applied` boolean, required: Whether this fact acts on the search now.
    - `questions` object[], required
      - `id` string, required
      - `question` string, required
      - `options` string[], required
      - `default` string: What applies when the question is skipped; absent only when nothing can stand in.
    - `segments` object[], required
      - `id` string, required
      - `name` string, required
      - `confidence` 'high' | 'medium' | 'low', required
      - `kinds` string[], required
      - `every_industry` true
      - `example_kind` string
      - `places` string[], required
      - `groups` object[], required
        - `id` string, required
        - `name` string, required
        - `titles` string[]
      - `evidence` object[], required
        - `source` string, required
        - `quote` string, required
      - `offered` object
        - `roles` string[]
        - `kinds` string[]
        - `places` string[]
    - `searches` object[], required
      - `id` string, required
      - `segment` string, required
      - `language` string, required
      - `where` string, required
      - `queries` string[], required
    - `unread` object[]
      - `url` string, required
      - `why` string, required
    - `next` string, required
  - object
    - `plan_id` string, required
    - `version` integer, required
    - `ready` true, required
    - `assumptions` object[], required
      - `fact` string, required
      - `origin` 'said' | 'inferred' | 'confirmed', required
      - `source` string, required
      - `use` 'search' | 'verification', required
      - `applied` boolean, required: Whether this fact acts on the search now.
    - `questions` object[], required
      - `id` string, required
      - `question` string, required
      - `options` string[], required
      - `default` string: What applies when the question is skipped; absent only when nothing can stand in.
    - `segments` object[], required
      - `id` string, required
      - `name` string, required
      - `confidence` 'high' | 'medium' | 'low', required
      - `kinds` string[], required
      - `every_industry` true
      - `example_kind` string
      - `places` string[], required
      - `groups` object[], required
        - `id` string, required
        - `name` string, required
        - `titles` string[]
      - `evidence` object[], required
        - `source` string, required
        - `quote` string, required
      - `offered` object
        - `roles` string[]
        - `kinds` string[]
        - `places` string[]
    - `searches` object[], required
      - `id` string, required
      - `segment` string, required
      - `language` string, required
      - `where` string, required
      - `queries` string[], required
    - `people_up_to` integer, required
    - `cost_estimate_credits` integer, required: The most the run may spend; it never spends more.
    - `cost_likely_credits` integer, required: What the run usually spends when the market holds the people.
    - `held_back` object: Searches and query lines kept out of the plan to fit its bounds or the pool, ready to add.
      - `searches` integer, required
      - `queries` integer, required
    - `unread` object[]
      - `url` string, required
      - `why` string, required
    - `next` string, required
  - object
    - `reason` string, required
    - `searches` object[], required
      - `id` string, required
      - `segment` string, required
      - `language` string, required
      - `where` string, required
      - `queries` string[], required
    - `unread` object[]
      - `url` string, required
      - `why` string, required
    - `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, 11 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`
  - …40 more
- **2026-10-22** `bdaed6984b20`: 1 warning
  - removed the optional property `anyOf[subschema #2]/credits_left` from the response with the `200` status
- **2026-10-16** `a797d757efbd`: 4 info
  - added the new optional request property `edits`
  - the request property `context` became optional
  - added `subschema #1, subschema #2` to the response body `anyOf` list for the response status `200`
  - removed `subschema #1, subschema #2` from the response body `anyOf` list for the response status `200`
- **2026-10-15** `cfc6b64415d2`: 2 info
  - added `subschema #1, subschema #2` to the response body `anyOf` list for the response status `200`
  - removed `subschema #1, subschema #2` from the response body `anyOf` list for the response status `200`
- **2026-10-03** `e8a9550eb535`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/berea/apis/bereach-api/changes/public/plan-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)
