Documentation

From first form to a published wall.

Everything you need to collect testimonials, approve them, and show them where prospects decide.

Getting started

  1. Create an account and a project for your brand.
  2. Create a collection form. Customize the questions, branding, consent wording, and optional reward, then publish it.
  3. Share the form link, or invite customers by email from the form's Invites tab.
  4. Review new submissions in Testimonials and approve the ones you want to show.
  5. Publish a wall or create a widget and embed it on your site.

Collecting testimonials

Forms collect a rating plus a written or video answer. Video can be recorded in the browser or uploaded; it is converted to web formats automatically, and you can retry processing from the testimonial page if it fails.

Invites. Paste up to 100 customers at a time, one per line, as email, Name <email>, or Name, email. Each person gets a personal link, reminders follow on the days you choose, and they stop once someone responds or unsubscribes.

Consent. Respondents choose whether their testimonial may be shown publicly. Only approved testimonials with public consent appear on walls and widgets.

Imports. Add testimonials manually or from a CSV file in Imports.

Walls and widgets

A wall is a hosted page at /your-project showing your approved testimonials. Pick a template, then choose testimonials automatically (by rating, type, or tag) or by hand. Additional walls live at /your-project/wall-slug.

Widgets show testimonials inside your own site: carousels, grids, marquees, rating badges, and floating popups or toasts.

Embedding on your site

Copy the snippet from a widget's Embed panel. It looks like this:

<div data-wol-widget="YOUR_WIDGET_ID"></div>
<script async src="https://walloflove.net/widget.js"></script>

To embed a collection form instead, use data-wol-form="your-form-slug". You can also use the web component <wall-of-love widget-id="…"></wall-of-love>. Widgets size themselves to their content; popups and toasts float in the corner you configured.

Custom domains (Pro)

In Project settings → Domain, add a hostname such as love.yourcompany.com, create the CNAME record shown there with your DNS provider, then click Verify. Once the certificate is issued, your default wall is served at the root of that domain and other walls at /wall-slug.

REST API (Pro)

Create a key in Integrations → API and send it as a bearer token. Keys are shown once; store them securely. A key acts with the permissions of the person who created it, inside its project only, and allows 1,000 requests per hour.

curl https://walloflove.net/api/v1/testimonials?status=approved&limit=25 \
  -H "Authorization: Bearer wol_live_…"

curl -X POST https://walloflove.net/api/v1/forms \
  -H "Authorization: Bearer wol_live_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"Customer love","slug":"customer-love"}'

Responses are JSON: { data } on success, or { error } with a code such as INVALID_INPUT (400), INVALID_API_KEY (401), PRO_PLAN_REQUIRED (402), FORBIDDEN (403), …_NOT_FOUND (404), SLUG_TAKEN (409), or RATE_LIMITED (429). Lists page with limit and the nextCursor you get back as cursor.

EndpointWhat it doesAccess
GET /api/v1/projectThe connected project: name, slug, and settings.Read
GET /api/v1/overviewDashboard overview for the last 30 days: testimonial counts by status, recent submissions, forms, walls, widgets, and invite totals.Read
GET /api/v1/analyticsViews and interactions for forms, walls, and widgets over the last N days (default 30).Read
GET /api/v1/testimonialsPage through every testimonial in the project, including pending and hidden ones. Filter by status (pending, approved, hidden), type, minimum rating, or full-text search. Follow nextCursor for more.Read
GET /api/v1/testimonials/{testimonialId}One testimonial with its media URLs, tags, and the form answers it came from.Read
POST /api/v1/testimonialsAdd a text testimonial you collected elsewhere (email, call notes, a review site). It starts as pending until approved.Write
PATCH /api/v1/testimonials/{testimonialId}Correct a testimonial's text, title, excerpt, rating, transcript, or customer details. Only change wording the customer approved.Write
POST /api/v1/testimonials/{testimonialId}/approveApprove a testimonial so it can appear on walls and widgets.Write
POST /api/v1/testimonials/{testimonialId}/unapproveMove an approved testimonial back to pending; it disappears from walls and widgets.Write
POST /api/v1/testimonials/{testimonialId}/restoreRestore a testimonial from the trash.Write
DELETE /api/v1/testimonials/{testimonialId}Move a testimonial to the trash. It can be restored with restore_testimonial. Confirm with the user first.Write
GET /api/v1/trashTestimonials in the trash, which can still be restored.Read
PUT /api/v1/testimonials/{testimonialId}/tags/{tagId}Add an existing tag to any testimonial in the project.Write
DELETE /api/v1/testimonials/{testimonialId}/tags/{tagId}Remove a tag from a testimonial.Write
GET /api/v1/tagsAll tags with their categories, colors, and usage counts.Read
POST /api/v1/tagsCreate a tag with an optional category, description, color, and emoji.Write
PATCH /api/v1/tags/{tagId}Rename a tag or change its category, description, color, or emoji.Write
DELETE /api/v1/tags/{tagId}Delete a tag and remove it from every testimonial. Confirm with the user first.Write
GET /api/v1/formsEvery collection form with its status, public link, and folder.Read
GET /api/v1/forms/{formId}A form's settings, questions in order, reward, and public link.Read
POST /api/v1/formsCreate a collection form. The slug is its public link (walloflove.net/{project}/f/{slug}); it starts as a draft until published.Write
PATCH /api/v1/forms/{formId}Update any of a form's settings and copy. Fields: name, collectVideo, collectText, responseMode, maxVideoDurationSec, ratingPlacement, labels, pageSettings, brandColor, buttonColor, textColor, backgroundColor, fontFamily, poweredByEnabled, welcomeTitle, welcomeSubtitle, welcomeCtaLabel, aboutYouTitle, aboutYouSubtitle, consentTitle, consentSubtitle, consentPublicLabel, consentPrivateLabel, thankYouTitle, thankYouSubtitle, requireName, collectEmail, requireEmail, collectPhone, requirePhone, collectPhoto, requirePhoto, collectCompany, requireCompany, collectTitle, requireTitle, collectWebsite, collectSocials, language, autoApprove, autoApproveMinRating, autoTagIds, transcribeVideos, translateSubmissions, inviteSubject, inviteBody, inviteCtaLabel, inviteReminderDays, thankYouEmailEnabled, thankYouEmailSubject, thankYouEmailBody, fromName, replyToEmail.Write
POST /api/v1/forms/{formId}/publishPublish a form so its public link accepts testimonials.Write
POST /api/v1/forms/{formId}/closeClose a published form; its link stops accepting testimonials.Write
DELETE /api/v1/forms/{formId}Delete a form. Its testimonials are kept. Confirm with the user first.Write
GET /api/v1/forms/{formId}/submissionsRaw submissions received by a form, newest first.Read
POST /api/v1/forms/{formId}/questionsAdd a question to a form. Types: primary, text, longText, video, videoOrText, rating, singleSelect (with options).Write
PATCH /api/v1/forms/{formId}/questions/{questionId}Change a question's title, subtitle, placeholder, options, tips, or turn it off.Write
DELETE /api/v1/forms/{formId}/questions/{questionId}Remove a question from a form.Write
PUT /api/v1/forms/{formId}/questions/orderSet the order of a form's questions by listing every question ID in order.Write
PUT /api/v1/forms/{formId}/rewardOffer a thank-you reward after submission: none, coupon (couponCode), externalLink (externalUrl), or spinTheWheel. Pro feature.Write
GET /api/v1/forms/{formId}/invitesCustomers invited to a form by email, with delivery and reminder status.Invites
POST /api/v1/forms/{formId}/invitesEmail up to 100 customers a personal link to a published form, with automatic reminders. Only invite people who agreed to hear from the business. Always confirm the list with the user first.Invites
GET /api/v1/wallsEvery Wall of Love, published or not, with its public link.Read
GET /api/v1/walls/{wallId}A wall's settings, design, testimonial selection, and public link.Read
POST /api/v1/wallsCreate a Wall of Love page at walloflove.net/{project}/{slug}. It starts unpublished.Write
PATCH /api/v1/walls/{wallId}Update a wall's settings, design, and testimonial selection. Fields: name, templateId, selectionMode (auto|manual), autoFilter, manualOrder, pinnedTestimonialIds, sortOrder, design, customCss, removeBranding, heroTitle, heroSubtitle, heroCta, inlineCta, seoTitle, seoDescription, richSnippetsEnabled.Write
POST /api/v1/walls/{wallId}/publishPublish a wall at its public link.Write
POST /api/v1/walls/{wallId}/unpublishTake a wall offline.Write
DELETE /api/v1/walls/{wallId}Delete a wall. Confirm with the user first.Write
GET /api/v1/widgetsEvery embeddable widget with its template and embed code.Read
GET /api/v1/widgets/{widgetId}A widget's full configuration and its embed code.Read
POST /api/v1/widgetsCreate a widget from a template; it shows approved testimonials automatically.Write
PATCH /api/v1/widgets/{widgetId}Update a widget's settings, design, and testimonial selection. Fields: name, templateId, embedLocationNote, selectionMode (auto|manual), autoFilter, manualTestimonialIds, pinnedTestimonialIds, sortOrder, maxItems, design, customCss, removeBranding, popupConfig.Write
DELETE /api/v1/widgets/{widgetId}Delete a widget; sites embedding it will show nothing. Confirm with the user first.Write
GET /api/v1/brand-kitBrand colors (by role) and fonts used across forms, walls, and widgets.Read
PATCH /api/v1/brand-kitReplace brand colors and/or fonts. Colors: [{ role: primary|accent|text|rating|custom, hex: "#rrggbb" }]. Fonts: [{ role: heading|body, family }].Write
GET /api/v1/import-sourcesConnected review sites (G2, Trustpilot, Capterra, ...) and their last sync.Read
POST /api/v1/import-sources/{sourceId}/syncPull new reviews from a connected review site right away. Pro feature.Write

AI assistants (MCP)

Connect Claude, ChatGPT, or any assistant that supports remote MCP servers to https://walloflove.net/mcp. Sign in, pick a project, and choose what it may do: read approved public proof (always), see the whole workspace, make changes, or email customers invites. MCP is included on every plan, and you can revoke a connection anytime under Integrations → MCP.

With workspace access, an assistant can use the same operations as the REST API, except that respondents' email addresses are never shared with it:

get_projectget_overviewget_analyticslist_testimonialsget_testimonial_detailscreate_testimonialupdate_testimonialapprove_testimonialunapprove_testimonialrestore_testimonialdelete_testimoniallist_trashadd_testimonial_tagremove_testimonial_tagupdate_tagdelete_taglist_formsget_formcreate_formupdate_formpublish_formclose_formdelete_formlist_form_submissionsadd_form_questionupdate_form_questiondelete_form_questionreorder_form_questionsset_form_rewardlist_form_invitessend_form_inviteslist_all_wallsget_wallcreate_wallupdate_wallpublish_wallunpublish_walldelete_wallget_widgetupdate_widgetdelete_widgetget_brand_kitupdate_brand_kitlist_import_sourcessync_import_source

Webhooks

Add an HTTPS endpoint in Integrations → Webhooks (Pro) and choose events: testimonial.created, testimonial.updated, testimonial.approved, testimonial.deleted, form.submission, form.published, and wall.published. Failed deliveries are retried with backoff.

Each request carries x-wall-of-love-event, x-wall-of-love-delivery, and x-wall-of-love-signature: t=TIMESTAMP,v1=HEX. To verify, compute HMAC-SHA256 of TIMESTAMP.RAW_BODY with your signing secret and compare it to v1.