A webhook is an HTTPS
callback that specifies how your agent should respond to messages and events. Once you configure your endpoint to accept webhooks, you can start receiving messages and events.
Vibes RBM service sends each RCS event/message as a single HTTP POST
request. They will follow this general format:
POST / HTTP/1.1
Content-Type: application/json
X-Vibes-Eventclass: {{eventClass}}
X-Vibes-Signature: {{signature}}
{{requestBody}}
Below is a table defining a few of these attributes:
Element | Definition |
---|---|
X-Vibes-Eventclass | An HTTP header that indicates what type of event class the callback is. Options areServerEvent , UserEvent , or UserMessage . |
X-Vibes-Signature | An HTTP header that contains a BASE64 encoded HMAC SHA512 signature. |
{{requestBody}} | An HTTP POST body that contains event data serialized in JSON format. |
Event Classes
ServerEvent
ServerEvent
An event that occurred server side that is related to a conversation between an agent and a user. The {{requestBody}}
will be formatted as follows:
{
"phoneNumber": string,
"agentId": string,
"messageId": string,
"eventType": enum ("SENT", "FAILED", "TTL_EXPIRATION_REVOKED", "TTL_EXPIRATION_REVOKE_FAILED", "EVENT_TYPE_UNSPECIFIED"),
"eventId": string,
"sendTime": string
}
Example
Below is an example of aSENT
event. The signature was created usingsuper-secret-value
as a callback secret:
POST / HTTP/1.1
Content-Type: application/json
X-Vibes-Eventclass: ServerEvent
X-Vibes-Signature: xZJCklJ8V7zSGvi5+d5Da3eiXkxECumAvnHtKH/buGsLoxkRp0kZrr7jxP/qzDYUke7y8H3XuUFVAs07g7hrmw==
{
"phoneNumber":"+12223334444",
"messageId":"be0ed04a-ff3c-4a1a-8c64-9235fb4f9073",
"eventType":"SENT",
"eventId":"75078f52-5ed0-4d95-95d8-0cb5a7c7dede",
"sendTime":"2025-01-01T00:00:00.000000000Z",
"agentId":"example_agent"
}
UserEvent
UserEvent
An event coming from an end user's RCS client in conversation with your RCS agent. This could be a delivery message, a notification that the end user is typing, or a read receipt. The {{requestBody}}
will be formatted as follows:
{
"senderPhoneNumber": string,
"eventType": enum ("DELIVERED", "IS_TYPING", "READ", "EVENT_TYPE_UNSPECIFIED"),
"eventId": string,
"messageId": string,
"sendTime": string,
"agentId": string
}
Example
Below is an example of a DELIVERED
event signature created using super-secret-value
as a callback secret:
POST / HTTP/1.1
Content-Type: application/json
X-Vibes-Eventclass: UserEvent
X-Vibes-Signature: QJyAq25GodhDIIV5drikYKoTLDUdT/Mt12QCJpuFMxD88CKv2BbFFHxb/Jt1yOXw/6e4CfCWOgjr2ehq088iwA==
{
"senderPhoneNumber":"+12223334444",
"eventType":"DELIVERED",
"eventId":"MxkiHGGOfhSvSi3xIsj-26MQ",
"messageId":"be0ed04a-ff3c-4a1a-8c64-9235fb4f9073",
"sendTime":"2025-01-01T00:00:00.000000Z",
"agentId":"example_agent"
}
UserMessage
UserMessage
The end user has sent a message to your RCS agent. The {{requestBody}}
will be formatted as follows:
{
"senderPhoneNumber": string,
"messageId": string,
"sendTime": string,
"agentId": string,
// Union field content can be only one of the following:
"text": string,
"userFile": { object (UserFile) },
"location": { object (LatLng) },
"suggestionResponse": { object (SuggestionResponse) }
// End of list of possible types for union field content.
}
Example
Below is an example of a UserMessage
event. The signature was created using super-secret-value
as a callback secret:
POST / HTTP/1.1
Content-Type: application/json
X-Vibes-Eventclass: UserMessage
X-Vibes-Signature: 4o4VhglRySPjZsAA2P9y4A8bq68GaI7JE7GEtXf7EHnGvX7BDujfAekIA589H4+JJcT0wE06/DiiEInVTNtdcg==
{
"senderPhoneNumber":"+12223334444",
"messageId":"MxZIMfKVnURVm7GEMvpbaIng",
"sendTime":"2025-01-01T00:00:00.000000Z",
"text":"some user response",
"agentId":"example_agent"
}
Security
To ensure the security and authenticity of webhooks sent from our API, we sign each webhook request using a SHA-512 HMAC. This allows you to verify that incoming requests are indeed from our API and have not been tampered with.
Each webhook request sent to your endpoint includes an X-Vibes-Signature
header. This header contains the SHA-512 HMAC signature of the request body, generated using the webhook token provided by our support team as the secret key.
Header information
- Header Key:
X-Vibes-Signature
- Signature Algorithm: HMAC SHA-512
- Secret Key: Your provided webhook token
Verifying the Webhook Signature
- Using your webhook token as a key, create a SHA-512 HMAC of the bytes of the message payload and base64-encode the result.
- Compare the
X-Vibes-Signature
header with your computed HMAC.- If the hashes match, you've confirmed that Vibes sent the message and can proceed with processing the webhook.
- If the hashes don't match, reject the request as it may not be authentic.
Sample Code for verifying signature
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class WebhookVerifier {
public static boolean verifySignature(String payload, String signature, String secret) throws Exception {
Mac sha512Hmac = Mac.getInstance("HmacSHA512");
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA512");
sha512Hmac.init(keySpec);
byte[] rawHmac = sha512Hmac.doFinal(payload.getBytes());
String computedSignature = Base64.getEncoder().encodeToString(rawHmac);
return computedSignature.equals(signature);
}
}
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha512', secret);
hmac.update(payload);
const computedSignature = hmac.digest('base64');
return computedSignature === signature;
}
import hmac
import hashlib
import base64
def verify_signature(payload, signature, secret):
computed_signature = base64.b64encode(hmac.new(secret.encode(), payload.encode(), hashlib.sha512).digest())
return computed_signature.decode() == signature
package main
import (
"crypto/hmac"
"crypto/sha512"
"encoding/base64"
)
func verifySignature(payload, signature, secret string) bool {
h := hmac.New(sha512.New, []byte(secret))
h.Write([]byte(payload))
computedSignature := base64.StdEncoding.EncodeToString(h.Sum(nil))
return computedSignature == signature
}
HTTP responses
It is the receiver's responsibility to ensure processing and to return the appropriate error codes. Depending on the error code, Vibes will attempt to redeliver the events up to the maximum number of tries. It is important that the callback endpoint not return errors when no retry attempts are desired. In that case, simply accepting the message with a 2XX response is sufficient.
Developers must be mindful that sending messages at high rates will generate webhook notifications at high rates and must design their code to ensure they can consume notifications at the expected rate. It is important that developers consider situations that may cause failure responses - including 500
responses from their web container, timeouts or upstream failures. Thing to consider include:
- Ensure your DDoS protections are configured to handle the expected rate of webhook notifications.
- Ensure resources such as database connection pools don't run out and produce timeouts or 500 responses.
- Below is a chart of the HTTP response codes that your endpoint should return, depending on the situation.
HTTP Response | Description |
---|---|
| Message was accepted and processed successfully. |
| Permanent event specific error conditions that should not be retried. It will immediately put the event in a failure queue and notify the customer for resolution. |
| Temporary error conditions that indicate a transient failure. These events will be retried based on the configured retry scheme, and then, if still failing, it will put the event in a failure queue and notify the customer for resolution. These can also trigger downed states within a URL that may suspend additional delivery attempts for short periods of time to avoid saturating a down (or slow) service. |