> ## Documentation Index
> Fetch the complete documentation index at: https://docs.freshtalent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Send test digest

> Replay a recent live signal digest to the organization's configured email and Slack destinations.

Selects one random person with matching live diffs from the recent Monitoring result set and sends a digest to the configured destinations. The digest can contain multiple matching changes for that person. This endpoint performs real delivery side effects; it is not a dry run. It looks back up to 30 days and considers up to 80 Monitoring rows, then chooses one matching row. Demo diffs are excluded.

## Request body

The body is optional. Send `{}` or omit the body.

<ParamField body="emails" type="string[]">
  Optional extra email recipients for this send. String entries containing `@` are accepted, trimmed, lowercased, and deduplicated with organization member and saved preference addresses. No endpoint-specific maximum is defined in the Gateway route. Invalid array items are ignored.
</ParamField>

The saved notification preferences still control whether email or Slack is attempted. An extra email does not force email on when `email_enabled` is false.

## Response

```json 200 theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "data": {
    "person": "Derek Morrow",
    "email": "sent",
    "slack": "disabled"
  }
}
```

`person`, `email`, and `slack` are strings. `email` can be `sent`, `disabled`, `skipped-no-recipients`, or `skipped-no-api-key`. `slack` can be `sent`, `disabled`, `not_connected`, or `skipped-no-channel`.

A `200` with `skipped-*` does not mean a message was delivered. `sent` means the downstream send call accepted the message; it is not a provider delivery guarantee.

## Actual delivery and retry safety

* If email is enabled, the Gateway resolves organization member addresses plus saved preference addresses and any `emails` in this request, then calls the configured email provider. No recipients produces `skipped-no-recipients`; a missing email-provider API key produces `skipped-no-api-key`.
* If Slack is enabled, the Gateway posts to the installed workspace's selected channel. No installation produces `not_connected`; an installation without a selected channel produces `skipped-no-channel`.
* Repeating this `POST` can send another email or Slack message. There is no idempotency key and no test-specific rate limit in the Gateway route. Do not automatically retry after a timeout or uncertain `5xx`; first check the destinations and provider logs, because the first send may already have happened.
* The shared Gateway limit is 300 requests per minute per client IP. Honor `Retry-After` on `429`; this limit does not prevent the downstream provider or Slack from applying its own limits.

## Errors

| Status | Meaning                                        | Recovery                                                                                    |
| ------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `400`  | Invalid platform-org scoping header            | Correct `X-FreshTalent-Org-Id`, or omit it for a customer key.                              |
| `401`  | Missing, malformed, or revoked API key         | Supply a valid key.                                                                         |
| `404`  | No recent live signal matches the saved fields | Configure fields/destinations if needed, then try again when a matching live signal exists. |
| `429`  | Shared Gateway limit exceeded                  | Honor `Retry-After`; do not replay blindly if a delivery may have occurred.                 |
| `5xx`  | Gateway or downstream failure                  | Reconcile email/Slack provider state before any retry.                                      |

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --fail-with-body --max-time 30 -X POST "https://api.freshtalent.ai/v1/signals/test" \
    -H "Authorization: Bearer $FRESHTALENT_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"emails":["qa@example.com"]}'
  ```

  ```js JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch("https://api.freshtalent.ai/v1/signals/test", {
    method: "POST",
    signal: AbortSignal.timeout(30_000),
    headers: {
      Authorization: `Bearer ${process.env.FRESHTALENT_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ emails: ["qa@example.com"] }),
  });
  if (!response.ok) throw new Error(`FreshTalent HTTP ${response.status}`);
  const result = (await response.json()).data;
  console.log(result.person, result.email, result.slack);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import json
  import os
  from urllib.request import Request, urlopen

  request = Request(
      "https://api.freshtalent.ai/v1/signals/test",
      data=json.dumps({"emails": ["qa@example.com"]}).encode(),
      method="POST",
      headers={
          "Authorization": "Bearer " + os.environ["FRESHTALENT_API_KEY"],
          "Content-Type": "application/json",
      },
  )
  with urlopen(request, timeout=30) as response:
      result = json.load(response)["data"]
  print(result["person"], result["email"], result["slack"])
  ```
</RequestExample>

## Related

* [Get notification preferences](/api-reference/signals/get-preferences)
* [Update notification preferences](/api-reference/signals/update-preferences)
* [Get account](/api-reference/account/me)
* [List events](/api-reference/events/list)
