---
title: "Find people to contact because something just happened at their company"
method: POST
path: "/public/signals"
tags: ["public"]
---

# Find people to contact because something just happened at their company

`POST /public/signals`

## Request

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

Two steps from public data. mode events returns dated events (a raise, an appointment, a job opening) for a description of the event, each with its title, date, source page and an id. mode resolve takes companies read in those events, each with a role to reach or the person the event names, and returns the company's LinkedIn page and the people found, each with their profile and the event. A company whose page is not found returns nobody. Events and people already returned never come back; an events ask with includeText keeps its own record, so it can return an event a wider ask already gave. The people found are saved to the list unless save is skip. Each event carries its date; the people come from our index, about 3 weeks old at the median, so a recent job move can be missing. Cost: each search costs by the results it brings back: 4 credits for up to 10, 11 for 25, 49 for 100; in mode resolve, each company costs its searches plus 1 credit for every 2 profiles read, and nothing when nobody comes back. creditsUsed says what the call spent.

## Request body

- object
  - `mode` 'events' | 'resolve', required: events finds dated events; resolve turns companies read in those events into people, each with their company's page.
  - `description` string: events: the event as a headline or a job posting would state it.
  - `kind` 'news' | 'any': events: news for raises and appointments; any for every kind of page, job postings included.
  - `since` string: events: only events published on or after this date, as YYYY-MM-DD. Omitted, the last 30 days.
  - `includeText` string: events: a phrase of at most five words every page must contain, other than the words of description.
  - `limit` integer: events: how many events to return.
  - `items` object[]: resolve: the companies to turn into people, each with a role to reach there or the person the event names.
    - `event` string: The id of the event this company was read in, as events returned it.
    - `company` string, required: The company as the event names it.
    - `role` string: A role to reach at the company, written the way people write it on their own profile.
    - `person` string: The full name of the person the event names. Looked up by name alone: their profile can still show their previous employer. With a role too, when no profile under the name shows the company, the people who state that role there now come after them.
    - `place` string: Where the company is, a country or a city.
  - `save` 'keep' | 'skip': resolve: keep (the default) saves the people found into the list; skip only when they are a step toward something else.

## Response `200`

Dated events, or the people they lead to

- object
  - `source` 'public', required
  - `creditsUsed` integer, required: Credits this call spent, net of anything given back. 0 when nothing was charged: a free read, a cached answer, nothing delivered.
  - `mode` 'events' | 'resolve', required
  - `events` object[]: events: dated events not returned before, each with an id to pass to resolve.
    - `id` string, required
    - `title` string, nullable, required
    - `date` string, nullable, required: When the event was published, YYYY-MM-DD. Null when it is not known.
    - `url` string, required: The source page.
    - `text` string, nullable, required: The opening of the source page.
  - `alreadyReturned` integer: events: events this search found again that were already returned, left out. Normal bookkeeping, never a failure.
  - `items` object[]: resolve: per company, its page and the people found, not returned before.
    - `event` object, nullable, required: The event this company was read in, as it was returned. Null when no known event id was given.
      - `id` string, required
      - `title` string, nullable, required
      - `date` string, nullable, required: When the event was published, YYYY-MM-DD. Null when it is not known.
      - `url` string, required: The source page.
    - `company` string, required
    - `companyPage` string, nullable, required: The company's LinkedIn page. Null when none was found, and then nobody is returned for this company.
    - `people` object[], required
      - `name` string, nullable, required
      - `headline` string, nullable, required
      - `currentTitle` string, nullable, required: Their job at the company when their profile states one, else their current job.
      - `location` string, nullable, required
      - `profileUrl` string, required
      - `imageUrl` string, nullable, required
      - `companyOnProfile` 'now' | 'before' | 'no', required: Whether their own profile names the company now, before, or not yet: a profile can lag the news by weeks.
      - `contactId` string
      - `avatarUrl` string
    - `note` string: Why nobody came back for this company, or what the people shown are when that needs saying. Relay it.
  - `saved` integer, nullable: resolve: how many people this call wrote to the contact list. Null when that write failed.
  - `pooled` integer: resolve: how many were linked into the list.
  - `note` string: events: present when no new event was found, and says why. Relay it.

## 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** `55b30b093819`: 1 info
  - added the new optional request property `includeText`
- **2026-10-21** `d04cdb8563c3`: 1 info
  - endpoint added

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