API Reference
EmbedMyReviews API
Two complementary interfaces, one platform. The REST API covers structured automations: reviews, organisations, review-request invites, and real-time webhook notifications. The AI Hub (MCP) covers interactive AI work: 12 tools any MCP-compatible client like Claude Desktop, Cursor, or ChatGPT can call over JSON-RPC 2.0.
https://app.your-white-label.com/api/v1Authentication
All API requests require a valid API token. Create tokens from your account settings under API & Webhooks. Include it in the Authorization header of every request.
Authorization Header
Authorization: Bearer your-api-tokenToken permissions
| Permission | Access |
|---|---|
| reviews:read | View reviews and review sources |
| reviews:create | Create reviews |
| reviews:update | Update reviews |
| reviews:delete | Delete reviews |
| request:read | View campaigns |
| request:create | Send review invites |
| organizations:read | View organisations |
| organizations:create | Create organisations |
| organizations:update | Update organisations |
| organizations:delete | Delete organisations |
Rate limiting
60 requests per minute per token. Every response includes rate limit headers.
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests per window (60) |
| X-RateLimit-Remaining | Remaining requests in current window |
| Retry-After | Seconds to wait before retrying (only on 429) |
Errors
Standard HTTP status codes. Errors return JSON with a message field.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource successfully created |
| 202 | Accepted | Request accepted and queued |
| 401 | Unauthenticated | Missing or invalid API token |
| 403 | Forbidden | Token lacks required permissions |
| 404 | Not Found | Resource does not exist |
| 422 | Validation Error | Request body failed validation |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Something went wrong on our end |
Pagination
List endpoints return paginated results with 10 items per page. Use the page query parameter to navigate.
{
"data": [...],
"links": {
"first": "https://app.your-white-label.com/api/v1/reviews?page=1",
"last": "https://app.your-white-label.com/api/v1/reviews?page=5",
"prev": null,
"next": "https://app.your-white-label.com/api/v1/reviews?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"per_page": 10,
"to": 10,
"total": 48
}
}Validation error (422) response
{
"message": "The email field is required when phone is not present.",
"errors": {
"email": [
"The email field is required when phone is not present."
]
}
}/api/v1/reviewsList reviews
Retrieve a paginated list of reviews across all connected sources. Filter by rating, organisation, location, or review source.
Requires reviews:read
Query parameters
| Parameter | Type | Description |
|---|---|---|
| rating | integer | Filter by rating (1-5) |
| organization_id | integer | Filter by organisation |
| location_id | integer | Filter by location |
| source_names[] | array | Filter by source names (e.g. Google, Facebook) |
| page | integer | Page number (default: 1) |
Example request
curl https://app.your-white-label.com/api/v1/reviews?rating=5 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": 142,
"organization_id": 1,
"location_id": 3,
"integration_id": 12,
"author": "Sarah Johnson",
"date": "2025-12-15T10:30:00.000000Z",
"rating": 5,
"title": null,
"message": "Outstanding service!",
"source": "Google",
"source_logo": "https://example.com/logos/google.svg",
"avatar": "https://...",
"reply": "Thank you Sarah!",
"reply_date": "2025-12-16T09:00:00.000000Z",
"hidden": false,
"verified": false
}
],
"links": { "first": "...", "last": "...", "prev": null, "next": "..." },
"meta": { "current_page": 1, "from": 1, "last_page": 5, "per_page": 10, "to": 10, "total": 48 }
}/api/v1/reviews/{id}Get review
Retrieve a single review by its ID.
Requires reviews:read
Example request
curl https://app.your-white-label.com/api/v1/reviews/142 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"data": {
"id": 142,
"organization_id": 1,
"location_id": 3,
"integration_id": 42,
"author": "Sarah Johnson",
"date": "2025-12-15T10:30:00.000000Z",
"rating": 5,
"title": null,
"message": "Outstanding service!",
"source": "Testimonials",
"source_logo": "https://cdn.revw.me/img/integration-logos/testimonials.svg",
"avatar": "https://...",
"reply": null,
"reply_date": null,
"hidden": false,
"verified": false
}
}/api/v1/reviewsCreate review
Create a new review from a custom or testimonial source. Only custom integrations and testimonials are supported — reviews from synced sources like Google or Facebook cannot be created via the API. Use the Writable Sources endpoint to discover available sources.
Requires reviews:read + reviews:create
Request body
| Parameter | Type | Description |
|---|---|---|
| author | string | Reviewer name (required, max 255 chars) |
| rating | integer | Star rating 1-5 (required) |
| published_on | date | Publication date in Y-m-d format (required) |
| organization_id | integer | Organisation ID (required) |
| location_id | integer | Location ID, must belong to the organisation (required) |
| source | integer | Integration ID from the Writable Sources endpoint (required) |
| message | string | Review content |
| title | string | Review title (max 255 chars) |
| avatar | file | Reviewer avatar (png, jpg, jpeg, svg, max 250KB) |
Example request
curl -X POST https://app.your-white-label.com/api/v1/reviews \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json" \ -F "author=Jane Smith" \ -F "rating=5" \ -F "message=Absolutely fantastic experience!" \ -F "published_on=2026-01-15" \ -F "organization_id=1" \ -F "location_id=3" \ -F "source=42"
Example response 201 Created
{
"data": {
"id": 285,
"organization_id": 1,
"location_id": 3,
"integration_id": 42,
"author": "Jane Smith",
"date": "2026-01-15T00:00:00.000000Z",
"rating": 5,
"title": null,
"message": "Absolutely fantastic experience!",
"source": "Testimonials",
"source_logo": "https://cdn.revw.me/img/integration-logos/testimonials.svg",
"avatar": "https://ui-avatars.com/api/?name=Jane Smith&background=333D9B&size=74&color=ffffff&rounded=1",
"reply": null,
"reply_date": null,
"hidden": false,
"verified": false
}
}Important
Only custom and testimonial sources are supported. Use GET /api/v1/reviews/sources to discover available sources and their IDs.
The location must belong to the specified organisation, and your token must have access to both.
/api/v1/reviews/{id}Update review
Update an existing review. All fields are optional — only include the fields you want to change. Only reviews from custom or testimonial sources can be updated. Source cannot be changed.
Requires reviews:read + reviews:update
Request body
| Parameter | Type | Description |
|---|---|---|
| author | string | Reviewer name (max 255 chars) |
| rating | integer | Star rating 1-5 |
| message | string | Review content |
| title | string | Review title (max 255 chars) |
| published_on | date | Publication date in Y-m-d format |
| avatar | file | Reviewer avatar (png, jpg, jpeg, svg, max 250KB) |
Example request
curl -X PUT https://app.your-white-label.com/api/v1/reviews/285 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json" \ -F "rating=4" \ -F "message=Updated review content."
Important
Only reviews from custom integrations and testimonial sources can be updated. Synced reviews (Google, Facebook, etc.) return 403.
Source cannot be changed — to change source, delete and recreate the review.
/api/v1/reviews/{id}Delete review
Permanently delete a review. This action cannot be undone. Only reviews from custom or testimonial sources can be deleted.
Requires reviews:read + reviews:delete
Example request
curl -X DELETE https://app.your-white-label.com/api/v1/reviews/285 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"message": "Review deleted successfully."
}Important
Only reviews from custom integrations and testimonial sources can be deleted. Synced reviews (Google, Facebook, etc.) return 403.
/api/v1/reviews/sourcesWritable review sources
Returns sources available for creating reviews (custom integrations and testimonials). The id from each source is what you pass as the source parameter when creating a review.
Requires reviews:read
Query parameters
| Parameter | Type | Description |
|---|---|---|
| organization_id | integer | Filter by organisation |
| location_id | integer | Filter by location |
| page | integer | Page number (default: 1) |
Example request
curl https://app.your-white-label.com/api/v1/reviews/sources?location_id=3 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": 42,
"name": "Testimonials",
"logo": "https://cdn.revw.me/img/integration-logos/testimonials.svg",
"type": "testimonials",
"organization_id": 1,
"location_id": 3
},
{
"id": 58,
"name": "My Custom Source",
"logo": "https://cdn.revw.me/...",
"type": "custom",
"organization_id": 1,
"location_id": 3
}
],
"links": { ... },
"meta": { ... }
}/api/v1/organizationsList organisations
Returns a paginated list of all organisations accessible to the authenticated user.
Requires organizations:read
Example request
curl https://app.your-white-label.com/api/v1/organizations \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": 1,
"name": "Acme Dental Clinic",
"created_at": "2025-01-15T08:30:00.000000Z",
"updated_at": "2025-06-20T14:22:00.000000Z"
}
],
"links": { ... },
"meta": { ... }
}/api/v1/organizationsCreate organisation
Create a new organisation. The name must be unique across your account.
Requires organizations:create
Request body
| Parameter | Type | Description |
|---|---|---|
| name | string | Organisation name (required, max 255 chars, unique) |
| logo | file | Logo image (png, jpg, jpeg, svg, max 250KB) |
Example request
curl -X POST https://app.your-white-label.com/api/v1/organizations \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"name": "Downtown Branch"}'Example response 201 Created
{
"id": 2,
"name": "Downtown Branch",
"created_at": "2025-12-15T10:30:00.000000Z",
"updated_at": "2025-12-15T10:30:00.000000Z"
}/api/v1/organizations/{id}Get organisation
Retrieve a single organisation by its ID.
Requires organizations:read
Example request
curl https://app.your-white-label.com/api/v1/organizations/1 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"id": 1,
"name": "Acme Dental Clinic",
"created_at": "2025-01-15T08:30:00.000000Z",
"updated_at": "2025-06-20T14:22:00.000000Z"
}/api/v1/organizations/{id}Update organisation
Update an existing organisation's name or logo.
Requires organizations:update
Request body
| Parameter | Type | Description |
|---|---|---|
| name | string | Organisation name (max 255 chars, unique) |
| logo | file | Logo image (png, jpg, jpeg, svg, max 250KB) |
Example request
curl -X PUT https://app.your-white-label.com/api/v1/organizations/1 \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Name"}'/api/v1/organizations/{id}Delete organisation
Permanently delete an organisation. This action cannot be undone. You must have at least one remaining organisation.
Requires organizations:delete
Example request
curl -X DELETE https://app.your-white-label.com/api/v1/organizations/1 \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"message": "Organization deleted successfully."
}/api/v1/request-reviews/campaignsList campaigns
Retrieve your review request campaigns. Use campaign UUIDs to send invites via the Send Invite endpoint.
Requires request:read
Query parameters
| Parameter | Type | Description |
|---|---|---|
| organization_id | integer | Filter campaigns by organisation |
| search | string | Search campaigns by name |
Example request
curl https://app.your-white-label.com/api/v1/request-reviews/campaigns \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Post-Visit Follow Up"
},
{
"id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321",
"name": "Monthly Customer Outreach"
}
],
"links": { ... },
"meta": { ... }
}/api/v1/request-reviews/campaigns/{campaign}/inviteSend review invite
Send a review request invite to a contact via email, SMS, or WhatsApp. This is the primary endpoint for automating review requests from your CRM, POS, or booking system.
Requires request:read + request:create
Path + request body
| Parameter | Type | Description |
|---|---|---|
| campaign | uuid | Campaign UUID (required path parameter, from List Campaigns) |
| string | Contact email. Required when phone is not provided. | |
| phone | string | Phone in E.164 format (e.g. +14275238194). Required when email is not provided. |
| first_name | string | Contact first name (max 255 chars) |
| last_name | string | Contact last name (max 255 chars) |
| send_after_hours | integer | Hours to wait before sending. 0 = send ASAP. null = use campaign default. |
Example request
curl -X POST https://app.your-white-label.com/api/v1/request-reviews/campaigns/{campaign_uuid}/invite \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"first_name": "Sarah",
"send_after_hours": 0
}'Example response 202 Accepted
{
"id": "c7d8e9f0-1234-5678-abcd-ef9876543210",
"message": "Invites sent successfully."
}Important
Duplicate contacts are handled gracefully. If the same contact is submitted again within the campaign's dedup window (default: 14 days), the request returns 202 without error and the contact is silently ignored.
Unsubscribed contacts will not receive new invites, even via the API. Their opt-out is always respected.
Invites respect the campaign's configured send window. Requests outside the window are queued for the next available slot.
Delivery channels (email, SMS, WhatsApp) depend on your campaign step configuration. Providing both email and phone maximises reach.
/api/v1/sourcesList review sources
Retrieve all available review sources (Google, Facebook, Yelp, Trustpilot, etc.) with their capabilities and logos.
Requires Any valid token
Example request
curl https://app.your-white-label.com/api/v1/sources \ -H "Authorization: Bearer your-api-token" \ -H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": 1,
"name": "Google",
"url": "https://google.com",
"logo": "https://...",
"available": true,
"can_collect_reviews": true,
"deep_linking_supported": true
}
]
}/api/v1/countriesList countries
Retrieve the full list of supported countries with ISO 3166-1 alpha-2 codes. Useful for populating country selectors.
Requires Any valid token
Example response 200 OK
[
{ "id": "US", "name": "United States" },
{ "id": "GB", "name": "United Kingdom" },
{ "id": "CA", "name": "Canada" },
...
]/api/v1/meCurrent user
Retrieve the authenticated user's basic information. Useful for verifying your API token.
Requires Any valid token
Example response 200 OK
{
"id": 1,
"name": "John Smith",
"email": "[email protected]"
}Agency API
The Agency API lets you manage your customers programmatically — create accounts, switch plans, adjust limits, manage credits, and handle orders. These endpoints use the same authentication but require an agency-level API token generated from the agency account.
Base URL
https://app.your-white-label.com/api/agency/v1Agency tokens have full access across all customer accounts. There are no scoped permissions here, so the token acts as a super admin.
/api/agency/v1/customersCreate customer
Create a new customer account. The customer receives login credentials and is assigned to the specified plan.
Request body
| Parameter | Type | Description |
|---|---|---|
| name | string | Customer name (required) |
| company | string | Organisation/company name (required) |
| string | Login email address (required) | |
| password | string | Password, min 8 characters (required) |
| custom_plan_id | string | Plan ID to assign (required) |
| phone | string | Phone in E.164 format (optional) |
| location_limit | integer | Override plan location limit (optional, min 1) |
| member_limit | integer | Override plan member limit. 0 = unlimited (optional) |
| send_invite | boolean | Email login details to the customer (optional) |
| country | string | ISO 3166-1 alpha-2 code. Required if Stripe Tax is enabled. |
| postal_code | string | Required for US/CA when Stripe Tax is enabled |
Example request
curl -X POST https://app.your-white-label.com/api/agency/v1/customers \
-H "Authorization: Bearer {token}" \
-d name="John Smith" \
-d company="My Clinic" \
-d email="[email protected]" \
-d password="Password123456" \
-d custom_plan_id="2"Example response 200 OK
{
"data": {
"id": 1,
"name": "John Smith",
"email": "[email protected]",
"phone": null,
"language": "en",
"trial_ends_at": null,
"created_at": "2024-09-26T19:57:52.000000Z",
"updated_at": "2024-09-26T19:57:52.000000Z",
"custom_plan": { "id": 2, "name": "Pro" },
"organizations": [{ "id": 1, "name": "My Clinic" }]
}
}/api/agency/v1/customers/{customer}Switch customer plan
Change the customer's assigned plan.
Request body
| Parameter | Type | Description |
|---|---|---|
| custom_plan_id | string | The plan ID to switch to (required) |
Example request
curl -X PUT https://app.your-white-label.com/api/agency/v1/customers/{customer} \
-H "Authorization: Bearer {token}" \
-d custom_plan_id="2"Example response 200 OK
{
"data": {
"id": 1,
"name": "John Smith",
"email": "[email protected]",
"custom_plan": { "id": 2, "name": "Pro" },
"organizations": [{ "id": 1, "name": "My Clinic" }]
}
}/api/agency/v1/customers/{customer}/location-limitUpdate location & member limits
Override the customer's location or member limit independently of their plan defaults. Two separate endpoints.
Request body
| Parameter | Type | Description |
|---|---|---|
| location_limit | integer | PUT .../location-limit: number of locations allowed (min 1) |
| member_limit | integer | PUT .../member-limit: number of team members allowed (0 = unlimited) |
Example request
# Update location limit
curl -X PUT https://app.your-white-label.com/api/agency/v1/customers/{customer}/location-limit \
-H "Authorization: Bearer {token}" \
-d location_limit="5"
# Update member limit
curl -X PUT https://app.your-white-label.com/api/agency/v1/customers/{customer}/member-limit \
-H "Authorization: Bearer {token}" \
-d member_limit="10"Example response 200 OK
{ "message": "Location limit updated successfully." }
// or
{ "message": "Member limit updated successfully." }/api/agency/v1/customers/{customer}/add-creditsAdd credits
Add email or SMS credits to a customer's account. Credits can optionally expire.
Request body
| Parameter | Type | Description |
|---|---|---|
| type | string | Credit type: "email" or "sms" (required) |
| credits | integer | Number of credits to add, min 1 (required) |
| expires_at | date | Expiry date in Y-m-d format (optional) |
| notes | string | Note visible to the customer (optional) |
Example request
curl -X POST https://app.your-white-label.com/api/agency/v1/customers/{customer}/add-credits \
-H "Authorization: Bearer {token}" \
-d type="email" \
-d credits="1000"Example response 200 OK
{
"message": "Credits added successfully.",
"balance": 250
}/api/agency/v1/customers/{customer}/pausePause & resume subscription
Pause or resume a customer's subscription. Only available when the plan is not linked to Stripe (for Stripe-managed subscriptions, use Stripe's native pause).
Example request
# Pause subscription
curl -X PUT https://app.your-white-label.com/api/agency/v1/customers/{customer}/pause \
-H "Authorization: Bearer {token}"
# Resume subscription
curl -X PUT https://app.your-white-label.com/api/agency/v1/customers/{customer}/resume \
-H "Authorization: Bearer {token}"Example response 200 OK
{ "message": "Subscription has been paused." }
// or
{ "message": "Subscription has been resumed." }/api/agency/v1/customers/{customer}Delete customer
Permanently delete a customer account.
Example request
curl -X DELETE https://app.your-white-label.com/api/agency/v1/customers/{customer} \
-H "Authorization: Bearer {token}"Example response 200 OK
{ "message": "Customer deleted successfully." }/api/agency/v1/customersList all customers
Retrieve a paginated list of all your customers with their plans and organisations.
Parameters
| Parameter | Type | Description |
|---|---|---|
| search | string | Search by name or email (optional) |
Example request
curl https://app.your-white-label.com/api/agency/v1/customers \
-H "Authorization: Bearer {token}"Example response 200 OK
{
"data": [
{
"id": 1,
"name": "John Smith",
"email": "[email protected]",
"phone": null,
"language": "en",
"trial_ends_at": "2023-08-24T16:57:57.000000Z",
"created_at": "2023-07-25T16:57:57.000000Z",
"updated_at": "2023-08-04T15:01:11.000000Z",
"custom_plan": { "id": 2, "name": "Pro" },
"organizations": [{ "id": 2, "name": "My Clinic" }]
}
],
"links": { ... },
"meta": { "current_page": 1, "from": 1, "per_page": 10, "to": 10 }
}/api/agency/v1/custom-plansList all plans
Retrieve all custom plans you've created. Use the plan ID when creating customers or switching plans.
Example request
curl https://app.your-white-label.com/api/agency/v1/custom-plans \
-H "Authorization: Bearer {token}"Example response 200 OK
{
"data": [
{
"id": 1,
"stripe_monthly_id": "",
"stripe_yearly_id": "",
"name": "Basic",
"is_default": false,
"is_hidden": false,
"is_free": true,
"updated_at": "2024-09-26T10:19:58.000000Z",
"created_at": "2023-07-25T15:14:02.000000Z"
}
]
}/api/agency/v1/ordersOrders (NFC products)
Manage NFC product orders. List all orders, mark as shipped (with optional tracking URL), complete, or cancel.
Example request
# List orders
curl https://app.your-white-label.com/api/agency/v1/orders \
-H "Authorization: Bearer {token}"
# Ship order (with optional tracking URL)
curl -X PUT https://app.your-white-label.com/api/agency/v1/orders/{order}/ship \
-H "Authorization: Bearer {token}" \
-d tracking_url="https://tracking.example.com/123"
# Complete order
curl -X PUT https://app.your-white-label.com/api/agency/v1/orders/{order}/complete \
-H "Authorization: Bearer {token}"
# Cancel order
curl -X PUT https://app.your-white-label.com/api/agency/v1/orders/{order}/cancel \
-H "Authorization: Bearer {token}"Example response 200 OK
{
"data": [
{
"id": "27d2ba02-...",
"order_number": "HUFTMX-1733678942",
"email": "[email protected]",
"total": 49.99,
"currency": "usd",
"status": "completed",
"shipping": {
"name": "John Smith",
"address": "49 Featherstone Street",
"city": "London",
"country": "GB",
"tracking_url": null
},
"items": [
{
"product_name": "Google Review Card",
"quantity": 1,
"unit_price": 29.99,
"nfc_urls": ["https://your-domain.com/nfc/..."]
}
]
}
]
}Webhooks
Receive real-time HTTP notifications when events occur. Configure your webhook URL in Settings → API & Webhooks.
| Property | Value |
|---|---|
| HTTP Method | POST |
| Content-Type | application/json |
| User-Agent | ReviewManagement/V1 |
| Retry Policy | Up to 10 retries over 5 minutes with exponential backoff |
| Timeout | 30 seconds per attempt |
Events
| Event | Triggered when |
|---|---|
| review-created | A new review is received from any connected source |
| review-updated | An existing review is modified (reply added, rating changed) |
| organization-created | A new organisation is created |
| organization-updated | An organisation's details are modified |
| organization-deleted | An organisation is deleted |
| location-created | A new location is added |
| location-updated | A location's details are modified |
| location-deleted | A location is removed |
Example payload (review-created)
{
"webhook_event": "review-created",
"id": 142,
"organization_id": 1,
"location_id": 3,
"source_name": "google",
"identifier": "AbcXyz123",
"avatar": "https://lh3.googleusercontent.com/a/photo.jpg",
"author": "Sarah Johnson",
"rating": 5,
"original_rating": 5,
"title": null,
"message": "Outstanding service! The team went above and beyond.",
"url": "https://maps.google.com/review/...",
"verified": true,
"replied": false,
"reply_message": null,
"reply_url": null,
"hidden": false,
"reply_published_on": null,
"published_on": "2025-12-15T10:30:00+00:00",
"review_updated_on": null,
"updated_at": "2025-12-15T10:35:00+00:00",
"created_at": "2025-12-15T10:35:00+00:00",
"meta": {}
}AI Hub (MCP Server)
The AI Hub exposes 13 tools over the Model Context Protocol so AI clients like Claude Desktop, Cursor, and ChatGPT can query live review data. This is a separate endpoint from the REST API above, uses a different authentication ability (mcp:access), and speaks JSON-RPC 2.0 instead of REST.
Use the REST API for structured automations and pipelines. Use the MCP endpoint for interactive AI work. Many customers run both.
Endpoint
https://app.your-white-label.com/api/mcpProtocol
JSON-RPC 2.0Spec version
2025-06-18Rate limit
120/min token, 600/min workspaceSetup
Create an AI token in the dashboard under Settings → AI Hub, copy the generated config snippet, and paste it into your MCP client. For Claude Desktop, that's Settings → Developer → Edit Config.
{
"mcpServers": {
"my-agency-reviews": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://app.your-white-label.com/api/mcp",
"--header",
"Authorization: Bearer your-mcp-token"
]
}
}
}mcp-remote is a small stdio-to-HTTP bridge that lets desktop MCP clients talk to an HTTP server. It's the most reliable setup today because Claude Desktop's native URL config still has rough edges.
Authentication
Every request must include the bearer token in the Authorization header. The token must carry the mcp:access ability. Write tools also require mcp:writes, and PII-sensitive calls also require reviews:pii.
Authorization header
Authorization: Bearer your-mcp-tokenCorrelation IDs
Pass an X-Correlation-Id header (up to 64 chars) and the server will echo it back on the response and record it in the audit log. Useful for grouping every tool call from one AI prompt. Optional.
/api/mcp method: initializeinitialize
Handshake with the server, negotiate the protocol version, and receive the server capabilities and branded server name.
Example request
curl -X POST https://app.your-white-label.com/api/mcp \
-H "Authorization: Bearer your-mcp-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": { "name": "Claude Desktop", "version": "1.0" }
}
}'Example response 200 OK
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": { "tools": {} },
"serverInfo": {
"name": "Your Agency MCP Server",
"version": "1.0.0"
}
}
}/api/mcp method: tools/listtools/list
List the tools this token can invoke. The server filters the catalog by your token's abilities and permissions, so AI clients never see tools they cannot actually call.
Read-only tokens see 10 tools. Read with PII tokens see 11 tools. Write tokens see all 13 tools.
Example request
curl -X POST https://app.your-white-label.com/api/mcp \
-H "Authorization: Bearer your-mcp-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }'Example response 200 OK
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "list_reviews",
"description": "List and filter reviews across organizations and locations...",
"inputSchema": { "type": "object", "properties": { ... } }
},
{
"name": "get_metrics",
"description": "Aggregate review metrics over a date range...",
"inputSchema": { "type": "object", "properties": { ... } }
}
]
}
}/api/mcp method: tools/calltools/call
Invoke one of the registered tools. The response contains both a text content block (for AI client display) and a structuredContent object with the parsed result.
Example request
curl -X POST https://app.your-white-label.com/api/mcp \
-H "Authorization: Bearer your-mcp-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Correlation-Id: client-prompt-20260421-abc123" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_metrics",
"arguments": {
"date_from": "2026-03-22",
"date_to": "2026-04-21",
"group_by": "source"
}
}
}'Example response 200 OK
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"structuredContent": {
"period": { "from": "2026-03-22", "to": "2026-04-21" },
"filters": { "organization_id": null, "location_id": null, "source_name": null },
"totals": {
"total_reviews": 487,
"avg_rating": 4.58,
"responded": 412,
"response_rate": 0.846,
"star_distribution": { "5": 362, "4": 79, "3": 21, "2": 12, "1": 13 },
"sentiment_distribution": { "positive": 441, "neutral": 21, "negative": 25 }
},
"breakdown": [
{ "bucket": "Google", "total_reviews": 318, "avg_rating": 4.61, "responded": 291, "response_rate": 0.915 },
{ "bucket": "Facebook", "total_reviews": 104, "avg_rating": 4.52, "responded": 78, "response_rate": 0.75 },
{ "bucket": "TripAdvisor", "total_reviews": 65, "avg_rating": 4.49, "responded": 43, "response_rate": 0.661 }
]
},
"content": [
{ "type": "text", "text": "{ \"period\": ..., \"totals\": ..., \"breakdown\": [...] }" }
]
}
}Tool catalog
Every tool exposed by the AI Hub, grouped by risk level. Pass the tool name to tools/call with the matching arguments. Required parameters are marked with an asterisk.
Read tools
(7 tools)list_reviews Requires reviews.viewFilter and list reviews across organisations and locations the caller can access. Supports filtering by source, date, rating, sentiment, response status, verified flag, and full-text search. Results are paginated.
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Limit to one organisation |
| location_id | integer | Limit to one location (requires organization_id) |
| source_names | array<string> | Review platforms, e.g. ["Google", "Facebook"] |
| date_from | date | Inclusive start date (YYYY-MM-DD) |
| date_to | date | Inclusive end date (YYYY-MM-DD) |
| ratings | array<integer> | Star ratings to include, 1-5 |
| sentiment | string | "positive", "negative", or "neutral" |
| responded | boolean | Only reviews with or without a reply |
| verified | boolean | Only verified or unverified reviews |
| query | string | Full-text search over author, message, and reply |
| min_message_length | integer | Exclude reviews shorter than N characters |
| sort_by | string | Newest First | Oldest First | Highest Rating First | Lowest Rating First |
| page | integer | Page number (default 1) |
| per_page | integer | Rows per page (1-50, default 25) |
get_review Requires reviews.viewFetch a single review by ID with full detail including reply, tags, auto-respond history, and language.
| Param | Type | Description |
|---|---|---|
| review_id* | integer | The review ID to fetch |
list_organizations Requires locations.viewList organisations the caller can access, with optional review-count and avg-rating enrichment. Pass organization_id for full detail including locations.
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Return full detail for one org (pagination ignored) |
| include_stats | boolean | Attach review count and avg rating. Default true |
| search | string | Substring match on org name |
| page | integer | Page number (default 1) |
| per_page | integer | Rows per page (1-50, default 25) |
list_locations Requires locations.viewList locations accessible to the caller with per-location review count and average rating. Scope to a single organisation with organization_id.
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Limit to one organisation |
| page | integer | Page number (default 1) |
| per_page | integer | Rows per page (1-50, default 25) |
get_metrics Requires reviews.viewAggregate review metrics over a date range: totals, avg rating, star distribution, response rate, sentiment breakdown. Optional group_by slices the data. Pass compare_to_date_from and compare_to_date_to for period-over-period deltas.
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Limit to one organisation |
| location_id | integer | Limit to one location |
| source_name | string | Filter by one source, e.g. "Google" |
| date_from | date | Inclusive start date (YYYY-MM-DD) |
| date_to | date | Inclusive end date (YYYY-MM-DD) |
| group_by | string | day | week | month | location | organization | source | rating | sentiment |
| compare_to_date_from | date | Baseline period start |
| compare_to_date_to | date | Baseline period end |
list_campaigns Requires campaigns.viewList review-request campaigns with paused state, schedule, location, contact list, and full funnel (invited, opened, clicked, reviewed, redirected, testimonials submitted, private feedback, unsubscribed, bounced) plus open, click, redirect, conversion, unsubscribe, and bounce rates.
| Param | Type | Description |
|---|---|---|
| campaign_id | integer | Return detailed metrics for one campaign |
| organization_id | integer | Limit to one organisation |
| date_from | date | Campaign created on or after |
| date_to | date | Campaign created on or before |
| page | integer | Page number |
| per_page | integer | Rows per page (1-50) |
get_ai_insights Requires reviews.viewRetrieve pre-computed AI analysis (themes, sentiment shifts, recommendations) for an organisation or location. Returns the most recent completed insight, or a specific period when period_start and period_end are provided.
| Param | Type | Description |
|---|---|---|
| organization_id* | integer | Target organisation |
| location_id | integer | Specific location (omit for org-wide insights only) |
| period_start | date | Start of the insight period |
| period_end | date | End of the insight period |
Read tools with PII access
(4 tools)list_private_feedback Requires reviews.viewList private feedback submissions (ratings and messages never published publicly). Name, email, and phone are redacted by default; pass include_pii=true to unlock them (requires reviews.pii on the token).
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Limit to one organisation |
| location_id | integer | Limit to one location |
| date_from | date | Submitted on or after |
| date_to | date | Submitted on or before |
| ratings | array<integer> | Star ratings to include, 1-5 |
| include_pii | boolean | Unlock name/email/phone (requires reviews.pii) |
| responded | boolean | Only responded or unresponded |
| page | integer | Page number |
| per_page | integer | Rows per page (1-50) |
list_contacts Requires contacts.viewList review-request contacts with subscription state, latest status, and per-contact engagement counters (invites, opens, clicks, video plays, redirects, testimonials, private feedback, bounces, unsubscribes). Email, phone, and name redacted by default; pass include_pii=true to unlock (requires reviews.pii on the token).
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Limit to one organisation |
| contact_list_id | integer | Limit to one contact list |
| subscribed | boolean | Only subscribed (true) or only unsubscribed (false) |
| date_from | date | Created on or after |
| date_to | date | Created on or before |
| include_pii | boolean | Unlock email/phone/name (requires reviews.pii) |
| page | integer | Page number |
| per_page | integer | Rows per page (1-50) |
get_contact_activity Requires contacts.viewFull timeline for one contact: every invite, open, click, video play, redirect, testimonial, private feedback, unsubscribe, bounce, and spam complaint, with the campaign, channel, step number, rating, message, and source attached. Contact name/email/phone are redacted by default; pass include_pii=true to unlock (requires reviews.pii on the token).
| Param | Type | Description |
|---|---|---|
| contact_id* | integer | The contact ID to load activity for |
| limit | integer | Max events to return, newest first (1-100, default 25) |
| include_pii | boolean | Unlock the contact's name, email, and phone (requires reviews.pii) |
list_auto_respond_rules Requires reviews.auto_respondList configured auto-respond rules with rating range, sources, delay, approval requirement, and AI usage. Use this to audit auto-respond coverage across accessible organisations.
| Param | Type | Description |
|---|---|---|
| organization_id | integer | Limit to one organisation |
| location_id | integer | Limit to one location |
| use_ai | boolean | Only AI-powered rules (true) or only static-template rules (false) |
| paused | boolean | Only paused (true) or only active (false) rules |
| page | integer | Page number |
| per_page | integer | Rows per page (1-50) |
Write tools (always held for approval)
(2 tools)draft_review_response Requires reviews.respondAlso requires mcp:writesDraft a response to a review. The draft is always held for agency approval and never auto-sent. It appears in the Auto-Respond approvals queue for a human to review. Requires write access (mcp:writes) on the token.
| Param | Type | Description |
|---|---|---|
| review_id* | integer | The review to respond to |
| message* | string | The drafted reply (max 8000 chars). Held for approval; never auto-sent. |
tag_reviews Requires reviews.editAlso requires mcp:writesAttach or detach tags on a set of reviews. Useful for clustering reviews by theme after summarisation. Caps at 50 reviews per call. Requires write access (mcp:writes).
| Param | Type | Description |
|---|---|---|
| review_ids* | array<integer> | Up to 50 review IDs |
| attach_tags | array<string> | Tags to attach (max 64 chars each; reserved flag sentinel rejected) |
| detach_tags | array<string> | Tags to detach |
MCP error codes
MCP errors follow JSON-RPC 2.0. The server wraps all infrastructure errors (auth, rate limit, malformed JSON) in a JSON-RPC envelope instead of returning HTML, so AI clients can parse them cleanly.
| Code | Meaning | When |
|---|---|---|
| -32700 | Parse error | Request body is not valid JSON |
| -32600 | Invalid request | Missing method, wrong jsonrpc version, or malformed envelope |
| -32601 | Method not found | Unknown method, or tools/call pointing at a tool that does not exist |
| -32602 | Invalid params | Validation failed, unknown parameter, or missing required parameter |
| -32603 | Internal error | Unexpected server-side failure |
| -32001 | Unauthenticated | Token missing, invalid, or lacks mcp:access |
| -32001 | Missing permission | Token lacks the required ability (e.g. mcp:writes) or semantic permission |
| -32001 | Access denied | Passed an organization_id or location_id outside the caller's scope |
| -32002 | Not found | Tool resolved the request but no matching record exists |
| -32002 | Rate limit exceeded | Per-token or per-workspace rate limit hit; Retry-After header included |
Example error response
{
"jsonrpc": "2.0",
"id": 7,
"error": {
"code": -32001,
"message": "Your token is missing the required permission: reviews.respond."
}
}Guide available
For the full walkthrough on token creation, permissions, PII controls, write approvals, and the audit log, see AI Hub (MCP Server): Setup & Usage.