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

# How it works

> Workspaces, projects, sources, destinations, events and deliveries.

## The parts

```mermaid theme={null}
flowchart LR
  A[Paystack webhook] --> S1[Webhook source]
  B[Gmail inbox] --> S2[Gmail source]
  C[JSON API] --> S3[Watch a URL source]
  S1 --> P((Project))
  S2 --> P
  S3 --> P
  P --> D1[Destination: ledger]
  P --> D2[Destination: CRM]
  P --> D3[Destination: your agent]
```

| Part            | What it is                                                                     |
| --------------- | ------------------------------------------------------------------------------ |
| **Workspace**   | Your team, your projects, your API keys and one bill.                          |
| **Project**     | A group of sources, destinations and events. Each project is Free or Pro.      |
| **Source**      | Where events come from: a webhook URL, WhatsApp, a mailbox or a watched URL.   |
| **Destination** | An HTTPS URL that gets events. It can filter, transform, add headers and sign. |
| **Event**       | One thing that happened: one webhook, one email or one change.                 |
| **Delivery**    | One event sent to one destination. It has its own attempts.                    |

## The life of an event

<Steps>
  <Step title="Receive">
    A push source gets an HTTP request. A mail or polled source finds new data. hooksnode checks the signature (if set), the rate limit and your credits.
  </Step>

  <Step title="Save">
    hooksnode writes the event to the database before it queues anything. If the server stops after the write, a job finds the event and queues it again.
  </Step>

  <Step title="Fan out">
    hooksnode makes one delivery for each active destination that takes events from this source. Each delivery has its own queue, so a slow destination does not stop the others.
  </Step>

  <Step title="Prepare">
    For each delivery, hooksnode applies the destination's transform, then its filter, then its extra headers. Then it adds the signature.
  </Step>

  <Step title="Deliver">
    hooksnode sends the request. A `2xx` response is a success. Any other result is a failed attempt. hooksnode tries again with backoff, up to 25 attempts.
  </Step>
</Steps>

## Event statuses

| Status      | Meaning                                                                                                                    |
| ----------- | -------------------------------------------------------------------------------------------------------------------------- |
| `received`  | Saved. Not queued yet.                                                                                                     |
| `queued`    | Deliveries are queued.                                                                                                     |
| `delivered` | At least one destination got the event.                                                                                    |
| `failed`    | No destination got the event.                                                                                              |
| `buffered`  | A Pro project had no destination for this source. The event waits for you. See [Replay](/delivery/replay#buffered-events). |

## Delivery statuses

| Status      | Meaning                                                      |
| ----------- | ------------------------------------------------------------ |
| `pending`   | The attempt is in progress.                                  |
| `delivered` | The destination answered `2xx`, or the filter did not match. |
| `failed`    | The attempt failed. hooksnode will try again.                |
| `dead`      | All attempts failed. Use retry to send it again.             |

<Note>
  A filtered delivery shows as `delivered` with status code `0` and the response `{"filtered":true}`.
</Note>

## Delivery guarantee

hooksnode delivers **at least once**. A destination can get the same event more than once, for example when it times out after it did the work. Make your endpoints idempotent. See [Idempotency](/delivery/idempotency).
