API reference

Everything you can automate with the ReliableReviews v1 API.

The ReliableReviews API lets you do everything the dashboard can do — list sites, import and moderate reviews in bulk, reply to customers, and send email invites — all over a simple, JSON HTTP interface. It is designed for server-to-server integrations, Zapier-style automations, and custom dashboards.

Quickstart

Generate a token from Settings → API Tokens, export it as an env var, and you’re ready to go.

bashexport RR_TOKEN=rr_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# List every site the token can see
curl -sSH "Authorization: Bearer $RR_TOKEN" \
  https://reliablereviews.com/api/v1/sites

# Create a review on the "acme" site
curl -sSX POST \
  -H "Authorization: Bearer $RR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"site_slug":"acme","author_name":"Jane","rating":5,"body":"Excellent"}' \
  https://reliablereviews.com/api/v1/reviews

# Reply to a review
curl -sSX PATCH \
  -H "Authorization: Bearer $RR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"owner_reply":"Thanks for the kind words!"}' \
  https://reliablereviews.com/api/v1/reviews/<review-id>

Authentication

Every request must include an API token in the Authorization header. Tokens look like rr_live_<random> and are shown to you exactly once at creation time — copy and store them securely. Lost a token? Revoke it and generate a new one.

httpAuthorization: Bearer rr_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Token scope

A token is tied to the personal account that created it and has full read-write access to that account’s sites, reviews, and invites. There is no per-scope permission system in v1 — if you need a limited-access token, create a separate account.

Base URL and versioning

All endpoints live under /api/v1. Responses are JSON-only. Requests with a body must send Content-Type: application/json. We may add fields to responses without bumping the version; breaking changes ship under /api/v2.

https://reliablereviews.com/api/v1

Sites

Sites are the top-level container for reviews. Each site has a unique slug (visible in URLs) and a UUID. The list and detail endpoints both return cached aggregates so you don’t need a second call to render a rating summary.

GET/api/v1/sites

List every site owned by the token's account.

Response

json{
  "sites": [
    {
      "id": "9b3a8f50-3a6e-4c31-8e91-2a0f4b2c5d77",
      "slug": "acme",
      "name": "Acme Plumbing",
      "domain": "acme.com",
      "tagline": "Licensed plumbers you can trust",
      "logo_url": null,
      "primary_color": "#14b8a6",
      "created_at": "2026-04-20T21:06:29.368055+00:00",
      "review_count": 42,
      "avg_rating": 4.7,
      "rating_counts": { "1": 0, "2": 0, "3": 2, "4": 8, "5": 32 },
      "response_rate": 83,
      "avg_reply_days": 1
    }
  ]
}
GET/api/v1/sites/{slugOrId}

Fetch a single site by slug or UUID. Includes topics and display settings.

Path parameters

slugOrIdstringrequired
Either the site’s slug (e.g. acme) or its UUID. Returns 404 if the site doesn’t exist or isn’t owned by the token’s account.

Response

json{
  "site": {
    "id": "9b3a8f50-3a6e-4c31-8e91-2a0f4b2c5d77",
    "slug": "acme",
    "name": "Acme Plumbing",
    "domain": "acme.com",
    "tagline": "Licensed plumbers you can trust",
    "logo_url": null,
    "primary_color": "#14b8a6",
    "display_author_style": "first_last_initial",
    "topics": ["pricing", "punctuality", "quality"],
    "created_at": "2026-04-20T21:06:29.368055+00:00",
    "review_count": 42,
    "avg_rating": 4.7,
    "rating_counts": { "1": 0, "2": 0, "3": 2, "4": 8, "5": 32 },
    "response_rate": 83,
    "avg_reply_days": 1
  }
}

Reviews

Reviews belong to a single site. Ratings are on a 1–5 scale in 0.5 increments (i.e. half stars). Reviews created via the API have source: "api", which is visible in the dashboard’s source column.

GET/api/v1/reviews

List reviews across every site on the account, with filters and pagination.

Query parameters

sitestring
Site slug or UUID. Omit to list across every site on the account.
statusenum
pending, published, or hidden.
ratinginteger
Exact integer rating (1–5). Half-stars (e.g. 4.5) aren’t filterable server-side — filter client-side on the result set.
qstring
Case-insensitive substring match on the review body.
limitinteger
1–100 (default 20).
offsetinteger
Pagination offset (default 0).
sortenum
recent (default), oldest, helpful, highest, or lowest.

Response

json{
  "reviews": [
    {
      "id": "488ec827-4da7-4ef6-8316-12c0d98b28e4",
      "site_id": "9b3a8f50-3a6e-4c31-8e91-2a0f4b2c5d77",
      "author_name": "Dana R.",
      "author_email": "dana@example.com",
      "rating": 5,
      "title": "Fixed my leak in under an hour",
      "body": "Called Acme on a Sunday morning...",
      "source": "api",
      "status": "published",
      "verified": false,
      "owner_reply": null,
      "owner_reply_at": null,
      "featured": false,
      "tags": [],
      "internal_note": null,
      "photos": [],
      "helpful_count": 0,
      "created_at": "2026-04-18T10:30:00+00:00",
      "updated_at": "2026-04-20T21:32:40.956217+00:00"
    }
  ],
  "total": 42
}
POST/api/v1/reviews

Create a single review. Published immediately — use PATCH later to hide or feature.

Request body

site_iduuid
Target site UUID. Required unless site_slug is provided.
site_slugstring
Target site slug. Required unless site_id is provided.
author_namestringrequired
1–100 characters.
author_emailemail
Optional, but recommended — enables Gravatar lookup and future reply notifications.
ratingnumberrequired
1–5 in 0.5 increments.
titlestring
Up to 200 characters.
bodystringrequired
1–4000 characters.
created_atdatetime
ISO 8601 or YYYY-MM-DD. Defaults to the current time. Useful when backfilling reviews from another platform.

Example

json{
  "site_slug": "acme",
  "author_name": "Dana R.",
  "author_email": "dana@example.com",
  "rating": 5,
  "title": "Fixed my leak in under an hour",
  "body": "Called Acme on a Sunday morning and they had a tech at my house within 45 minutes.",
  "created_at": "2026-04-18T10:30:00Z"
}

Returns the created review under a review key.

POST/api/v1/reviews/bulk

Batch-create up to 5,000 reviews in a single call. Use this to migrate from another platform.

Request body

site_id / site_sluguuid / string
Target site. Exactly one of the two is required.
rowsarrayrequired
Between 1 and 5,000 review objects. Each row has the same shape as POST /reviews (excluding site_id / site_slug).

Example

json{
  "site_slug": "acme",
  "rows": [
    {
      "author_name": "Jane",
      "author_email": "jane@example.com",
      "rating": 5,
      "body": "Amazing service",
      "created_at": "2026-01-12"
    },
    {
      "author_name": "John",
      "rating": 4,
      "body": "Pretty good",
      "created_at": "2026-02-03"
    }
  ]
}

Response

json{
  "imported": 2,
  "site_id": "9b3a8f50-3a6e-4c31-8e91-2a0f4b2c5d77",
  "site_slug": "acme"
}

All-or-nothing: if one row fails validation, the whole batch is rejected. Rating aggregates and topic extraction recompute in the background after a successful import.

GET/api/v1/reviews/{id}

Fetch a single review by UUID.

Returns the review under a review key. Returns 404 if the review doesn’t exist or belongs to a site owned by a different account.

PATCH/api/v1/reviews/{id}

Moderate, reply to, feature, or tag a review. All fields optional — only the fields present in the body change.

Request body

statusenum
pending, published, or hidden.
owner_replystring | null
Up to 2,000 characters. Pass null or "" to clear an existing reply. Setting a reply also updates owner_reply_at to the current time.
featuredboolean
Pin this review as the site’s featured review. Setting true automatically unpins the site’s previously featured review.
tagsstring[]
Up to 20 tags, each 1–40 characters. Replaces the existing tag list.
internal_notestring | null
Private note visible only to your team. Up to 2,000 characters. Pass null or "" to clear.

Example

json{
  "status": "published",
  "owner_reply": "Thanks for the kind words, Dana!",
  "featured": true,
  "tags": ["vip", "referral"],
  "internal_note": "Sent a thank-you card on 2026-04-22"
}
DELETE/api/v1/reviews/{id}

Permanently delete a review. This can't be undone.

Returns { "deleted": true } on success. Aggregates and topic extraction recompute in the background.

Invites

Invites send a one-time-use link to a customer’s inbox. When the customer submits a review through that link, the review is marked verified and tied back to the invite.

GET/api/v1/invites

List invites for a single site, or across every site on the account.

Query parameters

site_iduuid
Filter to a single site by UUID.
site_slugstring
Filter to a single site by slug.

Response

json{
  "invites": [
    {
      "id": "a1b2c3d4-...",
      "site_id": "9b3a8f50-...",
      "email": "customer@example.com",
      "token": "b8a4...",
      "sent_at": "2026-04-15T14:02:00Z",
      "completed_at": null,
      "reminder_count": 1,
      "last_reminder_at": "2026-04-18T14:02:00Z"
    }
  ]
}
POST/api/v1/invites

Send email invites. Up to 500 recipients per call; duplicates are de-duped automatically.

Request body

site_id / site_sluguuid / string
Target site. Exactly one of the two is required.
emailsstring[]required
1–500 addresses. Lowercased and de-duped server-side.
messagestring
Optional personal note, up to 2,000 characters, included in the invite email.

Response

json{
  "created": 2,
  "invites": [
    { "id": "a1b2...", "email": "alice@example.com", "token": "b8a4..." },
    { "id": "c3d4...", "email": "bob@example.com", "token": "e5f6..." }
  ]
}

Emails are dispatched immediately using the same mailer as the dashboard invite flow. If email delivery fails after the database insert, the invite is persisted and you can trigger a resend from the dashboard.

Errors

Every error response has the same shape:

json{
  "error": "Invalid request body",
  "details": {
    "properties": {
      "rating": { "errors": ["Rating must be at least 1"] }
    }
  }
}
StatusMeaning
400Invalid body, query params, or JSON. See details for field-level errors.
401Missing, malformed, or revoked token.
404Site or review not found, or not owned by the token’s account. We return 404 on ownership mismatches to avoid leaking existence.
500Unexpected server error. Let us know and include the response body.

Limits and quotas

ResourceLimit
Review body1–4,000 characters
Review titleUp to 200 characters
Author name1–100 characters
Rating1–5, in 0.5 increments
TagsUp to 20 per review, each 1–40 characters
Owner reply / internal noteUp to 2,000 characters each
Bulk import rowsUp to 5,000 per request
Invite emailsUp to 500 per request
Reviews list page size1–100 (default 20)

Rate limiting

v1 has no per-token rate limiting. If you’re building a high-volume integration, batch writes via POST /reviews/bulk and self-throttle reads to a few requests per second. We reserve the right to add rate limits in the future; you’ll get advance notice via the changelog.

Ready to build?

Tokens are free and unlimited. Generate one and start automating your review flows today.

Generate a token