Review Invites
Search and manage the recipients on your review-invite campaigns.
Searches recipients by name, email, or phone across your agency's review-invite campaigns.
Search recipients
/api/v1/review-invites{
"data": {
"recipients": [
{
"id": "cm_recip_1",
"name": "Jordan Lee",
"email": "jordan@example.com",
"phone": "",
"source": "manual",
"contactType": "Customer",
"status": "pending",
"campaignId": "cm_campaign_1",
"campaignName": "Spring Checkup Follow-up",
"locationId": "cm_loc_1",
"locationLabel": "Acme Dental — Downtown · Austin",
"alreadyMessaged": false
}
],
"count": 1
}
}Adds one or more recipients to a review-invite campaign, deduplicated against the batch itself and against everyone already on the campaign. Warning — this can trigger a real message send: if the target campaign is already launched with auto-send on, the newly added recipients are queued and sent to immediately, on their real email address or phone number.
Add recipients to a campaign
/api/v1/review-invites{
"data": {
"count": 1,
"duplicates": 0,
"alreadyPresent": 0
}
}Corrects a recipient's name, email, phone, or contact type. Email and phone are frozen once a message has gone out to that recipient — changing either after a send returns a 409, since delivery receipts and replies are tied to the address actually used.
Update a recipient
/api/v1/review-invites/update{
"data": {
"id": "cm_recip_1",
"name": "Jordan Lee",
"email": "jordan@example.com",
"phone": null,
"contactType": "Customer",
"status": "pending"
}
}Lists a location's review-invite campaigns, newest first.
List campaigns
/api/v1/review-invites/campaigns{
"data": {
"rows": [
{
"id": "cm_campaign_1",
"name": "Spring Checkup Follow-up",
"type": "email_sms",
"collectMode": "directory",
"status": "draft",
"archived": false,
"locationLabel": "Acme Dental — Downtown · Austin",
"emailsSent": 0,
"smsSent": 0,
"repliesCount": 0,
"clickRate": null,
"followUpSent": 0,
"autoSend": true,
"yelpCompliant": true,
"staticUrl": null
}
],
"total": 1
}
}Creates a new review-invite campaign as a draft. locationId is required; everything else can be set now or later with the update endpoint. Use the action endpoint to publish it once configured — this never sends anything on its own.
Create a campaign
/api/v1/review-invites/campaigns{
"data": {
"id": "cm_campaign_1",
"agencyId": "cm_agency_1",
"locationId": "cm_loc_1",
"clientLocationId": "cm_loc_1",
"name": "Spring Checkup Follow-up",
"campaignType": "email_sms",
"channels": "EMAIL",
"status": "draft",
"fromEmail": null,
"replyToEmail": null,
"emailSubject": null,
"emailBody": null,
"smsBody": null,
"smsReviewSite": null,
"reviewSites": null,
"screeningEnabled": false,
"landingTitle": null,
"landingContent": null,
"hideAddress": false,
"hideBusinessName": false,
"followups": null,
"stopFollowupOnClick": false,
"scheduleAt": null,
"timezone": null,
"autoSend": true,
"staticUrl": null,
"launchedAt": null,
"emailHtml": null,
"thankYouEnabled": false,
"thankYouSubject": null,
"thankYouBody": null,
"thankYouDelayHours": 12,
"funnelThreshold": 4,
"funnelStyle": null,
"lowRankContent": null,
"hideFeedbackBox": false,
"ratingMechanism": null,
"askName": true,
"askFeedback": true,
"archivedAt": null,
"hideImage": false,
"clientId": "cm_client_1",
"createdAt": "2026-01-20T09:00:00.000Z",
"updatedAt": "2026-01-20T09:00:00.000Z",
"createdByUserId": null,
"createdByType": "user",
"archived": false
}
}Returns a single campaign by id.
Get a campaign
/api/v1/review-invites/campaigns/{id}{
"data": {
"id": "cm_campaign_1",
"agencyId": "cm_agency_1",
"locationId": "cm_loc_1",
"clientLocationId": "cm_loc_1",
"name": "Spring Checkup Follow-up",
"campaignType": "email_sms",
"channels": "EMAIL",
"status": "draft",
"fromEmail": null,
"replyToEmail": null,
"emailSubject": "How was your visit?",
"emailBody": null,
"smsBody": null,
"smsReviewSite": null,
"reviewSites": null,
"screeningEnabled": false,
"landingTitle": null,
"landingContent": null,
"hideAddress": false,
"hideBusinessName": false,
"followups": null,
"stopFollowupOnClick": false,
"scheduleAt": null,
"timezone": null,
"autoSend": true,
"staticUrl": null,
"launchedAt": null,
"emailHtml": null,
"thankYouEnabled": false,
"thankYouSubject": null,
"thankYouBody": null,
"thankYouDelayHours": 12,
"funnelThreshold": 4,
"funnelStyle": null,
"lowRankContent": null,
"hideFeedbackBox": false,
"ratingMechanism": null,
"askName": true,
"askFeedback": true,
"archivedAt": null,
"hideImage": false,
"clientId": "cm_client_1",
"createdAt": "2026-01-20T09:00:00.000Z",
"updatedAt": "2026-01-20T09:00:00.000Z",
"createdByUserId": null,
"createdByType": "user",
"archived": false
}
}Edits a campaign's configuration. Pass only the fields you want to change. To change lifecycle status (publish, stop, clone, archive, unarchive) use the action endpoint instead of setting status directly here.
Update a campaign
/api/v1/review-invites/campaigns/{id}{
"data": {
"id": "cm_campaign_1",
"agencyId": "cm_agency_1",
"locationId": "cm_loc_1",
"clientLocationId": "cm_loc_1",
"name": "Spring Checkup Follow-up (updated)",
"campaignType": "email_sms",
"channels": "EMAIL",
"status": "draft",
"fromEmail": null,
"replyToEmail": null,
"emailSubject": "How was your visit?",
"emailBody": null,
"smsBody": null,
"smsReviewSite": null,
"reviewSites": null,
"screeningEnabled": false,
"landingTitle": null,
"landingContent": null,
"hideAddress": false,
"hideBusinessName": false,
"followups": null,
"stopFollowupOnClick": false,
"scheduleAt": null,
"timezone": null,
"autoSend": true,
"staticUrl": null,
"launchedAt": null,
"emailHtml": null,
"thankYouEnabled": false,
"thankYouSubject": null,
"thankYouBody": null,
"thankYouDelayHours": 12,
"funnelThreshold": 4,
"funnelStyle": null,
"lowRankContent": null,
"hideFeedbackBox": false,
"ratingMechanism": null,
"askName": true,
"askFeedback": true,
"archivedAt": null,
"hideImage": false,
"clientId": "cm_client_1",
"createdAt": "2026-01-20T09:00:00.000Z",
"updatedAt": "2026-01-21T10:00:00.000Z",
"createdByUserId": null,
"createdByType": "user",
"archived": false
}
}Runs one lifecycle action on a campaign. publish launches it — if autoSend is on this starts sending real emails or texts immediately, and it's gated per channel: a campaign that includes EMAIL needs a verified sending domain for the client, and one that includes SMS needs a carrier-verified number for the location. Either gate failing returns an explanatory 422; provisioning a domain or phone number is a UI-only step, not something this API can do on your behalf. stop halts an active campaign. clone duplicates it as a new draft. autoSend turns automatic sending on or off for new recipients — pass on. archive archives a stopped campaign; on a still-active one this is a no-op, not an error — the response is {id, skipped: true} instead of the full campaign, so check for skipped rather than assuming data is always a Campaign. unarchive restores an archived campaign.
Run a campaign lifecycle action
/api/v1/review-invites/campaigns/{id}/action{
"data": {
"id": "cm_campaign_1",
"agencyId": "cm_agency_1",
"locationId": "cm_loc_1",
"clientLocationId": "cm_loc_1",
"name": "Spring Checkup Follow-up (copy)",
"campaignType": "email_sms",
"channels": "EMAIL",
"status": "draft",
"fromEmail": null,
"replyToEmail": null,
"emailSubject": "How was your visit?",
"emailBody": null,
"smsBody": null,
"smsReviewSite": null,
"reviewSites": null,
"screeningEnabled": false,
"landingTitle": null,
"landingContent": null,
"hideAddress": false,
"hideBusinessName": false,
"followups": null,
"stopFollowupOnClick": false,
"scheduleAt": null,
"timezone": null,
"autoSend": false,
"staticUrl": null,
"launchedAt": null,
"emailHtml": null,
"thankYouEnabled": false,
"thankYouSubject": null,
"thankYouBody": null,
"thankYouDelayHours": 12,
"funnelThreshold": 4,
"funnelStyle": null,
"lowRankContent": null,
"hideFeedbackBox": false,
"ratingMechanism": null,
"askName": true,
"askFeedback": true,
"archivedAt": null,
"hideImage": false,
"clientId": "cm_client_1",
"createdAt": "2026-01-21T10:05:00.000Z",
"updatedAt": "2026-01-21T10:05:00.000Z",
"createdByUserId": null,
"createdByType": "user",
"archived": false
}
}Lists the agency's saved review-invite message templates — reusable email/SMS content for campaigns.
List message templates
/api/v1/review-invites/templates{
"data": [
{
"id": "cm_tmpl_1",
"name": "Standard follow-up",
"description": "Default post-visit email template",
"content": null,
"assignedLocationIds": [],
"createdAt": "2026-01-15T09:00:00.000Z"
}
]
}Creates a reusable review-invite message template. content is the rich-text JSON shape the campaign builder's editor produces.
Create a message template
/api/v1/review-invites/templates{
"data": {
"id": "cm_tmpl_1",
"agencyId": "cm_agency_1",
"name": "Standard follow-up",
"description": "Default post-visit email template",
"content": null,
"assignedLocationIds": [],
"createdAt": "2026-01-15T09:00:00.000Z",
"updatedAt": "2026-01-15T09:00:00.000Z"
}
}Edits a template. Pass only the fields you want to change.
Update a message template
/api/v1/review-invites/templates/{id}{
"data": {
"id": "cm_tmpl_1",
"agencyId": "cm_agency_1",
"name": "Standard follow-up",
"description": "Default post-visit email template (updated)",
"content": null,
"assignedLocationIds": [
"cm_loc_1"
],
"createdAt": "2026-01-15T09:00:00.000Z",
"updatedAt": "2026-01-16T09:00:00.000Z"
}
}Permanently deletes a template. This doesn't affect campaigns already using its content — it only removes the reusable template.
Delete a message template
/api/v1/review-invites/templates/{id}{
"data": {
"ok": true
}
}