> For the complete documentation index, see [llms.txt](https://docs.tnid.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tnid.com/company/webhooks.md).

# Webhooks

Register a company webhook so TNID calls your endpoint when connection requests, subscriptions, opt-outs, forms and social-network verifications change.

Instead of polling `received…Requests` and `…Connections`, register a webhook and let TNID call you. Webhooks belong to a company and are managed on the `/company` GraphQL server.

## Register a webhook

```graphql
mutation (
  $url: String!
  $name: String
  $bearerToken: String
  $customHeaders: JSON
  $receiveSubscriptionEvents: Boolean
  $receiveOptOutEvents: Boolean
  $b2bConnectionRequestReceivedWebhook: Boolean
  $b2bConnectionRequestResponseWebhook: Boolean
  $b2cConnectionRequestResponseWebhook: Boolean
  $c2bConnectionRequestReceivedWebhook: Boolean
  $b2cSubscriptionRequestResponseWebhook: Boolean
  $companySocialNetworkStatusChangeWebhook: Boolean
  $b2bFormInstanceSubmissionRequestReceivedWebhook: Boolean
) {
  createCompanyWebhook (
    url: $url
    name: $name
    bearerToken: $bearerToken
    customHeaders: $customHeaders
    receiveSubscriptionEvents: $receiveSubscriptionEvents
    receiveOptOutEvents: $receiveOptOutEvents
    b2bConnectionRequestReceivedWebhook: $b2bConnectionRequestReceivedWebhook
    b2bConnectionRequestResponseWebhook: $b2bConnectionRequestResponseWebhook
    b2cConnectionRequestResponseWebhook: $b2cConnectionRequestResponseWebhook
    c2bConnectionRequestReceivedWebhook: $c2bConnectionRequestReceivedWebhook
    b2cSubscriptionRequestResponseWebhook: $b2cSubscriptionRequestResponseWebhook
    companySocialNetworkStatusChangeWebhook: $companySocialNetworkStatusChangeWebhook
    b2bFormInstanceSubmissionRequestReceivedWebhook: $b2bFormInstanceSubmissionRequestReceivedWebhook
  ) {
    id
    url
    name
  }
}
```

```json
{
  "url": "https://api.example.com/tnid/webhook",
  "name": "production",
  "bearerToken": "<a secret you generate>",
  "customHeaders": { "X-Environment": "prod" },
  "receiveSubscriptionEvents": true,
  "receiveOptOutEvents": true,
  "b2bConnectionRequestReceivedWebhook": true,
  "b2bConnectionRequestResponseWebhook": true,
  "b2cConnectionRequestResponseWebhook": true,
  "c2bConnectionRequestReceivedWebhook": true,
  "b2cSubscriptionRequestResponseWebhook": true,
  "companySocialNetworkStatusChangeWebhook": false,
  "b2bFormInstanceSubmissionRequestReceivedWebhook": false
}
```

* `url` must be HTTPS and reachable from the internet.
* `bearerToken` is sent back to you on every delivery as `Authorization: Bearer <bearerToken>`. Generate a random secret and verify it on every request; reject calls that do not carry it.
* `customHeaders` are added verbatim to every delivery.
* Each boolean subscribes the webhook to one event type. Omitted flags default to off.

## Event types

| Flag                                              | Fires when                                                                                       |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `receiveSubscriptionEvents`                       | A person subscribes to your company, changes their topics or channels, or removes a subscription |
| `receiveOptOutEvents`                             | An opt-out is recorded for your company                                                          |
| `b2bConnectionRequestReceivedWebhook`             | Another company sends you a B2B connection request                                               |
| `b2bConnectionRequestResponseWebhook`             | A company accepts or rejects your B2B connection request                                         |
| `b2cConnectionRequestResponseWebhook`             | A person accepts or rejects your B2C connection request                                          |
| `c2bConnectionRequestReceivedWebhook`             | A person sends you a connection request                                                          |
| `b2cSubscriptionRequestResponseWebhook`           | A person accepts or rejects your subscription request                                            |
| `companySocialNetworkStatusChangeWebhook`         | A social-network link on your profile changes verification status                                |
| `b2bFormInstanceSubmissionRequestReceivedWebhook` | Another company asks you to fill in one of its forms                                             |

Sentiment analysis also delivers to your webhooks. When `reportExternalCommunication` detects an unsubscribe intent, TNID posts:

```json
{
  "external_communication_id": "00000000-0000-4000-8000-000000000001",
  "timestamp": "2026-01-15T09:00:00.000000",
  "action": "unsubscribe"
}
```

Confirm or reject it with `feedbackOnDetectedUnsubscribe(externalCommunicationId, action: UNSUBSCRIBE | DONT_UNSUBSCRIBE)`. See [sentiment analysis](https://docs.tnid.com/api-reference/002_company/003_message_sentiment_analysis) in the API Reference.

{% hint style="warning" %}
Payload schemas for the connection, subscription and opt-out events are not yet published on this site. Register a webhook on staging, trigger the event, and capture a sample; the fields mirror the objects returned by the corresponding `received…Requests`, `…Connections` and `optOutRequests` queries. Contact <support@tsgglobal.com> if you need the schemas in advance.
{% endhint %}

## Respond, retries and ordering

Return a `2xx` status quickly and do the work asynchronously. Treat deliveries as at-least-once: key your handler on the object `id` in the payload so a repeated delivery is harmless. Use `insertedAt`/`updatedAt` on the referenced object, not arrival order, when ordering matters.

## Manage webhooks

* `companyWebhooks` lists your webhooks with their flags.
* `updateCompanyWebhook(id, …)` changes only the arguments you pass; omitted settings keep their values.
* `removeCompanyWebhook(id)` stops delivery immediately.

All four operations, with full examples, are in the [API Reference](https://docs.tnid.com/api-reference/002_company/014_webhooks).
