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

# Delivery: email and webhooks

> Send matches where they're needed — email senders, recipients, templates, and signed webhooks.

# Delivery: email and webhooks

Delivery settings decide **where DarknetSearch sends what it finds** — email, a webhook, or both. They're org-level resources you configure once, up front, then reference by `id` wherever delivery is needed (today, that's [monitoring rules](https://github.com/kaduu-cti/darknetsearch-docs/blob/main/api/guides/monitoring-rules/README.md), which send each new match to them). Email uses three pieces — a **sender** (the SMTP account it's sent from), **recipients** (the addresses it goes to), and a **template** (subject and body). A webhook is a single signed HTTP `POST`.

Two rules apply across all four resource types: each organization has **exactly one default** of each (setting a new default unsets the old one), and **a resource can't be deleted while a rule references it** — detach or delete those rules first.

#### Recipients

A recipient is just an address. List with [`alert_system_setting_get_recipient_list`](https://client-api.leak.center/scalar-docs/#tag/alert-system/GET/service/alert_system_setting_get_recipient_list/), create with [`alert_system_setting_create_recipient`](https://client-api.leak.center/scalar-docs/#tag/alert-system/POST/service/alert_system_setting_create_recipient/), delete with [`alert_system_setting_delete_recipient`](https://client-api.leak.center/scalar-docs/#tag/alert-system/DELETE/service/alert_system_setting_delete_recipient/\{id}/).

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/alert_system_setting_create_recipient/ \
  -X POST -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" \
  -d '{ "email": "soc@acme.com", "is_default": false }'
```

Fields: `email`, `is_default`. Up to **10 recipients** per organization.

#### Senders

A sender is the SMTP account matches are sent *from*. List with [`alert_system_setting_get_sender_list`](https://client-api.leak.center/scalar-docs/#tag/alert-system/GET/service/alert_system_setting_get_sender_list/), create with [`alert_system_setting_create_sender`](https://client-api.leak.center/scalar-docs/#tag/alert-system/POST/service/alert_system_setting_create_sender/), delete with [`alert_system_setting_delete_sender`](https://client-api.leak.center/scalar-docs/#tag/alert-system/DELETE/service/alert_system_setting_delete_sender/\{id}/).

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/alert_system_setting_create_sender/ \
  -X POST -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" \
  -d '{
        "email": "alerts@acme.com",
        "server_host": "smtp.acme.com",
        "port": 587,
        "username": "alerts@acme.com",
        "password": "YOUR_SMTP_PASSWORD",
        "encryption_method": "TLS",
        "authentication_required": true,
        "is_default": true
      }'
```

| Field                             | Notes                                                             |
| --------------------------------- | ----------------------------------------------------------------- |
| `email`                           | The "from" address.                                               |
| `server_host`                     | SMTP host.                                                        |
| `port`, `username`, `password`    | **Write-only** — accepted on create, never returned in responses. |
| `encryption_method`               | `SSL` or `TLS`.                                                   |
| `authentication_required`         | Whether to log in with `username`/`password` (default `true`).    |
| `is_default`, `is_system_created` | `is_system_created` is read-only and cannot be deleted.           |

Up to **10 senders** per organization. Send a test before you rely on one with [`alert_system_setting_test_email`](https://client-api.leak.center/scalar-docs/#tag/alert-system/POST/service/alert_system_setting_test_email/) — `POST {"sender_id": 8, "recipient": "soc@acme.com"}`; it returns `202` and sends asynchronously.

\*\*\`encryption\_method\` only acts on \`TLS\`.\*\* A \`TLS\` sender issues \`STARTTLS\` before authenticating; an \`SSL\` sender currently connects in plaintext (no implicit TLS wrapper). Use \`TLS\` for an encrypted connection.

#### Email templates

A template is the subject and HTML body of the email. List with [`alert_system_setting_get_template_list`](https://client-api.leak.center/scalar-docs/#tag/alert-system/GET/service/alert_system_setting_get_template_list/), create with [`alert_system_setting_create_template`](https://client-api.leak.center/scalar-docs/#tag/alert-system/POST/service/alert_system_setting_create_template/), edit with [`alert_system_setting_update_template`](https://client-api.leak.center/scalar-docs/#tag/alert-system/PUT/service/alert_system_setting_update_template/\{id}/), delete with [`alert_system_setting_delete_template`](https://client-api.leak.center/scalar-docs/#tag/alert-system/DELETE/service/alert_system_setting_delete_template/\{id}/).

Fields: `name`, `subject`, `body` (HTML), `is_default`. The `body` **must** contain these placeholders, or create/update is rejected:

`{current_date}` · `{alert_rule_name}` · `{number_of_hits}` · `{service}` · `{match_detail_link}`

At send time those are substituted in both subject and body, along with two optional extras — `{total_results}` (all hits) and `{excluded_count}`. `{number_of_hits}` is the non-excluded count, and `{match_detail_link}` links straight to the incident in the dashboard.

#### Webhooks

A webhook delivers each match as one HTTP `POST`. List with [`alert_system_setting_get_webhook_list`](https://client-api.leak.center/scalar-docs/#tag/alert-system/GET/service/alert_system_setting_get_webhook_list/), create with [`alert_system_setting_create_webhook`](https://client-api.leak.center/scalar-docs/#tag/alert-system/POST/service/alert_system_setting_create_webhook/), edit with [`alert_system_setting_update_webhook`](https://client-api.leak.center/scalar-docs/#tag/alert-system/PUT/service/alert_system_setting_update_webhook/\{id}/), delete with [`alert_system_setting_delete_webhook`](https://client-api.leak.center/scalar-docs/#tag/alert-system/DELETE/service/alert_system_setting_delete_webhook/\{id}/).

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/alert_system_setting_create_webhook/ \
  -X POST -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" \
  -d '{ "name": "Acme SIEM", "url": "https://hooks.acme.example/darknetsearch", "headers": {}, "is_default": false }'
```

Fields: `name`, `url` (≤2048 chars), `headers` (a JSON object sent on every delivery), `is_default`, and a read-only `secret`. Up to **10 webhooks** per organization. The `secret` is **server-generated and read-only** — any value you send is ignored, and the response carries the real one. To rotate it, delete and recreate the webhook.

**The payload.** The body is compact JSON, delivered with a 30-second timeout and no retry (any `2xx` is treated as success):

```json theme={"dark"}
{
  "alert_rule_name": "Acme brand monitoring",
  "service": "Phishing",
  "total_matches": 15,
  "excluded_matches": 2,
  "results_url": "https://dashboard.darknetsearch.com/alerts/incidents/123/results",
  "timestamp": "2026-06-22T12:00:00.000000+00:00"
}
```

The shape adapts to the destination URL — Slack (`hooks.slack.com`), Discord (`discord.com/api/webhooks`), and Microsoft Teams (`webhook.office.com`/`outlook.office.com`) get their native message formats; every other URL gets the generic payload above. It carries the rule, the source, the match counts, and a link — not the hits themselves; fetch those from [the match](https://github.com/kaduu-cti/darknetsearch-docs/blob/main/api/guides/monitoring-matches/README.md).

**The signature.** When the webhook has a secret, every request carries `X-AlertSystem-Signature: sha256=<hex>`, an HMAC-SHA256 of the **raw request body** keyed with your secret. Verify it: strip the `sha256=` prefix, recompute the HMAC over the exact bytes you received, and compare in constant time. Reject mismatches; return a `2xx` to acknowledge. Two custom headers are always present too: `Content-Type: application/json` and `User-Agent: AlertSystem/1.0`.
