API Documentation

REST API Reference

Access your ChatFeatured articles programmatically. List articles by status, fetch individual articles, publish from review, and receive webhook notifications.

Authentication

All API requests require authentication via an API key. You can create an API key from the Integrations > REST API page in your dashboard.

Pass your API key using either method:

# Bearer token (recommended)
curl https://chatfeatured.com/api/v1/articles \
  -H "Authorization: Bearer cf_your_api_key"

# x-api-key header
curl https://chatfeatured.com/api/v1/articles \
  -H "x-api-key: cf_your_api_key"

Keep your API key secret. Do not expose it in client-side code or public repositories. If compromised, you can regenerate it from the dashboard.

Base URL

https://chatfeatured.com/api/v1

Endpoints

GET/api/v1/articles

List articles for your brand, filtered by status.

Query Parameters

ParameterTypeRequiredDescription
statusstringNoFilter by status: "published" (default), "review", or "scheduled"
limitnumberNoNumber of articles to return (default: 20, max: 100)
offsetnumberNoNumber of articles to skip for pagination (default: 0)

Example

curl "https://chatfeatured.com/api/v1/articles?status=review&limit=10" \
  -H "Authorization: Bearer cf_your_api_key"

Response

{
  "data": [
    {
      "id": "abc123",
      "title": "How to Optimize for AI Search",
      "slug": "how-to-optimize-for-ai-search",
      "status": "review",
      "excerpt": "A comprehensive guide...",
      "metaDescription": "Learn how to optimize...",
      "content": "<p>HTML content...</p>",
      "featuredImageUrl": "https://example.com/image.jpg",
      "scheduledAt": null,
      "publishedAt": null,
      "priority": "medium",
      "wordCount": 1200,
      "readingTimeMinutes": 5,
      "createdAt": "2026-03-19T10:00:00.000Z",
      "updatedAt": "2026-03-20T12:00:00.000Z",
      "metadata": {
        "articleType": "guide",
        "description": "A comprehensive guide to AI search optimization"
      }
    }
  ],
  "pagination": {
    "total": 42,
    "limit": 10,
    "offset": 0,
    "hasMore": true
  }
}
GET/api/v1/articles/:idOrSlug

Fetch a single article by ID or slug.

Path Parameters

ParameterTypeRequiredDescription
idOrSlugstringYesThe article ID or slug

Example

curl "https://chatfeatured.com/api/v1/articles/how-to-optimize-for-ai-search" \
  -H "Authorization: Bearer cf_your_api_key"

Response

{
  "data": {
    "id": "abc123",
    "title": "How to Optimize for AI Search",
    "slug": "how-to-optimize-for-ai-search",
    "status": "published",
    "excerpt": "A comprehensive guide...",
    "metaDescription": "Learn how to optimize...",
    "content": "<p>Full HTML content of the article...</p>",
    "featuredImageUrl": "https://example.com/image.jpg",
    "scheduledAt": null,
    "publishedAt": "2026-03-20T12:00:00.000Z",
    "priority": "medium",
    "wordCount": 1200,
    "readingTimeMinutes": 5,
    "createdAt": "2026-03-19T10:00:00.000Z",
    "updatedAt": "2026-03-20T12:00:00.000Z",
    "metadata": {
      "articleType": "guide",
      "description": "A comprehensive guide to AI search optimization"
    }
  }
}
POST/api/v1/articles/:idOrSlug/publish

Publish an article. Only articles in "review" status can be published.

Path Parameters

ParameterTypeRequiredDescription
idOrSlugstringYesThe article ID or slug of the article to publish

Example

curl -X POST "https://chatfeatured.com/api/v1/articles/abc123/publish" \
  -H "Authorization: Bearer cf_your_api_key"

Response

{
  "success": true,
  "data": {
    "id": "abc123",
    "status": "published",
    "publishedAt": "2026-03-20T12:00:00.000Z"
  }
}

Error Responses

All errors return a JSON object with an error field:

{
  "error": "Article not found"
}
StatusMeaning
401Missing or invalid API key
400Invalid request (e.g. publishing an article not in review)
404Article not found
500Internal server error

Webhooks

Configure webhooks from the Integrations > REST API page to receive real-time notifications when articles change status. You can enable notifications for two events independently.

Events

EventDescription
article.reviewFired when an article finishes generating and is ready for review
article.publishedFired when an article is published (manually, via API, or via schedule)

Payload

Webhooks are sent as POST requests with a JSON body:

{
  "event": "article.published",
  "timestamp": "2026-03-20T12:00:00.000Z",
  "data": {
    "id": "abc123",
    "title": "How to Optimize for AI Search",
    "slug": "how-to-optimize-for-ai-search",
    "status": "published",
    "excerpt": "A comprehensive guide...",
    "metaDescription": "Learn how to optimize...",
    "content": "<p>Full HTML content...</p>",
    "featuredImageUrl": "https://example.com/image.jpg",
    "scheduledAt": null,
    "publishedAt": "2026-03-20T12:00:00.000Z",
    "priority": "medium",
    "wordCount": 1200,
    "readingTimeMinutes": 5,
    "createdAt": "2026-03-19T10:00:00.000Z",
    "updatedAt": "2026-03-20T12:00:00.000Z",
    "metadata": {
      "articleType": "guide",
      "description": "A comprehensive guide to AI search optimization"
    }
  }
}

Signature Verification

If you configure a signing secret, every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the request body signed with your secret.

// Node.js example
import { createHmac } from "crypto";

function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return signature === expected;
}

// In your webhook handler
app.post("/webhooks/chatfeatured", (req, res) => {
  const signature = req.headers["x-webhook-signature"];
  const body = JSON.stringify(req.body);

  if (!verifyWebhook(body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send("Invalid signature");
  }

  const { event, data } = req.body;

  switch (event) {
    case "article.review":
      console.log(`Article "${data.title}" is ready for review`);
      break;
    case "article.published":
      console.log(`Article "${data.title}" has been published`);
      break;
  }

  res.status(200).send("OK");
});

Tip: Webhooks have a 10-second timeout. If your endpoint doesn't respond in time, the delivery is considered failed. Make sure your handler responds quickly — process the payload asynchronously if needed.