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

# Digest and Batched Notifications

> Batch and summarize notifications with Novu digest steps. Send digests like "10 new comments" instead of individual alerts, with configurable windows and keys.

Batch related notifications into a single digest message using Novu's digest step. Instead of sending one notification per event, Novu collects events over a time window and delivers a summarized message such as "10 people liked your post."

## How does digest work in Novu?

Add a [digest step](/platform/workflow/add-and-configure-steps/configure-action-steps/digest) to your workflow before the channel step. Novu collects events that match the digest key within the configured window, then renders a single notification with aggregated content.

Typical digest settings:

* **Window:** 5 minutes, 1 hour, or 24 hours depending on urgency
* **Digest key:** A field such as `payload.postId` to group events
* **Template:** Use digest variables to list aggregated items

## When should I use digest notifications?

| Scenario        | Digest window | Example message                |
| --------------- | ------------- | ------------------------------ |
| Social activity | 1–24 hours    | "10 people liked your post"    |
| Weekly summary  | 7 days        | "Your weekly activity report"  |
| Comment threads | 15–60 minutes | "5 new replies on your thread" |

## How do I trigger events for digest workflows?

Trigger the same workflow for each individual event. Novu handles batching automatically based on the digest step configuration and digest key.

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    import { Novu } from '@novu/api';

    const novu = new Novu({ secretKey: process.env.NOVU_SECRET_KEY });

    await novu.trigger({
      workflowId: 'post-liked',
      to: { subscriberId: 'user_123' },
      payload: { postId: 'post_456', likerName: 'Alex' },
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os
    import novu_py
    from novu_py import Novu

    with Novu(secret_key=os.getenv("NOVU_SECRET_KEY", "")) as novu:
        novu.trigger(trigger_event_request_dto=novu_py.TriggerEventRequestDto(
            workflow_id="post-liked",
            to={"subscriber_id": "user_123"},
            payload={"postId": "post_456", "likerName": "Alex"},
        ))
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    import (
        "context"
        "os"

        novugo "github.com/novuhq/novu-go"
        "github.com/novuhq/novu-go/models/components"
    )

    s := novugo.New(novugo.WithSecurity(os.Getenv("NOVU_SECRET_KEY")))

    _, err := s.Trigger(context.Background(), components.TriggerEventRequestDto{
        WorkflowID: "post-liked",
        To: components.CreateToSubscriberPayloadDto(components.SubscriberPayloadDto{
            SubscriberID: "user_123",
        }),
        Payload: map[string]any{
            "postId":    "post_456",
            "likerName": "Alex",
        },
    }, nil)
    ```
  </Tab>

  <Tab title="PHP">
    ```php theme={null}
    use novu;
    use novu\Models\Components;

    $sdk = novu\Novu::builder()
        ->setSecurity('<YOUR_SECRET_KEY_HERE>')
        ->build();

    $sdk->trigger(
        triggerEventRequestDto: new Components\TriggerEventRequestDto(
            workflowId: 'post-liked',
            to: new Components\SubscriberPayloadDto(subscriberId: 'user_123'),
            payload: [
                'postId' => 'post_456',
                'likerName' => 'Alex',
            ],
        ),
    );
    ```
  </Tab>

  <Tab title=".NET">
    ```csharp theme={null}
    using Novu;
    using Novu.Models.Components;
    using System.Collections.Generic;

    var sdk = new NovuSDK(secretKey: "<YOUR_SECRET_KEY_HERE>");

    await sdk.TriggerAsync(triggerEventRequestDto: new TriggerEventRequestDto() {
        WorkflowId = "post-liked",
        To = To.CreateSubscriberPayloadDto(new SubscriberPayloadDto() {
            SubscriberId = "user_123",
        }),
        Payload = new Dictionary<string, object>() {
            { "postId", "post_456" },
            { "likerName", "Alex" },
        },
    });
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import co.novu.Novu;
    import co.novu.models.components.*;
    import java.util.Map;

    Novu novu = Novu.builder()
        .secretKey("<YOUR_SECRET_KEY_HERE>")
        .build();

    novu.trigger()
        .body(TriggerEventRequestDto.builder()
            .workflowId("post-liked")
            .to(To2.of(SubscriberPayloadDto.builder()
                .subscriberId("user_123")
                .build()))
            .payload(Map.ofEntries(
                Map.entry("postId", "post_456"),
                Map.entry("likerName", "Alex")))
            .build())
        .call();
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST 'https://api.novu.co/v1/events/trigger' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: ApiKey <NOVU_SECRET_KEY>' \
    -d '{
      "name": "post-liked",
      "to": { "subscriberId": "user_123" },
      "payload": { "postId": "post_456", "likerName": "Alex" }
    }'
    ```
  </Tab>
</Tabs>

## Related guides

* [Digest step configuration](/platform/workflow/add-and-configure-steps/configure-action-steps/digest)
* [Framework digest channel](/framework/digest)
* [Throttle step](/platform/workflow/add-and-configure-steps/configure-action-steps/throttle)

## Frequently asked questions

<AccordionGroup>
  <Accordion title="What is the difference between digest and throttle?">
    Digest batches multiple events into one summarized notification. Throttle limits how often a subscriber receives notifications for the same workflow within a time window.
  </Accordion>

  <Accordion title="Can I send digests across multiple channels?">
    Yes. Place digest before multiple channel steps (for example, in-app and email) so all channels receive the batched summary.
  </Accordion>
</AccordionGroup>
