# `Tayori.Webhooks`
[🔗](https://github.com/hattoriai/tayori/blob/v0.1.0/lib/tayori/webhooks.ex#L1)

Tells other places of each entry when it is published: the `:webhooks`
feature. The admin adds them in Settings:

  * a webhook - a POST of the entry as JSON, signed with its secret
    (`x-tayori-signature: sha256=<hex HMAC of the body>`);
  * Slack - a message to an incoming webhook URL;
  * Discord - a message to a channel webhook URL.

Their URLs and secrets are kept encrypted, as the AI key is (a `:vault`
or the `:secret_key_base` of `Tayori.Config`). A failed delivery is
tried again (`Tayori.Jobs`), unless the place refused it for good.

A webhook gets every entry, for everyone or not; Slack and Discord get
the entries for everyone, which are public.

# `hook`

```elixir
@type hook() :: %{required(String.t()) =&gt; String.t()}
```

A place told of the entries.

# `add`

```elixir
@spec add(String.t(), String.t(), String.t(), String.t() | nil) ::
  {:ok, String.t() | nil} | {:error, atom()}
```

Adds a place: a kind, a name, an https URL and, for a webhook, a secret
to sign with (one is made when none is given). Returns the secret.

# `kinds`

```elixir
@spec kinds() :: [String.t()]
```

The kinds of places.

# `list`

```elixir
@spec list() :: [map()]
```

The places, without their secrets: `%{"id", "kind", "name", "host"}`,
where `host` shows where it goes without the secret part of the URL.

# `remove`

```elixir
@spec remove(String.t()) :: :ok
```

Removes a place.

# `test`

```elixir
@spec test(String.t()) :: :ok | {:error, term()}
```

Sends a test message to a place, and returns how it went.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
