---
title: The Manifest anatomy field guide
category: read
summary: Every part of a Manifest, which date means what, which fields to show people, and a defensive accessor that never breaks on a missing field.
order: 12
updated: 2026-10-07
next: signals-briefs-and-records
related: signals-briefs-and-records, present-manifests-to-your-users
reference: /docs/api, /openapi.json
---

A Manifest is one source item, delivered with everything needed to use it and cite it. It has a stable shape, but not every field is present on every item. Learn what each field is for. Read each field safely when it is absent.

## When to use this

Use it when you are writing code that consumes Manifests, deciding what to show your user, or debugging why a field you expected is missing.

## Smallest working call

Read one Manifest and inspect its keys. A direct read by ID returns only Manifests that are eligible for publication now:

```bash
curl -sS "https://api.synorb.com/manifests/by-id/MANIFEST_ID" \
  -H "Authorization: Bearer $SYNORB_KEY"
```

Or take a small page and look at the first item:

```mcp billed
synorb-manifests
{"stream_ids": ["STREAM_ID"], "days": 2, "target_count": 2, "compact": false}
```

## What you get back

### The top level

| Field | Meaning |
| --- | --- |
| `manifest_id`, `record_id` | Strings. `manifest_id` is the identity you dedupe on. |
| `stream_ids`, `stream_names` | Every Stream the item routed to. One item can sit in several. |
| `published_date` | The strict Stream publication date. **This is what `days` and date bounds measure.** |
| `matched_at` | When it was routed. Often identical across a batch, so it is not a publication time. |
| `source` | Where it came from. See below. |
| `signal` | The Claims view. |
| `brief` | The human narrative. Included on every plan. |
| `record` | The source text (plan-gated). |
| `tag_ids`, `tag_names`, `tag_types`, `subtypes`, `tag_quality` | What the item is about |
| `citations` | When present, evidence metadata that is separate from the item link. A zero count does not mean the item link is missing |

Deliveries also carry `presentation_items[]` (display-ready, one per Manifest) and a `render` hint. The presentation guide covers them.

### The four dates

| Field | What it is | Show it to users? |
| --- | --- | --- |
| `published_date` | Stream publication date; the basis of every window | Yes, by default |
| `source.source_published_date` | The upstream source's own date and time | Yes, when you want the original timestamp |
| `matched_at` | Routing time | No |
| `source.synorb_ingested_at` | When Synorb ingested it | Rarely |

### `source`: provenance

| Field | Use |
| --- | --- |
| `source_name`, `source_channel_display`, `source_channel_ids` | Who and which source channel. Use for attribution lines |
| `source_url` | A courtesy pointer for human review. It can rot. The canonical item link for display is `presentation_items[].source_url` |
| `source_class`, `evidence_type`, `source_class_confidence` | Who published it, and which type of evidence it is |
| `source_type`, `media_format`, `claim_type`, `author` | Descriptive facts |
| `content_quality` | `sufficient` or `thin`. Read the Record or the source before writing from a `thin` item |
| `source_reachability` | `status` and `is_active` of Synorb's crawler for that source. Not a live link check |
| `source_language`, `translation_status`, `translated_language`, `manifest_text_language`, `manifest_text_source` | Translation state. `manifest_text_source` is `translated` or `original` |
| `original_title`, `translated_title`, `original_summary`, `translated_summary` | Both language versions when a translation exists |

The Signal and Brief are the citable artifacts even when `source_url` later breaks, because the pipeline extracts Claims at ingestion.

### `signal`: for your reasoning

`headline`, `summary`, `significance`, `sentiment`, `claim_count`, `reading_time_minutes`, `version`, and a `body` containing `claims[]` (each with a `claim_id`), `claims_summary` and `claims_rollup`. The rollup is a profile of the Claims: counts by evidence type, confidence and sentiment.

### `brief`: for your user

`headline`, `summary`, `significance`, `sentiment`, `key_points_count`, `quote_count`, `body`, and `body_markdown`. The body carries the scan fields `tldr`, `why_it_matters`, `facts`, `timeline` and `unresolved`, plus `signal_digest` and `brief_meta`. Pass `markdown_version: "2"` to also get `body_markdown_v2`, the agent-friendly layout. Podcast Briefs add guest details, takeaways and cross-promotion.

### `record`: the source itself

`title`, `url`, `content`, `extra_data`, `source_name`, `media_format`, and the original and translated text. On plans without Records, these fields are marked as plan-gated. An entitled account whose Record has no captured body sees "content unavailable" markers instead.

### Rules of thumb

- **Every ID is a string.** They are 17 to 19 digits. A JavaScript number corrupts them silently.
- **The server omits empty sections.** Read by name, never by position, and ignore keys you do not recognize.
- **One item, one Manifest.** If the same story appears in several Streams, dedupe on `manifest_id`.

This accessor reads a Manifest safely. It never raises on a missing field, and it returns only what a display layer needs:

```python
def dig(obj, path, default=None):
    for key in path.split("."):
        if not isinstance(obj, dict) or obj.get(key) in (None, ""):
            return default
        obj = obj[key]
    return obj


def manifest_view(m):
    return {
        "id": m.get("manifest_id"),
        "title": dig(m, "brief.headline") or dig(m, "signal.headline") or dig(m, "source.record_title"),
        "date": m.get("published_date"),
        "publisher": dig(m, "source.source_channel_display") or dig(m, "source.source_name"),
        "link": dig(m, "source.source_url"),
        "story": dig(m, "brief.body.tldr") or dig(m, "brief.summary") or dig(m, "signal.summary"),
        "why": dig(m, "brief.body.why_it_matters"),
        "claims": dig(m, "signal.claim_count", 0),
        "thin": dig(m, "source.content_quality") == "thin",
        "translated": dig(m, "source.manifest_text_source") == "translated",
    }
```

## Failure modes

| Symptom | Cause | What to do |
| --- | --- | --- |
| `record` fields are marked plan-gated | Records are on Startup and Enterprise plans | Use the Signal and Brief. Do not treat gated as empty. |
| A date looks wrong | You used `matched_at` | Use `published_date`. |
| `source_url` returns an error page | Link rot, a paywall or a takedown | The Signal and Brief remain citable. |
| By-ID read returns `404` | The item is no longer eligible for publication (for example, held after a correction) | Look for the currently published replacement through its Stream. Do not assume the old ID points to it. |
| `tag_types` does not line up with `tag_names` | A compact view of an item with more than 15 Tags | Use `tag_quality`. |
| `translated_*` fields appear | The source was not in English | Tell your user when you show translated text. |

## Make it good for your user

Your user should never see the structure. They should see the effect: the right headline, the real source, the date, and a working link. If the text was translated, say so in a few words. If an item is thin, say that you read further. You can add these small notes of honesty because you now know how to read the fields.

## Next guide

[Signals, Briefs and Records](/agent-resources/signals-briefs-and-records): which part to read for which job, and when to go deeper.
