Prisma Reviews / Guides / Reviews to Notion

How to send every new customer review to a Notion database

A Notion database is a good place for reviews when the people who read them live in Notion: one page per review, filterable by rating, platform and location, with a checkbox for “replied” and a link to answer. Notion has no reviews integration, so the page is created through its API. This guide does it in Python with a Prisma webhook (one event per new review on 84 platforms) and POST /v1/pages, then shows the n8n version and a backfill. Everything runs with a test key before you connect anything.

Shell
pip install flask requests

You need a Prisma API key and webhook secret, a Notion internal integration token (notion.so/my-integrations), and a database shared with that integration (Share → invite the integration).

1. The database

Create a database with these properties, exactly named: Title (title), Rating (number), Platform (select), Author (text), Date (date), Location (select), URL (url), Replied (checkbox), Review ID (text). The API can’t add properties; it only fills them. Copy the database id from its URL (the 32-character part).

2. Receive the webhook, fetch the review, create the page

Python
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']}"}
SECRET = os.environ["PRISMA_WEBHOOK_SECRET"]
NOTION = {"Authorization": f"Bearer {os.environ['NOTION_TOKEN']}", "Notion-Version": "2022-06-28", "Content-Type": "application/json"}
DB = os.environ["NOTION_DATABASE_ID"]

def verify(raw: bytes, header: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    expected = hmac.new(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

def exists(review_id: str) -> bool:
    q = {"filter": {"property": "Review ID", "rich_text": {"equals": review_id}}, "page_size": 1}
    r = requests.post(f"https://api.notion.com/v1/databases/{DB}/query", headers=NOTION, json=q, timeout=30)
    r.raise_for_status()
    return bool(r.json().get("results"))

def create_page(r: dict):
    title = r.get("title") or (r.get("text") or "")[:60] or f"{r['platform']} review"
    props = {
        "Title": {"title": [{"text": {"content": title}}]},
        "Rating": {"number": r.get("rating")},
        "Platform": {"select": {"name": r["platform"]}},
        "Author": {"rich_text": [{"text": {"content": r.get("author") or ""}}]},
        "Date": {"date": {"start": r["created_at"]}},
        "Location": {"select": {"name": r["location_id"]}},
        "URL": {"url": r.get("url")},
        "Replied": {"checkbox": bool(r.get("reply"))},
        "Review ID": {"rich_text": [{"text": {"content": r["id"]}}]},
    }
    children = [{"object": "block", "type": "paragraph", "paragraph": {"rich_text": [{"text": {"content": (r.get("text") or "")[:2000]}}]}}]
    res = requests.post("https://api.notion.com/v1/pages", headers=NOTION, json={"parent": {"database_id": DB}, "properties": props, "children": children}, timeout=30)
    res.raise_for_status()

@app.post("/webhooks/prisma")
def prisma_webhook():
    if not verify(request.get_data(), request.headers.get("Prisma-Signature", "")):
        abort(400)
    event = request.get_json()
    if event["type"] == "review.created" and not exists(event["data"]["id"]):
        review = requests.get(f"{PRISMA}/reviews/{event['data']['id']}", headers=PH, timeout=30).json()
        create_page(review)
    return {"ok": True}

The review text goes in the page body (a paragraph block, 2,000 characters max per rich-text item) and the structured fields in properties, so the database views stay fast. exists() makes the endpoint idempotent: Prisma redelivers after a failure with the same ids. Notion allows about 3 requests a second per integration.

3. Register the webhook

cURL
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", "reply.published"]}'

Subscribe to reply.published too and, on that event, update the page’s Replied checkbox (PATCH /v1/pages/{page_id} with {"properties": {"Replied": {"checkbox": true}}}); find the page with the same Review ID query.

4. Backfill the history

Python
params = {"limit": 100}
while True:
    page = requests.get(f"{PRISMA}/reviews", headers=PH, params=params, timeout=30).json()
    for r in page["data"]:
        if not exists(r["id"]):
            create_page(r)
    if not page.get("next_cursor"):
        break
    params["cursor"] = page["next_cursor"]

5. The same with n8n, no code

Prisma Reviews trigger (new review) → Notion node, Database Page → Create, mapping Rating, Platform, Author, Date, URL and Review ID; a second Prisma node fetches the review if you want the text in the body. The Prisma node is verified on n8n Cloud (n8n setup). Zapier and Make do the same with their Notion modules behind a catch hook (webhooks in Zapier and Make).

The same webhook, other tools: HubSpot · Airtable · Zendesk · Intercom · Slack (approve replies) · Slack (alerts) · Microsoft Teams · Discord · Google Sheets.

FAQ

Can Notion import Google reviews on its own?

No. Notion has no reviews integration. A database page per review is created through the Notion API (POST /v1/pages with the database as parent) by your script, n8n, Zapier or Make, fed by a reviews webhook.

What properties should the Notion reviews database have?

Title (review title or first words), Rating (number), Platform (select), Author (text), Date (date), Location (select or relation), URL (url), Replied (checkbox) and Review ID (text) to keep it idempotent. Create them in Notion first; the API doesn’t add properties for you.

How do I avoid duplicate pages?

Store Prisma’s review id in a Review ID property and query the database for it before creating a page. Prisma may redeliver a webhook event after a failure, with the same event and review id.

Every review, one Notion database, filter by stars.

Get a free API key

2 locations free. Test keys return sample reviews, so the database fills today.

Next step: see the 84 review platforms Prisma supports, and compare plans on Prisma Reviews pricing.

Get your API key in a minute

Free Spark plan: 2 locations, no card. Test keys return sample data on all 84 platforms, so you can build before connecting a real one.