Prisma Reviews / Guides / Reviews to Intercom
Send customer reviews to Intercom as tickets
Teams that run support in Intercom want negative reviews in the same inbox, with an owner and a state, not in a separate dashboard nobody opens. Intercom has no reviews integration, but its Tickets API fits the job: one ticket per review below 4 stars, of a ticket type you create for reviews, with the rating, text and a link to answer. A Prisma webhook (one event per new review on 84 platforms) feeds it. About 40 lines of Python.
pip install flask requestsYou need a Prisma API key and webhook secret, and an Intercom access token from a private app (Developer Hub → your app → Authentication) with permission to read and write tickets and contacts.
1. Set up Intercom once
- Ticket type: Settings → Tickets → Ticket types → New, type Back-office (internal, no customer emails), name it “Public review”. Note its id (
GET https://api.intercom.io/ticket_typeslists them). - A contact to attach the tickets to: the reviewer isn’t an Intercom user, so create one lead for all of them:
curl -X POST https://api.intercom.io/contacts -H "Authorization: Bearer $INTERCOM_TOKEN" \
-H "Intercom-Version: 2.11" -H "Content-Type: application/json" -d '{"role": "lead", "name": "Public reviews"}'Keep the returned id.
2. Receive the review and create the ticket
import hashlib, hmac, os, time, requests
from flask import Flask, request, abort
app = Flask(__name__)
PRISMA = "https://api.prismareviews.com/v1"
PH = {"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"}
IC = {"Authorization": f"Bearer {os.environ['INTERCOM_TOKEN']}", "Intercom-Version": "2.11", "Content-Type": "application/json"}
TICKET_TYPE = os.environ["INTERCOM_TICKET_TYPE_ID"]
CONTACT = os.environ["INTERCOM_REVIEWS_CONTACT_ID"]
SEEN = set() # use your database in production
def verify(raw: bytes, header: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
expected = hmac.new(os.environ["PRISMA_WEBHOOK_SECRET"].encode(), f"{parts['t']}.".encode() + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"]) and abs(time.time() - int(parts["t"])) < 300
@app.post("/webhooks/prisma")
def prisma_webhook():
if not verify(request.get_data(), request.headers.get("Prisma-Signature", "")):
abort(400)
e = request.get_json()
rid = e["data"]["id"]
if e["type"] != "review.created" or rid in SEEN:
return {"ok": True}
r = requests.get(f"{PRISMA}/reviews/{rid}", headers=PH, timeout=30).json()
if (r.get("rating") or 5) >= 4:
return {"ok": True}
title = f"{r['rating']}★ {r['platform']} review: {(r.get('title') or r.get('text') or '')[:60]}"
desc = (f"By {r.get('author') or 'a customer'} on {r['created_at'][:10]} (location {r['location_id']}).\n\n"
f"{r.get('title') or ''}\n{r.get('text') or ''}\n\nAnswer on the platform: {r.get('url') or '-'}\nPrisma review id: {r['id']}")
body = {"ticket_type_id": TICKET_TYPE, "contacts": [{"id": CONTACT}],
"ticket_attributes": {"_default_title_": title, "_default_description_": desc}}
requests.post("https://api.intercom.io/tickets", headers=IC, json=body, timeout=30).raise_for_status()
SEEN.add(rid)
return {"ok": True}_default_title_ and _default_description_ are the two attributes every ticket type has; add your own (Rating, Platform) to the ticket type and send them in ticket_attributes to filter and report in Intercom. Keep the Prisma review id in the description or a custom attribute so a redelivered webhook doesn’t create a second ticket.
3. Register the Prisma webhook
curl -X POST https://api.prismareviews.com/v1/webhooks \
-H "Authorization: Bearer $PRISMA_API_KEY" -H "Content-Type: application/json" \
-d '{"url": "https://yourapp.example.com/webhooks/prisma", "events": ["review.created"]}'Answering
The ticket carries the link to answer on the platform. To publish the answer from your own tooling instead, call POST /v1/reviews/{id}/reply with the text the agent approved, on the platforms that accept replies (GET /v1/platforms says which: reply: "api"). The two-way pattern, where closing the case publishes the answer, is built step by step in reviews to Zendesk; with Intercom the trigger is a webhook on the ticket state change from your Intercom app.
Variants
- Route by location or platform: add a custom ticket attribute and an Intercom workflow that assigns the team.
- Match real customers: if the reviewer’s name or email matches a contact in your data, attach the ticket to that contact instead of the shared lead, so the agent sees their history.
- No code: n8n’s Prisma Reviews trigger (verified node, n8n setup) → IF rating < 4 → HTTP Request node to
POST https://api.intercom.io/ticketswith the same body.
The same webhook, other tools: HubSpot · Notion · Airtable · Zendesk · Slack (approve replies) · Slack (alerts) · Microsoft Teams · Discord · Google Sheets.
FAQ
Does Intercom import Google or App Store reviews?
No. Reviews reach Intercom through its REST API, typically as tickets created by your integration when a reviews webhook fires. A dedicated ticket type for reviews keeps them separate from customer conversations.
Which Intercom object should a review become?
A ticket of a custom type (for example Back-office or Tracker) titled with the rating and platform. It gets an owner, a state and SLAs like any case, without emailing the reviewer, who isn’t an Intercom contact.
Who is the ticket’s contact if the reviewer isn’t in Intercom?
Create one lead named after the platform’s reviews (for example “Public reviews”) once and attach every review ticket to it, or match the reviewer to an existing contact when your own data allows it.
Negative reviews in the support inbox, with an owner.
2 locations free. Test keys return sample reviews, so the first ticket appears today.