# API reference

> All public endpoints: list posts, get post, RSS, JSON Feed, sitemap, errors. With request/response shapes and per-language snippets.

The Mentionwell public API is small, RESTful, and read-only. Two endpoints cover almost every integration; three more give you syndication feeds.

## Base URL

```text
https://mentionwell.com
```

Self-hosted deployments use their own origin. Set this in `MENTIONWELL_API_URL` on your destination site.

## Conventions

- **Auth:** `Authorization: Bearer <site-api-key>` on the `/api/public/*` endpoints. Feeds and sitemaps are open.
- **Content type:** `application/json` (or `application/rss+xml` / `application/feed+json` / `application/xml` for feeds and sitemap).
- **Timestamps:** ISO-8601, UTC.
- **Caching:** post endpoints return `Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=600`.
- **CORS:** `Access-Control-Allow-Origin: *`, with `OPTIONS` preflight support.
- **Envelope:** every JSON response is `{ "ok": boolean, ... }`. On error, `ok: false` with a `message` field.

---

## List posts

```text
GET /api/public/{siteSlug}/posts
```

Returns up to `limit` published posts for one site, newest first. Use this for your `/blog` index page.

### Path parameters

| Name | Type | Description |
|---|---|---|
| `siteSlug` | string (required) | The slug of your site, as shown in the dashboard URL. |

### Query parameters

| Name | Type | Description |
|---|---|---|
| `limit` | integer (optional) | Maximum posts to return. Default `20`, max `100`. Clamped server-side. |

### Example — cURL

```bash
curl https://mentionwell.com/api/public/your-site-slug/posts?limit=12 \
  -H "Authorization: Bearer bgo_read_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

### Example — JavaScript

```ts
const res = await fetch(
  `${process.env.MENTIONWELL_API_URL}/api/public/${siteSlug}/posts?limit=12`,
  {
    headers: { Authorization: `Bearer ${process.env.MENTIONWELL_API_KEY}` },
    next: { revalidate: 300, tags: ["mentionwell:posts"] }
  }
);
const { posts } = await res.json();
```

### Example — Python

```python
import os, httpx

r = httpx.get(
  f"{os.environ['MENTIONWELL_API_URL']}/api/public/{site_slug}/posts",
  params={"limit": 12},
  headers={"Authorization": f"Bearer {os.environ['MENTIONWELL_API_KEY']}"}
)
posts = r.json()["posts"]
```

### Response

```json
{
  "ok": true,
  "site": { "slug": "your-site-slug", "name": "Your Site", "domain": "yoursite.com" },
  "posts": [
    {
      "slug": "five-questions-to-ask-before-you-buy",
      "title": "Five Questions to Ask Before You Buy",
      "excerpt": "A short, scannable summary that drops into your card UI.",
      "metaDescription": "150-character SEO description.",
      "featuredImage": "https://cdn.mentionwell.com/.../hero.jpg",
      "readingTime": 7,
      "tags": ["buying", "first-home"],
      "category": { "title": "Buying", "slug": "buying" },
      "publishedAt": "2026-04-21T15:00:00.000Z",
      "updatedAt": "2026-04-21T15:00:00.000Z",
      "author": { "name": "Editorial Team", "avatarUrl": null, "url": null },
      "canonicalUrl": null
    }
  ]
}
```

The list endpoint omits heavy fields (`html`, `markdown`, `tldr`, `toc`, `faqs`, `jsonLd`) to keep payloads small. Fetch the detail endpoint for those.

---

## Get post

```text
GET /api/public/{siteSlug}/posts/{slug}
```

Returns the full post: HTML body, table of contents, FAQ, JSON-LD, author block. Use for `/blog/[slug]` detail pages.

### Path parameters

| Name | Type | Description |
|---|---|---|
| `siteSlug` | string (required) | The slug of your site. |
| `slug` | string (required) | The slug of a published post. |

### Example

```bash
curl https://mentionwell.com/api/public/your-site-slug/posts/five-questions-to-ask-before-you-buy \
  -H "Authorization: Bearer bgo_read_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

### Response

```json
{
  "ok": true,
  "post": {
    "slug": "five-questions-to-ask-before-you-buy",
    "title": "Five Questions to Ask Before You Buy",
    "metaTitle": "Five Questions to Ask Before You Buy a Home | Your Site",
    "metaDescription": "Short SEO description.",
    "excerpt": "...",
    "html": "<header class=\"wb-header\">...</header><section class=\"wb-section\">...</section>",
    "markdown": "# Five Questions...\n\n...",
    "featuredImage": "https://cdn.mentionwell.com/.../hero.jpg",
    "readingTime": 7,
    "tags": ["buying", "first-home"],
    "category": { "title": "Buying", "slug": "buying" },
    "publishedAt": "2026-04-21T15:00:00.000Z",
    "updatedAt": "2026-04-21T15:00:00.000Z",
    "author": { "name": "Editorial Team", "avatarUrl": null, "url": null },
    "tldr": { "items": ["Takeaway 1", "Takeaway 2", "Takeaway 3"] },
    "toc": [{ "id": "intro", "title": "Introduction", "level": 2 }],
    "faqs": [{ "question": "Is now a good time to buy?", "answer": "..." }],
    "canonicalUrl": null,
    "jsonLd": "{\"@context\":\"https://schema.org\",\"@type\":\"Article\",...}"
  }
}
```

---

## RSS feed

```text
GET /api/sites/{siteSlug}/feed.xml
```

Standard RSS 2.0. Public, no authentication. Add it to your `<head>`:

```html
<link rel="alternate" type="application/rss+xml"
      title="Your Site Blog"
      href="https://mentionwell.com/api/sites/your-site-slug/feed.xml" />
```

## JSON Feed

```text
GET /api/sites/{siteSlug}/feed.json
```

[JSON Feed 1.1](https://www.jsonfeed.org/) format. Useful for n8n / Zapier / Make automations and AI ingestion pipelines.

## Sitemap

```text
GET /api/sites/{siteSlug}/sitemap.xml
```

Standard sitemap.xml. Submit to Google Search Console and Bing Webmaster Tools.

---

## Errors

All errors return a JSON envelope:

```json
{ "ok": false, "message": "Human-readable description." }
```

| Status | Meaning | What to do |
|---|---|---|
| `400` | Malformed request | Check the path and query parameters against this reference. |
| `401` | Unauthorized | Missing or wrong `Authorization` header. |
| `404` | Site or post not found | Verify the slug; treat as a normal no-result state in your UI. |
| `5xx` | Origin error | Retry with exponential backoff. Cached responses still serve via SWR. |

## Versioning

The public API is currently un-versioned because additive changes only. If a breaking change ever ships, it will land at a new path prefix and the existing one will continue to serve.


---

Canonical URL: https://mentionwell.com/docs/api
Live HTML version: https://mentionwell.com/docs/api
Section: API reference
Site index for AI ingestion: https://mentionwell.com/llms.txt
Full reference: https://mentionwell.com/llms-full.txt
