Skip to main content
Surveys are how Reputation Studio captures the client’s voice after a closing. They are transaction-triggered — a survey is scheduled from a real Deal reaching the won stage, not from a manual blast — and clients respond on a tokenized public page that requires no login.

When surveys send

When a deal transitions to won, Winnerr emits a DEAL_WON system event. The reputation survey workflow listens for that event and:
  1. Looks up the active SurveyTemplate matching the trigger (DEAL_WON).
  2. Creates a Survey addressed to the buyer or seller Person on the deal.
  3. Generates a unique accessToken for the public response page.
  4. Schedules the send for now + sendDelayHours (default 168 hours / 7 days after close).
You can also send a survey manually for any Person + Deal pair from the Reputation Studio UI or via the reputation API.

Survey templates

A SurveyTemplate is your org-authored, reusable questionnaire. Each template carries:
FieldPurpose
nameInternal label shown in the template list.
surveyTypeNPS, CSAT, STAR, or CUSTOM.
schemaJSON question definitions (validated with Zod), modeled on PortalForm.fields.
triggerEventThe system event that auto-schedules the survey, e.g. DEAL_WON.
sendDelayHoursDelay from the trigger to first send. Defaults to 168 (7 days).
channelEMAIL or SMS.
settingsReminder cadence, branding overrides, expiry window.
isActiveInactive templates are not used by the auto-scheduler.
Templates are org-scoped. Create, list, and edit them via the survey templates API.

Reminder ladder

By default, an unanswered survey triggers two reminder emails:
  • +3 days after the initial send.
  • +7 days after the initial send.
The Survey.reminderCount field tracks how many reminders have gone out. Surveys expire after expiresAt (default 30 days from creation), at which point reminders stop and the survey can no longer be answered. The reminder copy is rendered from the same React Email templates as the initial request, with a softer “we’d still love to hear from you” tone.

Branded email

Survey emails (initial + reminders) are rendered through React Email and pull identity from the agent’s Brand Kit: logo, colors, brokerage info, compliance footer, and social links. The recipient sees:
  • The agent’s headshot and name.
  • A one-tap CTA that opens the tokenized survey page.
  • Brokerage info and compliance disclaimers in the footer.
If the agent has not configured a Brand Kit, the template falls back to Winnerr defaults.

The public response page

The survey link in the email opens an unauthenticated, tokenized page:
GET /api/public/survey/:token
The endpoint:
  • Resolves the survey strictly by accessToken, server-side.
  • Returns the question schema plus minimal branding (brokerage name only — never agent PII, never other surveys).
  • Marks the survey OPENED and emits SURVEY_OPENED.
  • Returns a uniform 404 for unknown, expired, completed, or skipped tokens so that guessing learns nothing.
Submissions go to the same URL:
POST /api/public/survey/:token
The server validates the body against the template’s Zod schema, persists a SurveyResponse, flips the survey to COMPLETED, and emits SURVEY_COMPLETED. The response body is size-capped (64 KB) and rate-limited. See the full request and response shapes in the public reputation endpoints.

From response to testimonial

When the response comes in, the reputation response consumer:
  1. Stores the answers (npsScore, csatScore, starRating, free text) on SurveyResponse.
  2. Runs AI sentiment analysis and writes the score back to SurveyResponse.sentiment.
  3. If the client opted in (testimonialOptIn) and the rating is high enough, promotes the response into a Testimonial row with status PENDING and visibility PRIVATE.
  4. Captures the consent snapshot (use name, use photo, public) onto the testimonial.
The testimonial then waits for the agent in the approval inbox. Nothing is public until the agent approves and publishes it.

Manual sends

To send a survey outside of the auto-trigger, POST /api/reputation/surveys with a templateId, recipientPersonId, agentUserId, and optional dealId. The endpoint generates a fresh accessToken, schedules the send, and emits the same downstream events as the auto-flow.
curl -X POST https://api.winnerr.ai/api/reputation/surveys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_123",
    "recipientPersonId": "person_456",
    "agentUserId": "user_789",
    "dealId": "deal_abc",
    "channel": "EMAIL"
  }'

Survey lifecycle

StatusMeaning
SCHEDULEDCreated and waiting for scheduledFor.
SENTEmail or SMS dispatched.
OPENEDRecipient opened the tokenized page.
COMPLETEDA valid SurveyResponse was submitted.
EXPIREDReached expiresAt without a response.
BOUNCEDDelivery failed.
SKIPPEDManually cancelled.