Docs / API reference

Webhooks

Webhooks tell your server when something changes, so you don’t have to poll. You register an HTTPS endpoint with the API, choose the events, and Prisma sends a signed POST for each one.

Events

EventWhendata
review.createdA new review is found on a connected location.id (review), location_id, platform
review.updatedA review’s content changed on the platform, or a reply appeared or changed there.id, location_id, platform
reply.publishedA reply sent through Prisma is live on the platform.id (review), location_id, platform
reply.failedThe platform refused a reply, or every retry failed.id (review), platform, error
connection.updatedAn OAuth connection became active, or a connection became reauth_required.id (connection), platform, status, plus locations_created or reason

Events carry IDs, not full objects. Fetch the current state with GET /v1/reviews/{id} or GET /v1/connections.

Register an endpoint

POST /v1/webhooks

Body paramRequiredDescription
urlyesYour endpoint. Must start with https://.
eventsnoArray of event types, or ["*"] for all of them (the default). At least one if you send it.
api.prismareviews.com/v1
curl -X POST https://api.prismareviews.com/v1/webhooks \
  -H "Authorization: Bearer $PRISMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://yourapp.com/webhooks/prisma", "events": ["review.created", "reply.failed", "connection.updated"]}'

Response 201

JSON
{
  "id": "we_01KJ8R1A3B5C7D9E1F3G5H7J9K",
  "url": "https://yourapp.com/webhooks/prisma",
  "events": ["review.created", "reply.failed", "connection.updated"],
  "secret": "whsec_3q2Xk9LmP0aB7cD1eF4gH6jK8mN2pQ5r",
  "created_at": "2026-10-21T09:20:00.000Z"
}

The signing secret is returned only in this response. Prisma stores it encrypted and never shows it again.

Webhook endpoints belong to the workspace, not to a key: endpoints created with a test key and with a live key are the same list, and each endpoint receives events from both modes. Fetch the object with a key of the matching mode (a test review returns 404 to a live key).

List endpoints

GET /v1/webhooks

cURL
curl https://api.prismareviews.com/v1/webhooks \
  -H "Authorization: Bearer $PRISMA_API_KEY"
JSON
{
  "data": [
    {
      "id": "we_01KJ8R1A3B5C7D9E1F3G5H7J9K",
      "url": "https://yourapp.com/webhooks/prisma",
      "events": ["review.created", "reply.failed", "connection.updated"],
      "active": true,
      "created_at": "2026-10-21T09:20:00.000Z"
    }
  ]
}

Delete an endpoint

DELETE /v1/webhooks/{id}

cURL
curl -X DELETE https://api.prismareviews.com/v1/webhooks/we_01KJ8R1A3B5C7D9E1F3G5H7J9K \
  -H "Authorization: Bearer $PRISMA_API_KEY"
JSON
{ "id": "we_01KJ8R1A3B5C7D9E1F3G5H7J9K", "deleted": true }

404 resource_not_found if there is no endpoint with that ID in your workspace. Deliveries still pending for it are dropped. There is no update endpoint: to change the URL or the events, create a new endpoint and delete the old one.

The delivery

Each event is a POST with a JSON body:

JSON
{
  "id": "evt_01KJ8S2B4C6D8E0F2G4H6J8K0M",
  "type": "review.created",
  "created_at": "2026-10-21T09:00:03.000Z",
  "data": {
    "id": "rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E",
    "location_id": "loc_01KJ8P9W2C4D6F8G0H2J4K6M8N",
    "platform": "google"
  }
}

More data examples:

JSON
{ "id": "rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E", "platform": "google_play", "error": "Google Play API 400: ..." }
JSON
{ "id": "con_01KJ8P7R5S3T1V9W7X5Y3Z1A2B", "platform": "google", "status": "reauth_required", "reason": "Google rejected the access token" }

Headers:

HeaderValue
Content-Typeapplication/json
User-AgentPrisma-Webhooks/1
Prisma-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256>

Answer with any 2xx status within 10 seconds. Do the slow work after answering, for example in a queue.

Retries

A delivery fails on a non-2xx status, a timeout or a connection error. Failed deliveries are retried with exponential backoff: 30 seconds, then doubling up to one hour between attempts. Prisma stops after 30 attempts or when the event is older than your plan’s retry window, whichever comes first:

PlanRetry window
Spark24 hours
Beam72 hours
Spectrum, Aurora7 days

Each retry is signed again with a fresh timestamp and keeps the same event id. De-duplicate by id.

Verify the signature

Prisma-Signature is t=<timestamp>,v1=<signature>, where the signature is the hex HMAC-SHA256 of <timestamp>.<raw body> with your endpoint’s secret. Compute it over the raw request body, before any JSON parsing, compare in constant time and reject events whose timestamp is more than 5 minutes from your clock.

api.prismareviews.com/v1
import crypto from "node:crypto";

export function verifyPrismaSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || !parts.v1 || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

With Express, read the raw body with express.raw({ type: "application/json" }) on the webhook route, verify, then JSON.parse it.

FAQ

Why doesn’t the webhook include the whole review?

Events carry IDs only, so a retried or late event never overwrites newer data. Fetch the current object with GET /v1/reviews/{id}.

Can I get the signing secret again?

No. It is shown once, when you create the endpoint. If you lose it, delete the endpoint and create a new one.

Can events arrive twice or out of order?

Yes, as with most webhook systems. A delivery that timed out is retried with the same event id, so de-duplicate by id and use created_at to order events.

Get new reviews pushed to your server.

Get API key

Webhooks on every plan, including the free Spark plan.

Updated Oct 23, 2026 · Markdown · llms.txt