Build with Ravetell

Everything in Ravetell — campaigns, testimonials, consent — is available to your AI agents and automations. One MCP server, a REST API, and signed webhooks. No SDK required.

MCP — connect an AI assistant

The Ravetell MCP server lives at one URL:

https://mcp.ravetell.com

Claude (web, Desktop, mobile): Settings → Connectors → Add custom connector → paste the URL. Claude walks you through a Ravetell sign-in and an Allow access screen — that's it. No API keys.

CLI clients (Claude Code, Codex, Cursor): authenticate with an API key from Settings → API keys sent as Authorization: Bearer rvt_live_…. Per-client setup snippets live on the connect page.

Tools

All tools are prefixed ravetell_. Read tools (safe, no side effects): list_campaigns, get_testimonials, get_response, get_campaign_stats, get_person, get_account_settings, get_share_link, get_errors, help. Write tools (need the write scope): create_campaign, update_campaign (rename, archive, or set a custom /t2/<slug> link), update_testimonial, delete_response, restore_response. report_bug files a support report (read scope — telemetry, not data mutation).

Creation is consent-shaped by design: create_campaign shows a preview card and creates nothing until it is called again with confirm: true.

REST API

Same data, plain HTTP. Authenticate every request with Authorization: Bearer rvt_live_….

GET /api/campaignsList campaigns
POST /api/campaignsCreate a campaign (returns the share URL)
GET /api/campaigns/:idCampaign detail
PATCH /api/campaigns/:idEdit / archive / reactivate; send customSlug to set /t2/<slug>, or "" to clear it
GET /api/campaigns/:id/responsesResponse summaries (status, final text, hasTranscript)
GET /api/campaigns/:id/responses/:ridSingle response incl. full transcript + consent
PATCH /api/campaigns/:id/responses/:ridOwner edits to a response
GET/POST /api/webhooksManage webhooks (below)

Rate limits are generous for normal use; 429s carry a Retry-After header.

Webhooks — push events to Zapier, Make, n8n, or your server

Register an endpoint and Ravetell POSTs signed JSON events to it:

testimonial.approvedA giver approved their testimonial (the big one — full text, attribution, and consent in the payload)
testimonial.consent_updatedConsent changed — re-check before publishing
campaign.createdNew campaign (includes the share URL)
campaign.updatedCampaign edited, archived, or reactivated

Register

POST /api/webhooks Authorization: Bearer rvt_live_… { "url": "https://hooks.zapier.com/hooks/catch/…", "events": ["testimonial.approved"] }

The response includes a whsec_… signing secret — shown once. Endpoints must be https. Five webhooks per account.

Verify signatures

Every delivery carries Ravetell-Signature: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(secret, t + "." + rawBody). Reject requests older than ~5 minutes and dedupe on the envelope id:

import { createHmac, timingSafeEqual } from 'node:crypto'; function verifyRavetell(rawBody, signatureHeader, secret) { const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('='))); if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false; // replay window const expected = createHmac('sha256', secret).update(parts.t + '.' + rawBody).digest('hex'); return timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected)); }

Delivery semantics (the honest version)

At-least-once, with gaps: deliveries retry on a 0/2/6-second schedule and then stop — there is no out-of-band retry queue. A 7-day delivery log and a manual POST /api/webhooks/:id/redeliver cover misses. Zapier users: this is exactly what "Webhooks by Zapier" expects — create a Catch Hook trigger, paste its URL into the register call above, and your Zap fires on every approved testimonial.

For agents

A machine-readable summary of everything on this page lives at /llms.txt. The MCP server is self-describing — connect and call ravetell_help.