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

# Traverse Edge

> Follow typed relationships (edges) from documents to their linked documents

The Traverse Edge stage follows **[object edges](/docs/platform/data-model)** — typed, directed, customer-owned relationships stored on a document — to fetch the documents they point to. Starting from the documents in the pipeline, it reads each document's root-level `edges`, filters by edge type and direction, and returns the linked documents (carrying the edge's attributes with each result).

<Note>
  **Stage Category**: APPLY (relationship traversal)

  **Transformation**: N documents → M linked documents (optionally including the originating documents)
</Note>

Edges are saved onto documents at ingestion — for example, an assembled ad linked to every piece of footage it uses (see [Iconik project-file linkage](/docs/integrations/object-storage/iconik#project-file-linkage)). Traverse Edge is how you follow those saved relationships at query time instead of recomputing them.

## When to Use

| Use Case                            | Description                                                                                                          |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Footage ↔ ad linkage**            | From an ad, fetch every footage clip it uses (with clip order + start-ticks); from footage, find the ads that use it |
| **Bill-of-materials / composition** | Follow "part-of" relationships from an assembly to its components                                                    |
| **Reference expansion**             | Pull the documents a result explicitly links to, without a similarity search                                         |
| **Graph hops**                      | Walk saved relationships between entities you've modeled as edges                                                    |

## When NOT to Use

| Scenario                             | Recommended Alternative |
| ------------------------------------ | ----------------------- |
| Similarity / semantic matching       | `feature_search`        |
| Joining by a shared field value      | `document_enrich`       |
| Comparing content across collections | `cross_compare`         |
| Filtering on an attribute            | `attribute_filter`      |

## How it works

1. For each document entering the stage, the stage reads its root-level `edges` list.
2. Edges are kept when their `type` matches `edge_type` and their `direction` matches the configured `direction`.
3. Each kept edge's `target_object_id` is resolved to the linked document(s); with `target_collection_id` set, only documents from that collection are returned.
4. Matched documents are returned with the originating edge's `attributes` attached (e.g. `clip_order`, `start_ticks_in`/`start_ticks_out`), so downstream stages can use them.

Because edges are stored **reciprocally** (an edge and its inverse can be written on both endpoints), you can traverse the same relationship from either side by choosing the matching `edge_type` and `direction`.

## Creating edges on objects

Edges are **customer-owned data** written at the **root** of an object when you
create it (never under `_internal`). They flow automatically from the object,
through your collections, into each document's search payload — so a stage can
follow them at query time without you re-computing anything.

Pass an `edges` array to `POST /v1/buckets/{bucket_id}/objects`:

```json theme={null}
{
  "key_prefix": "ads/ad1.txt",
  "blobs": [{"property": "content", "type": "text", "data": "final produced ad one"}],
  "edges": [
    {
      "type": "uses_footage",
      "target_object_id": "obj_1a2b3c...",
      "direction": "out",
      "attributes": {"clip_order": 3, "start_ticks_in": 123456789, "start_ticks_out": 987654321}
    }
  ]
}
```

| Edge field         | Description                                                                                                                                   |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`             | The edge type you'll match on in `traverse_edge` (e.g. `uses_footage`).                                                                       |
| `target_object_id` | The object this edge points to. It resolves to that object's document(s) at traversal time.                                                   |
| `direction`        | `out` or `in` — which way the edge points. Follow it with the stage's matching `direction`.                                                   |
| `attributes`       | Arbitrary key/values carried on the edge (e.g. `clip_order`, `start_ticks_in`/`start_ticks_out`). They ride into results via `traversed_via`. |

<Tip>
  Write **reciprocal** edges to walk a relationship from either end: put
  `uses_footage`/`out` on the ad and `used_in_ad`/`out` on the footage, each
  carrying the same attributes. Connectors like [Iconik](/docs/integrations/object-storage/iconik#project-file-linkage)
  populate this shape automatically from editorial project files.
</Tip>

## Parameters

| Parameter              | Type                | Default    | Description                                                                       |
| ---------------------- | ------------------- | ---------- | --------------------------------------------------------------------------------- |
| `edge_type`            | string \| string\[] | *Required* | Edge type(s) to follow, e.g. `"uses_footage"` or `["uses_footage", "used_in_ad"]` |
| `direction`            | string              | `any`      | Which edge directions to follow: `out`, `in`, or `any`                            |
| `target_collection_id` | string              | `null`     | Only return traversed documents from this collection (else all collections)       |
| `include_source`       | boolean             | `false`    | Also keep the originating documents in the output                                 |
| `max_per_source`       | integer             | `50`       | Max edges to follow per source document (guards fan-out)                          |
| `limit`                | integer             | `200`      | Max total traversed documents to fetch across all sources                         |

## Example

Starting from an ad document, fetch every piece of footage it uses:

```json theme={null}
{
  "stage_name": "footage_used",
  "config": {
    "stage_id": "traverse_edge",
    "parameters": {
      "edge_type": "uses_footage",
      "direction": "out"
    }
  }
}
```

`edge_type` also accepts a **list** to follow several relationship types in a single
stage — e.g. `"edge_type": ["uses_footage", "used_in_ad"]` returns documents reached
by either edge, each still labelled with its own `traversed_via`.

Each returned footage document carries the edge attributes from the ad that referenced it — `clip_order`, `start_ticks_in`, and `start_ticks_out` — so you know exactly where in the footage each clip was taken.

## The `traversed_via` response

Every document produced by traversal carries a `traversed_via` field describing
the edge (or edges) that reached it:

| Field                | Description                                                                                 |
| -------------------- | ------------------------------------------------------------------------------------------- |
| `edge_type`          | The edge type that was followed.                                                            |
| `direction`          | The direction it was followed in (`out` / `in`).                                            |
| `attributes`         | The attributes stored on that edge (e.g. `clip_order`, `start_ticks_in`/`start_ticks_out`). |
| `source_document_id` | The document the traversal started from — the other end of the edge.                        |

<Warning>
  `traversed_via` is an **object** when a single source reached the document, but
  a **list** when several sources traversed to the *same* document (a many-to-one
  fan-in — the document is returned once, with one entry per incoming edge). Handle
  both shapes: check whether `traversed_via` is a list before indexing it.
</Warning>

Single source (footage → ad, `used_in_ad`) — `traversed_via` is an object:

```json theme={null}
{
  "document_id": "doc_9bd3572ecf180e72b7042b96",
  "traversed_via": {
    "edge_type": "used_in_ad",
    "direction": "out",
    "attributes": {"clip_order": 3, "start_ticks_in": 123456789, "start_ticks_out": 987654321},
    "source_document_id": "doc_e32de934c79775b870047c62"
  }
}
```

Multiple sources fan in to one document (ad → footage, `uses_footage`, where two
ads reference the same footage) — `traversed_via` is a list:

```json theme={null}
{
  "document_id": "doc_0b84044df6cbd7e4f10bbcbc",
  "traversed_via": [
    {
      "edge_type": "uses_footage",
      "direction": "out",
      "attributes": {"clip_order": 2, "start_ticks_in": 2000000, "start_ticks_out": 4000000},
      "source_document_id": "doc_a56a844765839e4abfcdbca2"
    },
    {
      "edge_type": "uses_footage",
      "direction": "out",
      "attributes": {"clip_order": 4, "start_ticks_in": 4000000, "start_ticks_out": 8000000},
      "source_document_id": "doc_7547528e54cc390a0fb59b1e"
    }
  ]
}
```

Because reciprocal edges are stored on both endpoints, the same pair is walkable
from either side — traverse `uses_footage`/`out` from an ad to reach its footage,
or `used_in_ad`/`out` from that footage to reach the ads that use it — and the
`attributes` (clip order, ticks) are identical in both directions.

## Related

* [Objects](/docs/platform/data-model) — how edges are stored on objects and flow to documents
* [Iconik integration](/docs/integrations/object-storage/iconik#project-file-linkage) — how footage↔ad edges are captured at ingestion
* [Cross Compare](/docs/retrieval/stages/cross-compare) — match content across collections by similarity instead of saved edges
