API Reference
Agency PlanThe RatingsRise REST API gives you programmatic access to your businesses, reviews, customers, review requests, and analytics. Build custom integrations, automate workflows, and embed review data directly into your own applications.
Base URL
https://app.ratingsrise.com/api/v1/All endpoints return JSON. All request bodies must be JSON with a Content-Type: application/json header.
Authentication
All API requests require a Bearer token in the Authorization header. API keys are scoped to your organization and can be created from Settings > API Keys in the RatingsRise dashboard.
Authorization: Bearer sk_live_your_api_key_hereSecurity tip: Keep your API keys secret. Never expose them in client-side code, public repositories, or frontend bundles. Use environment variables on your server.
Keys prefixed with sk_live_ access production data. sk_test_ keys access the sandbox environment and will not trigger real SMS or email sends.
Rate Limits
The API enforces a rate limit of 100 requests per minute per API key. When you exceed the limit, the API returns a 429 Too Many Requests response. Use the response headers to track your usage:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed per minute (100) |
| X-RateLimit-Remaining | Number of requests remaining in the current window |
| X-RateLimit-Reset | Unix timestamp when the rate limit window resets |
| Retry-After | Seconds to wait before retrying (only present on 429 responses) |
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1700000060
Retry-After: 23
{
"error": "Rate limit exceeded. Please retry after 23 seconds.",
"code": "RATE_LIMIT_EXCEEDED"
}Error Format
All errors return a consistent JSON body with an error message, a machine-readable code, and an optional details object for validation errors.
{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"customerEmail": "Must be a valid email address",
"method": "Must be one of: sms, email, whatsapp"
}
}Common Status Codes
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Request body or query parameters are invalid |
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 403 | FORBIDDEN | API key does not have permission for this resource |
| 404 | NOT_FOUND | The requested resource does not exist |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests — slow down and retry |
| 500 | INTERNAL_ERROR | An unexpected server error occurred — contact support |
Pagination
List endpoints support cursor-based pagination with these query parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | Page number (default: 1) |
| perPage | integer | Optional | Items per page (default: 25, max: 100) |
Paginated responses include a pagination object alongside the data array:
{
"data": [ ... ],
"pagination": {
"page": 1,
"perPage": 25,
"total": 142,
"totalPages": 6
}
}Code Examples
Quick-start examples showing authentication and fetching reviews in JavaScript and Python.
JavaScript (fetch)
const API_KEY = process.env.RATINGSRISE_API_KEY;
const BASE_URL = "https://app.ratingsrise.com/api/v1";
async function listReviews(businessId) {
const response = await fetch(
`${BASE_URL}/reviews?businessId=${businessId}&perPage=10`,
{
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(`API error: ${error.code} — ${error.error}`);
}
return response.json();
}
// Usage
const { data: reviews, pagination } = await listReviews("biz_abc123");
console.log(`Found ${pagination.total} reviews`);
reviews.forEach((r) => console.log(`${r.rating}★ — ${r.content}`));Python (requests)
import os
import requests
API_KEY = os.environ["RATINGSRISE_API_KEY"]
BASE_URL = "https://app.ratingsrise.com/api/v1"
def list_reviews(business_id: str, per_page: int = 10) -> dict:
response = requests.get(
f"{BASE_URL}/reviews",
params={"businessId": business_id, "perPage": per_page},
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
)
response.raise_for_status()
return response.json()
# Usage
result = list_reviews("biz_abc123")
print(f"Found {result['pagination']['total']} reviews")
for review in result["data"]:
print(f"{review['rating']}★ — {review['content']}")Businesses
/api/v1/businessesReturns a paginated list of all business locations in your organization.
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | Page number (default: 1) |
| perPage | integer | Optional | Items per page (default: 25, max: 100) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/businesses?perPage=2" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"data": [
{
"id": "biz_abc123",
"name": "Joe's Coffee Shop",
"address": "123 Main St, Austin, TX 78701",
"phone": "+15125551234",
"googlePlaceId": "ChIJrTLr-GyuEmsRBfy61i59si0",
"averageRating": 4.6,
"totalReviews": 142,
"platforms": ["google", "yelp"],
"createdAt": "2024-01-15T08:30:00Z",
"updatedAt": "2024-11-20T14:22:00Z"
},
{
"id": "biz_def456",
"name": "Joe's Coffee — Downtown",
"address": "456 Congress Ave, Austin, TX 78701",
"phone": "+15125555678",
"googlePlaceId": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"averageRating": 4.8,
"totalReviews": 89,
"platforms": ["google"],
"createdAt": "2024-03-01T10:00:00Z",
"updatedAt": "2024-11-19T09:15:00Z"
}
],
"pagination": {
"page": 1,
"perPage": 2,
"total": 5,
"totalPages": 3
}
}/api/v1/businesses/:idRetrieves detailed information for a single business location.
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The business ID (e.g. biz_abc123) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/businesses/biz_abc123" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"id": "biz_abc123",
"name": "Joe's Coffee Shop",
"address": "123 Main St, Austin, TX 78701",
"phone": "+15125551234",
"website": "https://joescoffee.com",
"googlePlaceId": "ChIJrTLr-GyuEmsRBfy61i59si0",
"averageRating": 4.6,
"totalReviews": 142,
"platforms": ["google", "yelp"],
"reviewBreakdown": {
"5": 89,
"4": 31,
"3": 12,
"2": 6,
"1": 4
},
"sentimentBreakdown": {
"positive": 112,
"neutral": 20,
"negative": 10
},
"createdAt": "2024-01-15T08:30:00Z",
"updatedAt": "2024-11-20T14:22:00Z"
}Reviews
/api/v1/reviewsReturns a paginated list of reviews across all or a specific business. Supports filtering by platform, rating, sentiment, and date range.
| Name | Type | Required | Description |
|---|---|---|---|
| businessId | string | Optional | Filter by business ID |
| platform | string | Optional | Filter by platform: google, yelp, facebook, tripadvisor |
| rating | integer | Optional | Filter by star rating (1-5) |
| sentiment | string | Optional | Filter by AI sentiment: positive, neutral, negative |
| dateFrom | string | Optional | Start date (ISO 8601, e.g. 2024-01-01) |
| dateTo | string | Optional | End date (ISO 8601, e.g. 2024-12-31) |
| page | integer | Optional | Page number (default: 1) |
| perPage | integer | Optional | Items per page (default: 25, max: 100) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/reviews?businessId=biz_abc123&rating=5&perPage=2" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"data": [
{
"id": "rev_xyz789",
"businessId": "biz_abc123",
"platform": "google",
"rating": 5,
"content": "Best coffee in Austin! The pour-over is incredible and the staff is super friendly. Will definitely be back.",
"authorName": "Sarah M.",
"authorAvatar": "https://lh3.googleusercontent.com/a/example",
"sentiment": "positive",
"sentimentScore": 0.94,
"reply": null,
"repliedAt": null,
"publishedAt": "2024-11-18T09:30:00Z",
"importedAt": "2024-11-18T10:00:00Z"
},
{
"id": "rev_uvw456",
"businessId": "biz_abc123",
"platform": "google",
"rating": 5,
"content": "Amazing latte art and the pastries are always fresh. This is my go-to spot every morning.",
"authorName": "Michael R.",
"authorAvatar": "https://lh3.googleusercontent.com/a/example2",
"sentiment": "positive",
"sentimentScore": 0.91,
"reply": "Thank you, Michael! We're thrilled you enjoy our lattes and pastries. See you tomorrow morning!",
"repliedAt": "2024-11-17T15:45:00Z",
"publishedAt": "2024-11-17T12:00:00Z",
"importedAt": "2024-11-17T12:30:00Z"
}
],
"pagination": {
"page": 1,
"perPage": 2,
"total": 89,
"totalPages": 45
}
}/api/v1/reviews/:idRetrieves a single review by its ID, including full content and reply status.
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The review ID (e.g. rev_xyz789) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/reviews/rev_xyz789" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"id": "rev_xyz789",
"businessId": "biz_abc123",
"platform": "google",
"rating": 5,
"content": "Best coffee in Austin! The pour-over is incredible and the staff is super friendly. Will definitely be back.",
"authorName": "Sarah M.",
"authorAvatar": "https://lh3.googleusercontent.com/a/example",
"sentiment": "positive",
"sentimentScore": 0.94,
"keywords": ["coffee", "pour-over", "staff", "friendly"],
"reply": null,
"repliedAt": null,
"publishedAt": "2024-11-18T09:30:00Z",
"importedAt": "2024-11-18T10:00:00Z"
}| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The review ID to reply to (path parameter) |
| content | string | Required | The reply text (max 4096 characters) |
Example Request
curl -X POST "https://app.ratingsrise.com/api/v1/reviews/rev_xyz789/reply" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"content": "Thank you so much, Sarah! We are glad you loved the pour-over. Our baristas take great pride in every cup. See you again soon!"
}'Example Response
{
"id": "rev_xyz789",
"businessId": "biz_abc123",
"platform": "google",
"rating": 5,
"content": "Best coffee in Austin! The pour-over is incredible and the staff is super friendly. Will definitely be back.",
"authorName": "Sarah M.",
"reply": "Thank you so much, Sarah! We are glad you loved the pour-over. Our baristas take great pride in every cup. See you again soon!",
"repliedAt": "2024-11-20T16:30:00Z",
"publishedAt": "2024-11-18T09:30:00Z"
}Customers
/api/v1/customersReturns a paginated list of customers. Filter by business, search by name or email, or filter by tags.
| Name | Type | Required | Description |
|---|---|---|---|
| businessId | string | Optional | Filter by business ID |
| search | string | Optional | Search by customer name or email (case-insensitive partial match) |
| tags | string | Optional | Comma-separated list of tags to filter by (e.g. vip,loyal) |
| page | integer | Optional | Page number (default: 1) |
| perPage | integer | Optional | Items per page (default: 25, max: 100) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/customers?businessId=biz_abc123&tags=vip&perPage=2" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"data": [
{
"id": "cust_001",
"businessId": "biz_abc123",
"name": "Emily Johnson",
"email": "emily@example.com",
"phone": "+15125559876",
"tags": ["vip", "loyal"],
"notes": "Regular customer — comes in every weekday morning.",
"reviewRequestsSent": 3,
"reviewsLeft": 1,
"lastVisit": "2024-11-19T08:15:00Z",
"createdAt": "2024-02-10T14:00:00Z",
"updatedAt": "2024-11-19T08:15:00Z"
},
{
"id": "cust_002",
"businessId": "biz_abc123",
"name": "David Chen",
"email": "david.chen@example.com",
"phone": "+15125554321",
"tags": ["vip"],
"notes": null,
"reviewRequestsSent": 1,
"reviewsLeft": 1,
"lastVisit": "2024-11-15T12:30:00Z",
"createdAt": "2024-06-05T09:00:00Z",
"updatedAt": "2024-11-15T12:30:00Z"
}
],
"pagination": {
"page": 1,
"perPage": 2,
"total": 18,
"totalPages": 9
}
}/api/v1/customersCreates a new customer record. At minimum, a name is required. Email or phone is recommended for sending review requests.
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Customer full name |
| string | Optional | Customer email address | |
| phone | string | Optional | Customer phone in E.164 format (e.g. +15125551234) |
| tags | string[] | Optional | Array of tags (e.g. ["vip", "new"]) |
| notes | string | Optional | Internal notes about the customer |
Example Request
curl -X POST "https://app.ratingsrise.com/api/v1/customers" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Jessica Williams",
"email": "jessica@example.com",
"phone": "+15125557890",
"tags": ["new", "walk-in"],
"notes": "Referred by Emily Johnson."
}'Example Response
{
"id": "cust_003",
"businessId": "biz_abc123",
"name": "Jessica Williams",
"email": "jessica@example.com",
"phone": "+15125557890",
"tags": ["new", "walk-in"],
"notes": "Referred by Emily Johnson.",
"reviewRequestsSent": 0,
"reviewsLeft": 0,
"lastVisit": null,
"createdAt": "2024-11-20T17:00:00Z",
"updatedAt": "2024-11-20T17:00:00Z"
}/api/v1/customers/:idUpdates an existing customer. Only include the fields you want to change; omitted fields remain unchanged.
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The customer ID (path parameter) |
| name | string | Optional | Updated customer name |
| string | Optional | Updated email address | |
| phone | string | Optional | Updated phone in E.164 format |
| tags | string[] | Optional | Replaces all tags with the provided array |
| notes | string | Optional | Updated internal notes |
Example Request
curl -X PUT "https://app.ratingsrise.com/api/v1/customers/cust_003" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"tags": ["vip", "walk-in"],
"notes": "Upgraded to VIP after third visit. Referred by Emily Johnson."
}'Example Response
{
"id": "cust_003",
"businessId": "biz_abc123",
"name": "Jessica Williams",
"email": "jessica@example.com",
"phone": "+15125557890",
"tags": ["vip", "walk-in"],
"notes": "Upgraded to VIP after third visit. Referred by Emily Johnson.",
"reviewRequestsSent": 0,
"reviewsLeft": 0,
"lastVisit": null,
"createdAt": "2024-11-20T17:00:00Z",
"updatedAt": "2024-11-20T17:45:00Z"
}Review Requests
/api/v1/review-requestsSends a review request to a customer via SMS, email, or WhatsApp. The message includes a personalized link to leave a review.
| Name | Type | Required | Description |
|---|---|---|---|
| customerName | string | Required | The recipient's name (used for personalization) |
| customerEmail | string | Optional | Email address (required if method is email) |
| customerPhone | string | Optional | Phone number in E.164 format (required if method is sms or whatsapp) |
| method | string | Required | Delivery method: sms, email, or whatsapp |
| businessId | string | Optional | Target business ID (defaults to primary business) |
| templateId | string | Optional | Custom template ID (uses default template if omitted) |
Example Request
curl -X POST "https://app.ratingsrise.com/api/v1/review-requests" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"customerName": "Jessica Williams",
"customerEmail": "jessica@example.com",
"customerPhone": "+15125557890",
"method": "sms",
"businessId": "biz_abc123"
}'Example Response
{
"id": "rr_98765",
"businessId": "biz_abc123",
"customerId": "cust_003",
"customerName": "Jessica Williams",
"method": "sms",
"status": "sent",
"reviewLink": "https://app.ratingsrise.com/r/abc123xyz",
"sentAt": "2024-11-20T18:00:00Z",
"openedAt": null,
"completedAt": null,
"createdAt": "2024-11-20T18:00:00Z"
}/api/v1/review-requestsReturns a paginated list of review requests with status tracking. Filter by delivery method or current status.
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | Optional | Filter by status: pending, sent, opened, completed, failed |
| method | string | Optional | Filter by method: sms, email, whatsapp |
| businessId | string | Optional | Filter by business ID |
| page | integer | Optional | Page number (default: 1) |
| perPage | integer | Optional | Items per page (default: 25, max: 100) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/review-requests?status=completed&method=sms&perPage=2" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"data": [
{
"id": "rr_98760",
"businessId": "biz_abc123",
"customerId": "cust_001",
"customerName": "Emily Johnson",
"method": "sms",
"status": "completed",
"reviewLink": "https://app.ratingsrise.com/r/def456uvw",
"sentAt": "2024-11-15T10:00:00Z",
"openedAt": "2024-11-15T10:05:00Z",
"completedAt": "2024-11-15T10:12:00Z",
"createdAt": "2024-11-15T10:00:00Z"
},
{
"id": "rr_98755",
"businessId": "biz_abc123",
"customerId": "cust_002",
"customerName": "David Chen",
"method": "sms",
"status": "completed",
"reviewLink": "https://app.ratingsrise.com/r/ghi789rst",
"sentAt": "2024-11-10T14:30:00Z",
"openedAt": "2024-11-10T14:45:00Z",
"completedAt": "2024-11-10T15:00:00Z",
"createdAt": "2024-11-10T14:30:00Z"
}
],
"pagination": {
"page": 1,
"perPage": 2,
"total": 34,
"totalPages": 17
}
}Analytics
/api/v1/analytics/overviewReturns high-level dashboard metrics for your organization, including total reviews, average rating, response rate, and request conversion.
| Name | Type | Required | Description |
|---|---|---|---|
| businessId | string | Optional | Scope metrics to a specific business (omit for org-wide) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/analytics/overview?businessId=biz_abc123" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"businessId": "biz_abc123",
"period": "all_time",
"metrics": {
"totalReviews": 142,
"averageRating": 4.6,
"responseRate": 0.87,
"averageResponseTime": "2h 15m",
"totalRequestsSent": 210,
"requestConversionRate": 0.42,
"sentimentBreakdown": {
"positive": 112,
"neutral": 20,
"negative": 10
},
"platformBreakdown": {
"google": 128,
"yelp": 14
},
"reviewsThisMonth": 18,
"ratingChangeThisMonth": 0.1
}
}/api/v1/analytics/ratingsReturns monthly average rating data for charting trends over time. Useful for building dashboards and reports.
| Name | Type | Required | Description |
|---|---|---|---|
| months | integer | Optional | Number of months to look back (default: 6, max: 24) |
| businessId | string | Optional | Scope to a specific business (omit for org-wide) |
Example Request
curl -X GET "https://app.ratingsrise.com/api/v1/analytics/ratings?months=6&businessId=biz_abc123" \
-H "Authorization: Bearer sk_live_your_api_key_here"Example Response
{
"businessId": "biz_abc123",
"months": 6,
"data": [
{ "month": "2024-06", "averageRating": 4.3, "reviewCount": 12 },
{ "month": "2024-07", "averageRating": 4.4, "reviewCount": 15 },
{ "month": "2024-08", "averageRating": 4.5, "reviewCount": 19 },
{ "month": "2024-09", "averageRating": 4.5, "reviewCount": 22 },
{ "month": "2024-10", "averageRating": 4.7, "reviewCount": 25 },
{ "month": "2024-11", "averageRating": 4.6, "reviewCount": 18 }
]
}Webhooks
Webhooks let you receive real-time HTTP POST notifications when events happen in your RatingsRise account. Configure webhook endpoints from Settings > Webhooks in the dashboard.
Events
| Event | Description |
|---|---|
| review.created | A new review is imported from any connected platform |
| review.updated | An existing review is modified (rating change, content edit, or reply added) |
| request.completed | A customer completes a review request by submitting a review |
| payment.received | A subscription payment is successfully processed |
Payload Format
Every webhook delivery sends a JSON POST body with the following structure:
{
"id": "wh_evt_abc123",
"event": "review.created",
"data": {
"id": "rev_xyz789",
"businessId": "biz_abc123",
"platform": "google",
"rating": 5,
"content": "Best coffee in Austin!",
"authorName": "Sarah M.",
"sentiment": "positive",
"publishedAt": "2024-11-18T09:30:00Z"
},
"timestamp": "2024-11-18T10:00:05Z"
}Signature Verification
Every webhook request includes an X-RatingsRise-Signature header containing an HMAC-SHA256 signature of the raw request body. Verify this signature using your webhook secret (found in Settings > Webhooks) to ensure the request originated from RatingsRise.
Node.js Verification
import crypto from "crypto";
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac("sha256", secret)
.update(payload, "utf-8")
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler (e.g. Express / Next.js API route):
app.post("/webhooks/ratingsrise", (req, res) => {
const signature = req.headers["x-ratingsrise-signature"] as string;
const rawBody = JSON.stringify(req.body);
if (!verifyWebhookSignature(rawBody, signature, process.env.WEBHOOK_SECRET!)) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = req.body;
console.log(`Received event: ${event.event}`, event.data);
// Process the event...
res.status(200).json({ received: true });
});Python Verification
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
WEBHOOK_SECRET = os.environ["WEBHOOK_SECRET"]
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
payload,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(signature, expected)
@app.route("/webhooks/ratingsrise", methods=["POST"])
def handle_webhook():
signature = request.headers.get("X-RatingsRise-Signature", "")
raw_body = request.get_data()
if not verify_signature(raw_body, signature, WEBHOOK_SECRET):
return jsonify({"error": "Invalid signature"}), 401
event = request.get_json()
print(f"Received event: {event['event']}", event["data"])
# Process the event...
return jsonify({"received": True}), 200Retry Behavior
If your endpoint returns a non-2xx status code or times out (30 seconds), RatingsRise retries the delivery up to 3 times with exponential backoff:
| Attempt | Delay After Failure |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 25 minutes |
After all retries are exhausted, the event is marked as failed. You can view failed deliveries and manually retry them from the Webhooks settings page.
Ready to integrate?
Create your RatingsRise account and generate an API key to start building. The API is available on the Agency plan.