---
updatedAt: 2026-07-07T07:30:13.000Z
agentTools:
  projectIndex: https://docs.getembed.ai/llms.txt
---

# Serving Feeds in Production

Once you've built and tested your algorithms in the [Console](https://console.mbd.xyz), this guide shows you how to serve your feed config to users — with pagination, new item detection, and cache management.

***

## How It Works

When you call the Serve endpoint, the platform:

1. Runs each algorithm in your config
2. Interleaves results according to the weights you set
3. Caches the result
4. Returns the first page of items plus a `served_id` for fetching more pages

```
Console                          Your App
┌──────────────┐
│ Algo A (0.6) │
│ Algo B (0.4) │──── config_id ───▶  POST /deploy/serve
│ Fallbacks    │                           │
│ Cache TTL    │                     ┌─────┴──────┐
└──────────────┘                     │  served_id  │
                                     │  num_pages  │
                                     │  feed[]     │
                                     └─────┬──────┘
                                           │
                              ┌────────────┼────────────┐
                              ▼            ▼            ▼
                        GET /page    GET /new_items   POST /cache/clear
                     (pagination)   (pull to refresh)  (after algo edit)
```

***

## Step 1: Serve Your Feed

Call the Serve endpoint with your `config_id` and user context for personalization.

```bash
curl -X POST https://api.mbd.xyz/v3/studio/deploy/serve \
  -H "Authorization: Bearer mbd-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "config_id": 104,
    "inputs": {
      "farcasterFid": "16085",
      "polymarketWallet": "0x1234..."
    }
  }'
```

**JavaScript:**

```javascript
const response = await fetch('https://api.mbd.xyz/v3/studio/deploy/serve', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mbd-YOUR_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    config_id: 104,
    inputs: {
      farcasterFid: '16085',
      polymarketWallet: '0x1234...'
    }
  })
})

const { result } = await response.json()
```

**Python:**

```python
import requests

response = requests.post(
    'https://api.mbd.xyz/v3/studio/deploy/serve',
    headers={
        'Authorization': 'Bearer mbd-YOUR_KEY',
        'Content-Type': 'application/json'
    },
    json={
        'config_id': 104,
        'inputs': {
            'farcasterFid': '16085',
            'polymarketWallet': '0x1234...'
        }
    }
)

result = response.json()['result']
```

* **config\_id** — your saved feed config ID from the Console
* **inputs** — user context for personalization. Pass `{}` for a non-personalized feed

### Response

```json
{
  "result": {
    "served_id": "707a68e8-2483-4b11-9180-5add8a8ec6e2",
    "served_hash": "02a3ee745b36fea8",
    "num_pages": 8,
    "feed": [
      {
        "_id": "661295",
        "_index": "polymarket-items-v20251126",
        "_source": {
          "question": "Will Bournemouth win the Carabao Cup?",
          "outcome_prices": [0.5, 0.5],
          "volume_1wk": 15000
        }
      }
    ],
    "feeds_ages": {
      "42": 0,
      "43": 3600
    },
    "logs": [],
    "took_algo_building": 120,
    "took_backend": 180
  }
}
```

Save these values from the response:

| Field        | What it's for                                         |
| ------------ | ----------------------------------------------------- |
| `served_id`  | Pass to the Page and New Items endpoints              |
| `num_pages`  | Total pages available — controls your pagination UI   |
| `feed`       | First page of items (default 25 per page)             |
| `feeds_ages` | Cache age in seconds per algorithm. `0` = fresh build |

***

## Step 2: Paginate Through Results

Use the `served_id` from Step 1 to fetch additional pages. Pages are 1-based — page 1 was already returned in the `feed` array.

```bash
curl "https://api.mbd.xyz/v3/studio/deploy/serve/page?served_feed_id=707a68e8-2483-...&page_num=2" \
  -H "Authorization: Bearer mbd-YOUR_KEY"
```

**JavaScript:**

```javascript
const params = new URLSearchParams({
  served_feed_id: result.served_id,
  page_num: String(2)
})

const pageResponse = await fetch(
  `https://api.mbd.xyz/v3/studio/deploy/serve/page?${params}`,
  { headers: { 'Authorization': 'Bearer mbd-YOUR_KEY' } }
)

const { result: pageResult } = await pageResponse.json()
```

### Response

```json
{
  "result": {
    "items": [
      { "_id": "661300", "_source": { "question": "Will Russia capture Shakhove?" } }
    ],
    "new_items": 3
  }
}
```

* **items** — feed items for the requested page
* **new\_items** — optional count of items published since your initial serve

### Infinite Scroll Pattern

```javascript
let currentPage = 1
const allItems = [...result.feed]

async function loadMore() {
  if (currentPage >= result.num_pages) return
  currentPage++

  const params = new URLSearchParams({
    served_feed_id: result.served_id,
    page_num: String(currentPage)
  })

  const res = await fetch(
    `https://api.mbd.xyz/v3/studio/deploy/serve/page?${params}`,
    { headers: { 'Authorization': 'Bearer mbd-YOUR_KEY' } }
  )
  const { result: pageResult } = await res.json()
  allItems.push(...pageResult.items)
}
```

***

## Step 3: Check for New Items

After the initial serve, new content may be published. Use this endpoint to detect new items without re-fetching the entire feed — useful for "X new items available" banners or pull-to-refresh.

```bash
curl "https://api.mbd.xyz/v3/studio/deploy/serve/new_items?served_feed_id=707a68e8-2483-..." \
  -H "Authorization: Bearer mbd-YOUR_KEY"
```

### Response

If new items exist:

```json
{
  "result": {
    "items": [
      { "_id": "new_item_1", "_source": { "question": "Will BTC reach $150k by July?" } }
    ]
  }
}
```

If no new items exist, the API returns HTTP 404 with `{"error": "New items not found"}`. Handle this as "no new items" in your code:

```javascript
const res = await fetch(...)
if (res.status === 404) {
  // No new items — this is normal, not an error
  return []
}
const { result } = await res.json()
return result.items
```

### Polling Pattern

```javascript
function pollForNewItems(servedId, onNewItems, intervalMs = 60000) {
  const poll = async () => {
    const params = new URLSearchParams({ served_feed_id: servedId })
    const res = await fetch(
      `https://api.mbd.xyz/v3/studio/deploy/serve/new_items?${params}`,
      { headers: { 'Authorization': 'Bearer mbd-YOUR_KEY' } }
    )
    if (res.status === 404) return // no new items
    const { result } = await res.json()
    if (result.items && result.items.length > 0) {
      onNewItems(result.items)
    }
  }

  const interval = setInterval(poll, intervalMs)
  return () => clearInterval(interval)
}
```

***

## Step 4: Preview Config Changes

Test different algorithm weights or settings without modifying your saved config:

```javascript
const preview = await fetch('https://api.mbd.xyz/v3/studio/deploy/preview', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mbd-YOUR_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    config: {
      main_algos: [
        { algo_id: 42, weight: 0.7 },
        { algo_id: 43, weight: 0.3 }
      ],
      page_size: 25,
      building_timeout_ms: 300
    },
    inputs: { farcasterFid: '16085' }
  })
})
```

Response is identical to `/serve` — you get a `served_id` and can paginate the preview.

***

## Step 5: Clear Cache After Algorithm Updates

When you update an algorithm in the Console, cached feeds continue serving the previous version until the cache TTL expires. Force a refresh:

```javascript
const clearResponse = await fetch('https://api.mbd.xyz/v3/studio/deploy/cache/clear', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mbd-YOUR_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    feedIds: [42, 43],
    inputs: { farcasterFid: '16085' }
  })
})
```

* **feedIds** — these are **algorithm IDs**, not config IDs
* **inputs** — optional. If provided, only clears the cache for that specific user context

### Response

```json
{
  "result": {
    "42": { "denied": false, "found": 1 },
    "43": { "denied": false, "found": 0 }
  }
}
```

* `found: 1` — cache was cleared
* `found: 0` — no cached version to clear

***

## Handling Cold Starts

If your algorithms take longer than `building_timeout_ms` (default 150ms) to build, the API returns an empty feed:

```json
{ "result": { "feed": [], "num_pages": 0, "served_id": "707a68e8-..." } }
```

**How to handle it:**

1. **Increase the timeout** — set `building_timeout_ms` to 300–500ms in your config
2. **Retry with the served\_id** — the build continues in the background. Wait 1–2 seconds and fetch page 1:

```javascript
const result = await serve(104, inputs)

if (result.feed.length === 0 && result.served_id) {
  await new Promise(resolve => setTimeout(resolve, 2000))

  const params = new URLSearchParams({
    served_feed_id: result.served_id,
    page_num: '1'
  })
  const retryResponse = await fetch(
    `https://api.mbd.xyz/v3/studio/deploy/serve/page?${params}`,
    { headers: { 'Authorization': 'Bearer mbd-YOUR_KEY' } }
  )
  const { result: retryResult } = await retryResponse.json()
}
```

3. **Show a loading state** — display a skeleton UI rather than "no results found"

***

## Debugging Multi-Algorithm Configs

When your config has two or more algorithms, the serve response doesn't indicate which algorithm produced which item. To debug:

1. **Check `feeds_ages`** — shows cache age per algorithm ID. `0` = fresh, any other value = cached.
2. **Preview each algo separately** — use `/deploy/preview` with one algorithm at a time:

```javascript
// Test algo 42 alone
const algoA = await preview({
  main_algos: [{ algo_id: 42, weight: 1.0 }]
}, inputs)

// Test algo 43 alone
const algoB = await preview({
  main_algos: [{ algo_id: 43, weight: 1.0 }]
}, inputs)
```

3. **Check the logs** — the `logs` array in the response may contain debugging output from your algorithm code.

***

## Complete Example

```javascript
const API_BASE = 'https://api.mbd.xyz/v3/studio/deploy'
const API_KEY = 'mbd-YOUR_KEY'
const headers = {
  'Authorization': `Bearer ${API_KEY}`,
  'Content-Type': 'application/json'
}

// 1. Serve the feed
const serveResponse = await fetch(`${API_BASE}/serve`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    config_id: 104,
    inputs: { farcasterFid: '16085' }
  })
})
const { result } = await serveResponse.json()
console.log(`Page 1: ${result.feed.length} items, ${result.num_pages} total pages`)

// 2. Fetch remaining pages
for (let page = 2; page <= result.num_pages; page++) {
  const params = new URLSearchParams({
    served_feed_id: result.served_id,
    page_num: String(page)
  })
  const pageResponse = await fetch(`${API_BASE}/serve/page?${params}`, { headers })
  const { result: pageResult } = await pageResponse.json()
  console.log(`Page ${page}: ${pageResult.items.length} items`)
}

// 3. Poll for new items every 60 seconds
setInterval(async () => {
  const params = new URLSearchParams({ served_feed_id: result.served_id })
  const res = await fetch(`${API_BASE}/serve/new_items?${params}`, { headers })
  const { result: newItems } = await res.json()
  if (newItems.items?.length) {
    console.log(`${newItems.items.length} new items since last serve`)
  }
}, 60000)
```

**Python:**

```python
import requests
import time

API_BASE = 'https://api.mbd.xyz/v3/studio/deploy'
headers = {
    'Authorization': 'Bearer mbd-YOUR_KEY',
    'Content-Type': 'application/json'
}

# 1. Serve the feed
serve_response = requests.post(f'{API_BASE}/serve', headers=headers, json={
    'config_id': 104,
    'inputs': {'farcasterFid': '16085'}
})
result = serve_response.json()['result']
print(f"Page 1: {len(result['feed'])} items, {result['num_pages']} total pages")

# 2. Fetch remaining pages
for page in range(2, result['num_pages'] + 1):
    page_response = requests.get(f'{API_BASE}/serve/page', headers=headers, params={
        'served_feed_id': result['served_id'],
        'page_num': page
    })
    items = page_response.json()['result']['items']
    print(f"Page {page}: {len(items)} items")

# 3. Check for new items
new_items_response = requests.get(f'{API_BASE}/serve/new_items', headers=headers, params={
    'served_feed_id': result['served_id']
})
new_items = new_items_response.json()['result']['items']
print(f"{len(new_items)} new items since last serve")
```

***

## What's Next

* **[Feed Deployment Status →](../Feeds/deploy-status)** — Understand warmup tiers (Draft, Group, Live)
* **[Feed Configs →](../Feeds/deploy-feed-configs)** — Create and manage feed configurations
* **[API Reference: Feed Serving](/reference/Deployments/serving/deployserve)** — Full endpoint specifications
* **\[Quickstart: Algorithm DSL]\(../Getting Started/quickstart-studio-sdk)** — Build custom pipelines