> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uppzy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Playbook: Content Sync

> Publish approved CMS, FAQ, policy, and support content into Uppzy through the M2M document endpoints.

This playbook is for systems that keep source content in a CMS, help center, product catalog, or internal knowledge tool and need to publish approved content into Uppzy.

Use this for content that is safe to answer from:

* Public help center articles
* Approved policy pages
* Support macros
* FAQ entries
* Product care or setup guides

Do not sync secrets, private credentials, raw payment data, or private customer records.

## Flow

1. Select approved source records
2. Normalize each record into a document payload
3. Send text or Q\&A documents to Uppzy
4. Store source IDs and returned document IDs in your own sync log
5. Run a smoke chat after each content batch
6. Review statistics and feedback after rollout

## Choose the document type

Use text documents when the source is article-like content.

```json theme={null}
{
  "title": "Shipping Policy",
  "content": "Orders are shipped according to the published shipping policy.",
  "category": "policy"
}
```

Use Q\&A documents when the source is a direct question and answer.

```json theme={null}
{
  "title": "Same-day Delivery FAQ",
  "question": "Do you offer same-day delivery?",
  "answer": "Same-day delivery availability depends on location and order timing.",
  "category": "delivery"
}
```

## CMS sync example

This example maps CMS records to text documents. It assumes your CMS client returns only approved records.

```js theme={null}
import { uppzy } from "./uppzy-client.js";
import { listApprovedArticles, markSynced } from "./cms-client.js";

const SITE_ID = process.env.UPPZY_SITE_ID;

function toTextDocument(article) {
  return {
    title: article.title,
    content: article.bodyText,
    category: article.section || "cms",
  };
}

export async function syncApprovedArticles() {
  const articles = await listApprovedArticles();

  for (const article of articles) {
    const payload = toTextDocument(article);

    const document = await uppzy(`/m2m/sites/${SITE_ID}/documents/text`, {
      method: "POST",
      body: payload,
    });

    await markSynced(article.id, {
      uppzy_document_id: document?.id,
      synced_at: new Date().toISOString(),
    });
  }
}
```

## FAQ sync example

Use Q\&A documents for short direct answers.

```js theme={null}
import { uppzy } from "./uppzy-client.js";
import { listApprovedFaqs } from "./cms-client.js";

const SITE_ID = process.env.UPPZY_SITE_ID;

export async function syncFaqs() {
  const faqs = await listApprovedFaqs();

  for (const faq of faqs) {
    await uppzy(`/m2m/sites/${SITE_ID}/documents/qa`, {
      method: "POST",
      body: {
        title: faq.title,
        question: faq.question,
        answer: faq.answer,
        category: faq.category || "faq",
      },
    });
  }
}
```

## Batch safety

Keep content sync predictable:

* Sync a small first batch before a full import
* Keep a source-to-document mapping in your own database
* Avoid syncing draft, archived, or unapproved records
* Normalize HTML into readable text before sending it
* Remove tracking snippets, raw IDs, hidden content, and unrelated markup
* Run smoke questions after each batch

## Smoke test after sync

Run a known question after a content sync and check whether the answer uses the expected content.

```js theme={null}
import { uppzy } from "./uppzy-client.js";

const SITE_ID = process.env.UPPZY_SITE_ID;

export async function smokeTestContentSync() {
  return uppzy(`/m2m/sites/${SITE_ID}/chat`, {
    method: "POST",
    body: {
      session_id: `content_sync_${Date.now()}`,
      message: "What is the shipping policy?",
      response_language: "en",
    },
  });
}
```

## Rollout checklist

* Sync only approved customer-facing content
* Start with text and Q\&A documents before large file batches
* Keep source IDs in your own sync log
* Run a smoke chat after each batch
* Review low-confidence answers and update the source content first
