Back to Novu

Push Webhook Push Integration with Novu

docs/platform/integrations/push/push-webhook.mdx

3.18.012.4 KB
Original Source

This guide walks you through the entire process of configuring and using Push Webhook with Novu.

The Push Webhook provider is different from other push providers because it does not depend on a third-party service. Instead, Novu sends push notifications directly to a webhook URL that you control. This approach is ideal if you want full control over how notifications are processed, routed, or stored in your system.

Configure Push Webhook with Novu

To configure Push Webhook, you must provide an endpoint URL for Novu to call and a secret HMAC key to verify the request's authenticity.

Step 1: Get your webhook URL and secret key

Before connecting to Novu, you need two things:

  • Webhook URL: This is your own API endpoint that will receive the POST request from Novu. For quick testing, you can use a service like webhook.site.
  • Secret HMAC Key: This is a self-generated secret string. Novu will use it to encrypt the payload using the HMAC SHA256 algorithm and send the hash in the x-novu-signature header. This lets you verify that the request is genuinely from Novu. See how to generate a HMAC key.
<Note> Your webhook URL endpoint must be able to accept `POST` requests. </Note>

Step 2: Connect Push Webhook to Novu

Next, add these keys to your Push Webhook integration in the Novu dashboard:

<Steps> <Step title="Log in to the Novu dashboard"> Open the [Novu Dashboard](https://dashboard.novu.co). </Step> <Step title="Open Integration Store"> On the Novu dashboard, navigate to the **Integration Store**. </Step> <Step title="Connect a provider"> In the **Integration Store**, click **Connect provider** to begin setup. </Step> <Step title="Select Push Webhook"> In the **Push** tab, choose **Push Webhook** from the provider list. </Step> <Step title="Fill in integration fields"> * **Webhook URL:** The endpoint URL that you prepared in Step 1. * **Secret HMAC Key:** The secret key used to sign webhook calls. ![Push Webhook Integration in Novu](/images/channels-and-providers/push/push-webhook/push-webhook-integration.png) </Step> <Step title="Create the integration"> Review your credentials, then click **Create Integration** to save. </Step> </Steps>

Using Push Webhook with Novu

Once configured, you must register a device token for your subscriber and trigger a workflow.

Step 1: Add subscriber device token

This step is mandatory. Unlike other push providers that generate a unique token, for the Push Webhook, you must provide your own identifier.

Any random string can be used as a device token. This token is included in the webhook payload sent to your endpoint, allowing you to identify which user or device the notification is for.

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

const novu = new Novu({ secretKey: "<NOVU_SECRET_KEY>" });

await novu.subscribers.credentials.update( { providerId: ChatOrPushProviderEnum.PushWebhook, integrationIdentifier: "push-webhook-MnGLxp8uy", credentials: { deviceTokens: ["token1", "token2", "token3"] }, }, "subscriberId" );

  </Tab>
  <Tab title="Python">
```python
import os
import novu_py
from novu_py import Novu

with Novu(secret_key=os.getenv("NOVU_SECRET_KEY", "")) as novu:
    novu.subscribers.credentials.update(
        subscriber_id="subscriberId",
        update_subscriber_channel_request_dto={
            "provider_id": novu_py.ChatOrPushProviderEnum.PUSHWEBHOOK,
            "credentials": {"deviceTokens": ["token1", "token2", "token3"]},
            "integration_identifier": "push-webhook-MnGLxp8uy",
        },
    )
</Tab> <Tab title="Go"> ```go 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")))

res, err := s.Subscribers.Credentials.Update(context.Background(), "subscriberId", components.UpdateSubscriberChannelRequestDto{ ProviderID: components.ChatOrPushProviderEnumPushWebhook, IntegrationIdentifier: novugo.String("push-webhook-MnGLxp8uy"), Credentials: components.ChannelCredentials{ DeviceTokens: []string{"token1", "token2", "token3"}, }, }, nil)

  </Tab>
  <Tab title="PHP">
```php
use novu;
use novu\Models\Components;

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

$sdk->subscribersCredentials->update(
    subscriberId: 'subscriberId',
    updateSubscriberChannelRequestDto: new Components\UpdateSubscriberChannelRequestDto(
        providerId: Components\ChatOrPushProviderEnum::PushWebhook,
        integrationIdentifier: 'push-webhook-MnGLxp8uy',
        credentials: new Components\ChannelCredentials(
            deviceTokens: ['token1', 'token2', 'token3'],
        ),
    ),
);
</Tab> <Tab title=".NET"> ```csharp using Novu; using Novu.Models.Components; using System.Collections.Generic;

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

await sdk.Subscribers.Credentials.UpdateAsync( subscriberId: "subscriberId", updateSubscriberChannelRequestDto: new UpdateSubscriberChannelRequestDto() { ProviderId = ChatOrPushProviderEnum.PushWebhook, IntegrationIdentifier = "push-webhook-MnGLxp8uy", Credentials = new ChannelCredentials() { DeviceTokens = new List<string> { "token1", "token2", "token3" }, }, });

  </Tab>
  <Tab title="Java">
```java
import co.novu.Novu;
import co.novu.models.components.*;
import java.util.List;

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

novu.subscribers().credentials().update()
    .subscriberId("subscriberId")
    .body(UpdateSubscriberChannelRequestDto.builder()
        .providerId(ChatOrPushProviderEnum.PUSHWEBHOOK)
            .integrationIdentifier("push-webhook-MnGLxp8uy")
        .credentials(ChannelCredentials.builder()
            .deviceTokens(List.of("token1", "token2", "token3"))
            .build())
        .build())
    .call();
</Tab> <Tab title="cURL"> ```bash curl -L -X PUT 'https://api.novu.co/v1/subscribers/<SUBSCRIBER_ID>/credentials' \ -H 'Content-Type: application/json' \ -H 'Authorization: ApiKey <NOVU_SECRET_KEY>' \ -d '{ "providerId": "push-webhook", "credentials": { "deviceTokens": [ "token1", "token2", "token3" ] }, "integrationIdentifier": "push-webhook-MnGLxp8uy" }' ``` </Tab> </Tabs>

Step 2: Send a notification

Now you're ready to send a push notification. Create a workflow with a Push step and trigger it. Novu sends the notification payload to the webhook URL that you configured.

The example below demonstrates a simple trigger using Novu’s SDK.

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

const novu = new Novu({ secretKey: "<NOVU_SECRET_KEY>" });

await novu.trigger({ workflowId: "workflowId", to: { subscriberId: "SUBSCRIBER_ID", }, payload: { "custom_message": "This is custom message from payload." }, });

  </Tab>
  <Tab title="Python">
```python
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="workflowId",
        to={"subscriber_id": "SUBSCRIBER_ID"},
        payload={
        "custom_message": "This is custom message from payload."
},
    ))
</Tab> <Tab title="Go"> ```go 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")))

res, err := s.Trigger(context.Background(), components.TriggerEventRequestDto{ WorkflowID: "workflowId", To: components.CreateToSubscriberPayloadDto(components.SubscriberPayloadDto{ SubscriberID: "SUBSCRIBER_ID", }), Payload: map[string]any{ "custom_message": "This is custom message from payload." }, }, nil)

  </Tab>
  <Tab title="PHP">
```php
use novu;
use novu\Models\Components;

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

$sdk->trigger(
    triggerEventRequestDto: new Components\TriggerEventRequestDto(
        workflowId: 'workflowId',
        to: new Components\SubscriberPayloadDto(subscriberId: 'SUBSCRIBER_ID'),
        payload: {
        "custom_message": "This is custom message from payload."
},
    ),
);
</Tab> <Tab title=".NET"> ```csharp using Novu; using Novu.Models.Components;

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

await sdk.TriggerAsync(triggerEventRequestDto: new TriggerEventRequestDto() { WorkflowId = "workflowId", To = To.CreateSubscriberPayloadDto(new SubscriberPayloadDto() { SubscriberId = "SUBSCRIBER_ID" }), Payload = { "custom_message": "This is custom message from payload." }, });

  </Tab>
  <Tab title="Java">
```java
import co.novu.Novu;
import co.novu.models.components.*;

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

novu.trigger()
    .body(TriggerEventRequestDto.builder()
        .workflowId("workflowId")
        .to(To2.of(SubscriberPayloadDto.builder().subscriberId("SUBSCRIBER_ID").build()))
        .payload({
        "custom_message": "This is custom message from payload."
})
        .build())
    .call();
</Tab> <Tab title="cURL"> ```bash curl --location 'https://api.novu.co/v1/events/trigger' \ --header 'Content-Type: application/json' \ --header 'Authorization: ApiKey <NOVU_SECRET_KEY>' \ -d '{ "name": "workflowId", "to": [ "SUBSCRIBER_ID" ], "payload": { "custom_message": "This is custom message from payload." } }' ``` </Tab> </Tabs>

Payload sent by Novu to webhook URL

When you trigger a workflow, Novu sends a POST request to your webhook URL with a JSON body similar to the one below.

The payload includes:

  • The title and content from your workflow editor.
  • The target (the device token you set).
  • Your overrides.
  • The full payload from your trigger.
  • The subscriber's profile.
json
{
  "target": ["subscriber-token-for-push-webhook-provider"],
  "title": "Push Webhook message title",
  "content": "push Webhook content body",
  "overrides": {
    "data": {
      "custom_message": "this is custom message from payload push webhook demo"
    }
  },
  "payload": {
    "custom_message": "this is custom message from payload push webhook demo",
    "__source": "test-workflow",
    "subscriber": {
      // subscriber fields
      "_id": "65c0d71c0959a38e8857b131",
      "_organizationId": "organizationId",
      "_environmentId": "environmentId",
      "firstName": "Pawan",
      "lastName": "Jain",
      "phone": "+123456789",
      "subscriberId": "push-webhook-demo-subscriber-id",
      "email": "[email protected]",
      "channels": [
        {
          "credentials": {
            "deviceTokens": ["subscriber-token-for-push-webhook-provider"]
          },
          "_integrationId": "integrationId",
          "providerId": "push-webhook"
        }
      ],
      "data": {
        // custom data field of subscriber
        "isDeveloper": "true"
      },
      "deleted": false,
      "createdAt": "2024-02-05T12:39:56.379Z",
      "updatedAt": "2024-02-05T12:54:08.684Z",
      "__v": 0,
      "id": "65c0d71c0959a38e8857b131"
    },
    "step": {
      // digest variables
      "digest": false,
      "events": [],
      "total_count": 0
    }
  }
}

Checking authenticity

If you provided a secret HMAC key during configuration, then Novu will include a x-novu-signature header in the request. You can use this header to verify that the request is from Novu and not a malicious third party.

Here is an example of how to validate the hash:

typescript
import crypto from 'crypto';

// secret key added in step 3
const secretKey = 'YOUR_HMAC_SECRET_KEY';

// function to handle webhook url route request
async function acceptNovuPushWebHookRequest(request, response) {
  const payloadSentByNovu = request.body;
  const hmacHashSentByNovu = request.headers['x-novu-signature'];

const actualHashValue = crypto
    .createHmac('sha256', secretKey)
    .update(payloadSentByNovu, 'utf-8')
    .digest('hex');

if (hmacHashSentByNovu === actualHashValue) {
    // handle the notification
    console.log('Request sent by Novu');
  } else {
    throw new Error('Not a valid request');
  }
}