Skip to content
Plauditlyplauditly
← PlauditlyDevelopers

A public API your CTO will approve.

Every Plauditly widget is backed by a single JSON endpoint anyone can hit. No API key. No SDK to install. No rate-limit headers to debug at 2 AM. If you can write fetch(), you can build whatever the embed widget doesn't.

Auth

None required

Public read endpoint. Treat the widget public_id as the access token; rotate it from the dashboard if it leaks.

Cache

5 min edge

Cloudflare-grade edge caching with stale-while-revalidate. Busts the instant you approve, edit, or hide a testimonial.

Format

JSON, typed

Stable shape with semantic versioning at the URL level. Breaking changes ship at /api/widgets/v2/ — never inline.

The endpoint

One route. Accepts either a widget public ID (wgt_…) or a project slug for backwards compatibility.

Request
curl https://plauditly.app/api/widgets/wgt_YOUR_ID
Response
{
  "project": {
    "name": "Latitude",
    "slug": "latitude",
    "brand_color": "#e0492a"
  },
  "widget": {
    "public_id": "wgt_a8f3c…",
    "type": "wall",
    "config": { "count": 50, "accent": "#e0492a" },
    "showBadge": false
  },
  "testimonials": [
    {
      "id": "tst_a1b2c3…",
      "author_name": "Sarah Chen",
      "author_role": "Founder",
      "author_company": "Latitude",
      "rating": 5,
      "body": "Wired up Plauditly in twelve minutes…",
      "pinned": false,
      "created_at": "2026-05-12T14:22:01Z"
    }
  ]
}

Privacy invariant: author_email is collected on the form but structurally absent from this response — it lives in a separate column the public API never reads. Adding it to a response would be a security regression, not a feature request.

In your language

JavaScript / TypeScript
// Fetch in any JS runtime — Node, browser, Bun, Deno.
const res = await fetch("https://plauditly.app/api/widgets/wgt_YOUR_ID");
const { project, testimonials } = await res.json();
console.log(`${testimonials.length} testimonials for ${project.name}`);
Python
import httpx

r = httpx.get("https://plauditly.app/api/widgets/wgt_YOUR_ID")
data = r.json()
print(f"{len(data['testimonials'])} testimonials for {data['project']['name']}")
React Server Components
// React Server Component example — re-validates every 5 minutes
async function Wall() {
  const res = await fetch("https://plauditly.app/api/widgets/wgt_YOUR_ID", {
    next: { revalidate: 300 },
  });
  const { testimonials } = await res.json();
  return (
    <ul>
      {testimonials.map((t) => (
        <li key={t.id}>
          <p>{t.body}</p>
          <small>{t.author_name}</small>
        </li>
      ))}
    </ul>
  );
}

Rate limits & abuse handling

  • Reads: unmetered. Edge cache absorbs traffic spikes; your database stays quiet even when your customer's landing page goes viral on Hacker News.
  • Writes: the public submission endpoint (POST /api/submissions) is honeypot-protected and rate-limited per IP. Suspicious traffic gets soft-rejected — never silently dropped.
  • Abuse: if you spot a leaked widget ID being used to scrape testimonials beyond your intent, rotate it from the dashboard — old ID returns 410 Gone within 60 seconds.

Beyond the embed

The embed widget is one consumer of this API. Other things you can build with the same endpoint:

  • Static-site bake-in: fetch at build time, render HTML directly into your Astro/Hugo/Eleventy output. Zero client-side JS, perfect Lighthouse.
  • RSS / OPML of praise: turn your wall into an RSS feed for changelog aggregators or customer-success dashboards.
  • Slack/Discord notifier: poll the endpoint, post a message every time a new approved testimonial appears.
  • Investor / board updates: drop the JSON into a Notion page or board doc — proof of customer love, sourced from production.

More docs

Create a widget to get an ID