Receiving Messages and User Events

When your webhook receives inbound messages, user events, form submissions, or campaign status updates from Pinnacle, the raw request body lacks type information. The process method validates incoming events by checking the signing secret and transforms the request into a fully typed MessageEvent, UserEvent, FormSubmissionEvent, or CampaignStatusEvent object.

Parameters

ParameterTypeDescription
reqRequest | ExpressLikeRequestStandard Fetch API Request object or Express-like request that must contain both a headers and body field.
secretstring (optional)Signing secret for webhook validation. If not provided, uses PINNACLE_SIGNING_SECRET environment variable. Throws an error if neither is provided.

Returns

One of the following objects (discriminated by the type field):

  • MessageEvent: Inbound message or message status update (MESSAGE.RECEIVED, MESSAGE.STATUS).
  • UserEvent: User event such as when a user started typing (USER.TYPING).
  • FormSubmissionEvent: A recipient completed a hosted form (FORM.SUBMISSION).
  • CampaignStatusEvent: Per-carrier launch or verification status changed for an RCS campaign (CAMPAIGN.STATUS).

Errors

ErrorDescription
UnauthorizedErrorWebhook secret validation failed
BadRequestErrorRequest body validation failed

Example Implementation

1import express from 'express';
2import { PinnacleClient, Pinnacle } from 'rcs-js';
3
4const app = express();
5const client = new PinnacleClient({ apiKey: PINNACLE_API_KEY });
6
7app.post('/webhook', express.json(), async (req, res) => {
8 try {
9 // Process and validate the webhook. Returns one of:
10 // Pinnacle.MessageEvent | Pinnacle.UserEvent | Pinnacle.FormSubmissionEvent | Pinnacle.CampaignStatusEvent
11 const event = await client.messages.process(req);
12
13 switch (event.type) {
14 case "MESSAGE.RECEIVED":
15 case "MESSAGE.STATUS":
16 console.log(`${event.direction} ${event.type}:`, event.message);
17 break;
18 case "USER.TYPING":
19 console.log("user typing in conversation", event.conversation.id);
20 break;
21 case "FORM.SUBMISSION":
22 console.log("form", event.form.id, "submitted:", event.submission.data);
23 break;
24 case "CAMPAIGN.STATUS":
25 // Per-carrier launch + verification status for an RCS campaign.
26 console.log(
27 "campaign status for", event.agent.id,
28 "carriers:", event.carrierLaunches.carriers,
29 "verification:", event.carrierLaunches.verification,
30 );
31 break;
32 }
33
34 res.status(200).json({ status: 'processed' });
35 } catch (error) {
36 throw error
37 }
38});