Skip to content

02 Get your data in /Integrations

Judge.me

Send Judge.me product and store reviews to Dimension Labs with the universal API.

  1. JM Judge.meTickets, chats, calls, reviews
  2. ⟳ Your jobPull new · map fields · every 15 min
  3. { } Universal APIPOST /track · /trackhistorical
  4. Dimension LabsRead in full · enriched daily

This brings in the reviews in your Judge.me store, product reviews and store reviews: each review as a customer message, with its rating, product and verified status. One conversation per review. You run it on your side: a small script pulls from the Judge.me API and posts each message to the universal API.

  • A Judge.me store, your Private API Token and your shop domain (in example.myshopify.com format).
  • A Dimension Labs API key for a new Universal API source. See Your API key.

Judge.me’s steps are in Using Judge.me API.

  1. In your Judge.me admin, go to Settings > Integrations.
  2. Click View API tokens at the top right. Copy the Private API Token and your Shop domain.
  3. Send the token in the X-Api-Token header, with shop_domain as a query parameter. The private token grants read and write access to your data, so use it on a server only. Judge.me says you can’t regenerate it yourself: if it is ever exposed, contact Judge.me support for a new one.
Terminal window
curl -H "X-Api-Token: $JUDGEME_PRIVATE_TOKEN" \
"https://api.judge.me/api/v1/reviews?shop_domain=example.myshopify.com&per_page=100&page=1"
  • With no product_id, the endpoint returns all product and store reviews of the store.
  • The reviews endpoints return raw review information, which can include unpublished reviews. curated says whether a review is published (ok), not published (spam) or waiting (not-yet).
  • Incremental: the endpoint has no “updated since” filter, so the code pages through every review and sends those whose updated_at is at or after the cursor.
  • Pagination: page and per_page (up to 100).
  • Judge.me’s help center says the response doesn’t include replies to reviews, so only the review is sent.
  • Rate limits: Judge.me’s API documentation doesn’t state one. The code waits and retries on 429 and 5xx.

Each review is one incoming message under its own sessionId.

Dimension LabsJudge.meNotes
texttitle and bodyJoin the title and body with a line break.
userIdreviewer.idJudge.me’s internal reviewer id, prefixed judge-me-reviewer-. Don’t send reviewer.email, reviewer.name or reviewer.phone.
incomingAlways true.
sessionIdidJudge.me’s internal review id, prefixed judge-me-.
conversationIdid
dimensionlabs_timestampcreated_atConvert with toMillis.
platformJsonrating, product_external_id, product_handle, product_title, source, verified, curated, hidden, reviewer.external_idproduct_external_id is the product id in your e-commerce platform (for example Shopify), and reviewer.external_id the customer id there: the fields to join to your own data.

Personal data. Judge.me returns the reviewer’s email, name and phone, and the review’s ip_address. Don’t send them: the code uses Judge.me’s ids instead. Reviews can still name people in their text: see PII redaction.

// judge-me.mjs. Environment: JUDGEME_PRIVATE_TOKEN, JUDGEME_SHOP_DOMAIN, DL_API_KEY.
import { sendToDimensionLabs, toMillis } from './dimensionlabs.mjs';
const HOUR = 60 * 60 * 1000;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// Retries Judge.me's rate limits (429) and server errors (5xx), honoring Retry-After when it is sent.
async function get(url) {
for (let attempt = 0; ; attempt++) {
const res = await fetch(url, { headers: { 'X-Api-Token': process.env.JUDGEME_PRIVATE_TOKEN, Accept: 'application/json' } });
if (res.ok) return res.json();
if ((res.status !== 429 && res.status < 500) || attempt === 5) throw new Error(`Judge.me returned ${res.status}: ${await res.text()}`);
await sleep((Number(res.headers.get('retry-after')) || 2 ** attempt) * 1000);
}
}
// Sends every review created or updated at or after `since` (Unix ms). Returns the new `since`.
export async function syncJudgeMe({ since, historical = false }) {
const started = Date.now();
for (let page = 1; ; page++) {
const q = new URLSearchParams({ shop_domain: process.env.JUDGEME_SHOP_DOMAIN, per_page: '100', page: String(page) });
const { reviews = [] } = await get(`https://api.judge.me/api/v1/reviews?${q}`);
for (const r of reviews) {
if (toMillis(r.updated_at ?? r.created_at) < since) continue; // unchanged since the last run
const text = [r.title, r.body].filter((x) => x?.trim()).join('\n');
if (!text) continue;
const id = `judge-me-${r.id}`;
const created = toMillis(r.created_at);
await sendToDimensionLabs({ userId: r.reviewer?.id ? `judge-me-reviewer-${r.reviewer.id}` : id, sessionId: id, conversationId: id,
text, incoming: true, dimensionlabs_timestamp: created,
platformJson: { rating: r.rating, productExternalId: r.product_external_id, productHandle: r.product_handle,
productTitle: r.product_title, source: r.source, verified: r.verified, curated: r.curated, hidden: r.hidden,
reviewerExternalId: r.reviewer?.external_id } },
{ historical: historical || created < Date.now() - HOUR });
}
if (reviews.length < 100) break;
}
return started;
}

A review that is edited, curated or moved to another product comes back with a newer updated_at and is sent again under the same sessionId. Anything unchanged is a duplicate, and is removed automatically.

Save the code as judge-me.mjs in a project set up as in Set up your project, and run it with the scheduled sync runner: import { syncJudgeMe as sync } from './judge-me.mjs';.

  • History first: node run.mjs 2020-01-01 sends every review since that date to /trackhistorical. Then start a backfill from the Backfill tab.
  • Then on a schedule: the job sends new and changed reviews to /track, and they are enriched automatically every day. Anything more than an hour old when the job sees it goes to /trackhistorical, and needs a backfill. Every run reads all your reviews, because the API has no date filter: every 15 minutes is fine for a small store, but for thousands of reviews run it hourly or daily.
  • Re-runs are safe: duplicates are removed automatically.

If you have reviews in a file instead, upload it and check it first with the file checker, then run a backfill.

Checked against Judge.me’s documentation on 2026-10-26.