> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datavibe.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# v2 multi-channel gate

> Gate AI-generated WhatsApp, Telegram, SMS, LinkedIn, and Slack messages, not only email.

`POST /v2/gate/outbound` extends the production gate to live-chat channels.
`channel: "email"` behaves identically to `POST /v1/gate/outbound`; use v1
directly for email-only integrations.

```json theme={null}
{
  "channel": "whatsapp",
  "recipient": "+15555550123",
  "body_text": "Hi Jordan, checking in on your Q3 plans.",
  "source_model": "gpt-4o",
  "idempotency_key": "chat-session-42-reply-3",
  "auto_remediate": true
}
```

`recipient` format depends on `channel`: email address (`email`), E.164 phone
number (`whatsapp`/`sms`), `@username` or numeric ID (`telegram`), profile URL
(`linkedin`), user/channel ID (`slack`). `subject` and `body_html` are required
only when `channel` is `email`; `body_text` is always required.

## Auto-remediation

Set `auto_remediate: true` for live-chat channels where review latency is
unacceptable. When every violation is `WARN` severity (no `BLOCK`), DataVibe
applies `safer_alternative` substitutions inline and returns `APPROVED`
immediately, no human queue. Any `BLOCK` violation still requires human
review regardless of this flag.

## Response

```json theme={null}
{
  "action_id": "gate_01hw...",
  "status": "QUEUED",
  "policy_passed": false,
  "policy_violations": [],
  "channel": "whatsapp",
  "remediated": false,
  "remediated_body": null,
  "hold_token": "hld_...",
  "ack_message": "On it, let me check that and get back to you in a moment.",
  "safe_fallback": "Thanks for your message! Our team will be in touch with you soon.",
  "delivery_status": null,
  "snapshot_id": "3039cc54-...",
  "config_hash": "..."
}
```

* `hold_token` is present when `status` is `QUEUED` on a non-email channel.
  Store it. DataVibe returns it again in the approval/rejection callback so
  the bot can match the hold back to the original message.
* `ack_message` is a suggested instant reply for the bot to send while the
  real message waits for review. Falls back to a channel-appropriate default;
  configurable per workspace via `ack_template`.
* `safe_fallback` is a suggested reply if the bot needs to respond without
  ever exposing the held content (for example, a hard timeout on the
  customer's side).

## Review callback

Configure `callback_url` (and optionally `callback_secret`) in workspace
governance settings. When a reviewer approves or rejects a `QUEUED`
submission, DataVibe POSTs to that URL:

```json theme={null}
{
  "event": "gate.review.approved",
  "action_id": "gate_01hw...",
  "hold_token": "hld_...",
  "channel": "whatsapp",
  "recipient": "+15555550123",
  "body_text": "Hi Jordan, checking in on your Q3 plans.",
  "reviewed_by": "reviewer@company.com",
  "reviewed_at": "2026-07-23T18:04:11Z"
}
```

`event` is `gate.review.approved` or `gate.review.rejected`. If `callback_secret`
is configured, the request is HMAC-signed the same way as governance webhooks:

```http theme={null}
X-DataVibe-Signature: v1=<hex-hmac-sha256>
X-DataVibe-Signature-Timestamp: 1721760251
X-DataVibe-Signature-Version: v1
```

The signed message is `f"{timestamp}.{raw_body}"`, HMAC-SHA256 over
`callback_secret`. Reject the callback if the signature doesn't match or the
timestamp is stale.

<Note>
  No `callback_url` configured? Poll `GET /v2/gate/outbound/{action_id}` for
  status instead of waiting for a push callback.
</Note>

## Idempotency

Same rule as v1: a repeated `idempotency_key` returns the original submission
unconditionally. DataVibe does not compare the retried payload against the
original; see [Idempotency and retries](/concepts/idempotency-and-retries).
