# Hootsuite Vai Webhooks API

**Canonical:** https://apis.io/apis/hootsuite/hootsuite-vai-webhooks-api/  
**Provider:** Hootsuite — https://apis.io/providers/hootsuite/  
**Base URL:** https://platform.hootsuite.com/v1  
**Documentation:** https://developer.hootsuite.com/docs/api-overview

Hootsuite Vai Webhooks API is one of 21 APIs that [Hootsuite](https://apis.io/providers/hootsuite/) publishes on the [APIs.io](https://apis.io/) network, described by a machine-readable OpenAPI specification. The published artifact set on APIs.io includes an OpenAPI specification, API documentation, an API reference, a getting-started guide, authentication docs, and rate-limit docs.

### Webhook authentication When setting up a virtual agent, you received a secret key that you can use to verify whether an incoming webhook request really comes from Inbox 2.0 without alterations. In the request headers of each webhook call is the `X-Hootsuite-Signature`. This contains an `HMAC-SHA256` signature based on the body of the request. Both the secret key you received and the signature are encoded as hexadecimal strings. Most languages come with libraries out of the box to verify this signature. Here is some sample code to verify it in Node.js: ```javascript const secret = "..."; // do not share! const expectedSignature = request.headers["X-Hootsuite-Signature"]; const actualSignature = crypto .createHmac("sha256", Buffer.from(secret, "hex")) .update(request.body, "utf-8") .digest("hex"); if (actualSignature !== expectedSignature) { throw new createError.Unauthorized("X-Hootsuite-Signature wrong"); } ``` Note: Make sure you calculate the signature off the body as is, before you deserialize it from JSON. During the calculation of the signature, all white space is considered significant. As part of the request body, you will find a timestamp. This is the time a request was sent. To prevent replay attacks, we recommend verifying that this timestamp is no older than 5 minutes: ```javascript if (moment(JSON.parse(request.body).timestamp).isBefore(moment().subtract(5, "minutes"))) { throw new createError.Unauthorized("Request too old"); } ``` ### Events When a conversation is assigned to the virtual agent you registered in the previous section, Inbox 2.0 sends you an event via the URL you configured. Three important events are sent: - `CONVERSATION_STARTED` - `CONVERSATION_DELEGATED` - `INBOUND_MESSAGE_RECEIVED` ### Common fields All events have certain common fields: - type: A string that defines what kind of event occurred (currently `CONVERSATION_STARTED`, `CONVERSATION_DELEGATED`, or `INBOUND_MESSAGE_RECEIVED`). New events can be added in the future. Avoid responding with an error to unknown values; instead, ignore them. Depending on this type, the structure of data will be different. - version: A number designating the version of the type of request. Currently, the version is always 1. Versions will be used in the future for introducing non-backward-compatible changes. - idempotencyKey: A string that uniquely identifies each event. When a timeout occurs when sending you the event, (or we receive an error response), we will retry the event. This key can help you to ensure that a request is processed only once. - timestamp: The timestamp when we sent the request. This is used to counter possible replay attacks. - data: An object that contains structured data for the specific type. For example, an `INBOUND_MESSAGE_RECEIVED` type event has fields such as `conversationId` and `message`. Fields may be added in the future. ### Requirements To provide a good customer experience, some non-functional requirements are imposed on the webhook. When a webhook is sent, you have 10 seconds to respond with a 200 OK. If a timeout occurs, we will retry 3 times using an exponential backoff (up to 2 seconds). If the failures persisted during the retries, the assigned conversation will be handed over to a human agent by placing it in the New queue. When the contact sends a message through Inbox 2.0, by default we expect the virtual agent to reply to that message within 5 minutes (using either the response to the webhook call or the REST API). You can configure the timeout on the settings page for your virtual agent (Timeout virtual agent). If the virtual agent does not answer the contact, by default the conversation is placed in the New queue for a human agent to pick up. This can also be configured in `Settings`. If you prefer, you can automatically resolve the conversation and send a message to the contact (such as "Please try again in a little while"). The virtual agent could also decide to immediately return control by sending `RESOLVED` or `HANDOVER` in the `complete` field. Similarly, after a `CONVERSATION_DELEGATED` event, your virtual agent has 5 minutes to pose a question to the contact by default. If the virtual agent fails to do this, the conversation is handed back to the previous owner of the conversation or placed in the New queue, depending on the handoff rule. ### Response Your response to the webhook should be a status `200 OK`. In the body, you can return the response you want to send to the contact: ```json { "sendMessage": { "text": "Hi! How can I help you?", "attachment": "funny_cat.gif" }, "applyTopics": [ "Hotel Reservation" ], "applyTags": [ "Happy" ], "setContactAttributes": { "account_number": "19758293529351" }, "complete": "HANDOVER" } ``` - sendMessage: (Optional) The message you want to send to the contact. You can send only text, only an attachment, or both at the same time. If you want to send an attachment, you must upload it first, so we recommend using the asynchronous flow. - applyTopics: (Optional) The list of topics you want to apply to the conversation (the intent or action that your Virtual Agent matched). Topics that do not exist in Inbox 2.0 will be ignored. - applyTags: The list of tags you want to apply to the message from the contact. Tags that do not exist in Inbox 2.0 will be ignored. It's only possible to use `applyTags` in response to an `INBOUND_MESSAGE_RECEIVED`. It's also possible to tag a specific message by specifying the `messageId`. In that case you can respond using ```json { "applyTags": [{ "messageId": "cc75552a-1a78-11e9-855e-6d1e71016abf", "tag": "Happy" }] } ``` - setContactAttributes: The attributes you want to set on a contact. The object is a map between the attribute definition's alias and value to set. - complete: (Optional) This can be either `HANDOVER` if you want to give the conversation to another agent, or `RESOLVED` if you want to resolve the conversation. When you pass HANDOVER, the handoff rule you configured in settings determine what will happen next. If the handoff rule is "No one," the conversation is placed in the New queue without an owner. Any human agent can pick up the conversation. If the rule has been set to "Previous agent,"the conversation will be assigned back to the previous human agent. If there was no previous agent, the conversation is placed in the New queue without an owner. If you are integrating with an asynchronous bot platform, you can simply return an empty JSON body {} and send this message using a POST request. We also recommend using the REST API when you want to send an attachment. You can respond with {}, upload an attachment using a PUT request, and then send the attachment using a POST request.

## Machine-readable artifacts (19)

- **OpenAPI** — https://raw.githubusercontent.com/api-evangelist/hootsuite/refs/heads/main/openapi/hootsuite-vai-webhooks-api-openapi.yml
- **Documentation** — https://developer.hootsuite.com/docs/api-overview
- **APIReference** — https://apidocs.hootsuite.com/docs/api/index.html
- **GettingStarted** — https://developer.hootsuite.com/docs/getting-started-with-the-rest-api
- **Authentication** — https://developer.hootsuite.com/docs/api-authentication
- **OAuth 2.0** — https://developer.hootsuite.com/docs/enabling-oauth-20
- **Postman** — https://app.getpostman.com/run-collection/eeda0fcdf55ea26bd0ec
- **Webhooks** — https://raw.githubusercontent.com/api-evangelist/hootsuite/refs/heads/main/asyncapi/hootsuite-webhooks.yml
- **RateLimits** — https://raw.githubusercontent.com/api-evangelist/hootsuite/refs/heads/main/rate-limits/hootsuite-rate-limits.yml
- **ErrorCatalog** — https://raw.githubusercontent.com/api-evangelist/hootsuite/refs/heads/main/errors/hootsuite-problem-types.yml
- **DataModel** — https://raw.githubusercontent.com/api-evangelist/hootsuite/refs/heads/main/data-model/hootsuite-data-model.yml
- **Documentation** — https://developer.hootsuite.com/docs/analytics-overview
- **APIReference** — https://apidocs.hootsuite.com/docs/api/analytics/index.html
- **GettingStarted** — https://developer.hootsuite.com/docs/using-the-api
- **OAuthScopes** — https://raw.githubusercontent.com/api-evangelist/hootsuite/refs/heads/main/scopes/hootsuite-scopes.yml
- **Documentation** — https://developer.hootsuite.com/docs/inbox-overview
- **APIReference** — https://apidocs.hootsuite.com/docs/api/inbox/index.html
- **Documentation** — https://developer.hootsuite.com/docs/amplify-overview
- **APIReference** — https://amplify.hootsuite.com/api-docs

## Other Hootsuite APIs (12)

- [Hootsuite Developer Documentation MCP](https://apis.io/apis/hootsuite/mcp/)
- [Hootsuite Analytics API](https://apis.io/apis/hootsuite/hootsuite-analytics-api-api/)
- [Hootsuite Authentication API](https://apis.io/apis/hootsuite/hootsuite-authentication-api/)
- [Hootsuite Comments API](https://apis.io/apis/hootsuite/hootsuite-comments-api/)
- [Hootsuite CRM Rest API](https://apis.io/apis/hootsuite/hootsuite-crm-rest-api-api/)
- [Hootsuite CRM Webhooks API](https://apis.io/apis/hootsuite/hootsuite-crm-webhooks-api/)
- [Hootsuite Me API](https://apis.io/apis/hootsuite/hootsuite-me-api/)
- [Hootsuite Media API](https://apis.io/apis/hootsuite/hootsuite-media-api/)
- [Hootsuite Members API](https://apis.io/apis/hootsuite/hootsuite-members-api/)
- [Hootsuite Messages API](https://apis.io/apis/hootsuite/hootsuite-messages-api/)
- [Hootsuite Organizations API](https://apis.io/apis/hootsuite/hootsuite-organizations-api/)
- [Hootsuite Proactive Messaging Rest API](https://apis.io/apis/hootsuite/hootsuite-proactive-messaging-rest-api-api/)

---

Profiled by [API Evangelist](https://apievangelist.com) and published on [APIs.io](https://apis.io/apis/hootsuite/hootsuite-vai-webhooks-api/). The API's provider profile, Kin Score and agent-readiness rating are at https://apis.io/providers/hootsuite/.
