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

# Split, Crop and Map

> Break documents into pages or parts, keep only some pages, and repeat steps for each item of a list

Long or bundled documents are easier to process in pieces. **Split** and **Crop** (group **Resources**) turn one file into several, and **Map** repeats a group of steps once per item of a list, in parallel, then hands you the list of results.

In the running example's second variant, a 60-page contract is **Split** into pages, a **Map** runs **Extract Page** for each page, and a **Code Execution** step merges the pages into one record.

![Split step followed by a Map containing an Extract Page step, then a Merge Pages step](https://mintcdn.com/meistrari/M2w7BduKZAFA1Sbx/images/workflow/pages-graph.png?fit=max\&auto=format\&n=M2w7BduKZAFA1Sbx\&q=85\&s=4b929d129ea1dc3137379b2bd5f58d02)

## Split

**Split** takes a PDF or CSV and returns a **list of files**, one per piece.

**1. Choose the file**

In **File**, type `@` and pick the file Input or the file output of a previous step (for example the result of a Crop). Split accepts one file or a list of files.

**2. Choose the type**

**PDF** or **CSV**.

**3. Choose the Split mode (PDF)**

* **Single Pages** (deterministic): each page becomes its own file. You can set how many pages go into each piece; with 1, every page is a separate file.
* **Smart Files** (AI): the model detects logical sub-documents and groups pages into files, for example a bundle that contains a contract, its annexes and a cover letter.

**4. Optionally add custom instructions (Smart Files)**

**Custom instructions** tell the AI how to group pages ("Group pages by invoice number; keep cover letters with their contract"). Choose **Always** to apply them to every file, or **Only when no summary** to use them only as a fallback.

### What Split returns

A list, one entry per piece:

| Field | Meaning |
| - | - |
| `file` | the new file for this piece |
| `originalFile` | the file it was cut from |
| `pages` | the page range, like `"1"`, `"3-5"` or `"1,2,5-10"` |
| `startPage`, `endPage` | first and last page of the piece |
| `description`, `fileType` | what the AI understood the piece to be; only filled in Smart Files mode |

The entries are files, not text. To read them you pass them to an AI Module (one at a time inside a Map, used as Parser or Multimodal) or to another document step.

## Crop

**Crop** keeps only some pages of a PDF.

**1. Choose the file**

**Take this variable**: type `@` and pick the file.

**2. Choose the pages**

**And crop it with this value**: page numbers and ranges, counted from 1, like `1-2, 7, 10-18`.

Crop returns a list with one entry per input file: `file` (the cropped PDF), `originalFile` and the `indexes` you asked for. Typical use: keep the first two pages of every contract before extraction, so the model only reads the cover and the summary of terms.

> [!TIP]
>
> Chain Crop and Split: Crop the signature pages of a bundle, then Split the result into single pages for a per-page check.

## Map

**Map** repeats the steps you place inside it for **each item of a list**, runs those iterations in parallel, and returns the list of results.

**1. Add the Map**

Add **Map** after the step that produces the list (a Split, or an AI Module whose Output Format has a list attribute). Name it, for example `Each page`.

**2. Choose what to iterate over**

**Over**: type `@` and pick the list. For the running example, the output of **Split contract**.

**3. Name the Map Variable**

**Map Variable** is the name of the current item inside the Map, for example `page`. Steps inside the Map reference it as `@page`.

**4. Add steps inside the Map**

Click inside the Map to add the steps that run for each item. In the example, **Extract Page** is an AI Module whose prompt reads `@page` (used as Multimodal for a scanned contract) and returns `page_number`, `clauses` and `amounts`.

![Map configuration with Over and Map Variable, and the banner 'You're inside a map node' on an inner step](https://mintcdn.com/meistrari/M2w7BduKZAFA1Sbx/images/workflow/map-config.png?fit=max\&auto=format\&n=M2w7BduKZAFA1Sbx\&q=85\&s=b47f91f570704bc3c8547edb60408ede)

Inside the Map, a step sees the Map Variable, the Inputs of the Workflow and the outputs of the steps before the Map. A banner on each inner step reminds you which Map it belongs to.

### What Map returns

After the Map, the next steps see:

* the **Map step** itself: a list with one entry per item, each entry holding the outputs of the inner steps keyed by step name;
* each **inner step**: a list of that step's outputs, one per item, in the same order as the input list.

So after `Each page`, referencing **Extract Page** gives the list of page records. In Code Execution that is `input["Extract Page"]`, an array you can merge:

```javascript theme={null}
// Merge the per-page extractions of the Each page Map into one record.
async function execute(input) {
  const pages = input["Extract Page"]
  return {
    page_count: pages.length,
    clauses: pages.flatMap(p => p.clauses ?? []),
    total_of_amounts: pages.reduce((sum, p) => sum + (p.amounts ?? []).reduce((s, a) => s + a, 0), 0),
  }
}
```

If the list is empty, the Map returns an empty list and the Workflow continues with the next step.

### Reading Map results

In the result pane, a Map shows the iteration count and lets you move between iterations (**Iteration 3 of 60**) to see each item's outputs and errors. In **Debug**, each iteration is its own child run: open **Iterations** and **Open iteration as run** to inspect one page as if it were a standalone run. Through the API, inner steps carry one `runs` entry per iteration; see [Outputs and results](https://docs.tela.com/en/workflow/outputs-and-results.md#through-the-api).

> [!NOTE]
>
> Iterations run in parallel, so a Map over 60 pages finishes in about the time of one page, but it also makes 60 model calls at once. Mind your model quotas and cost when mapping over large documents.

## Typical patterns

> **Per-page extraction of a long document**
>
> **Split** (Single Pages, 1 page) → **Map** over the Split output → inside: **AI Module** reading `@page` → after the Map: **Code Execution** merging `input["<inner step>"]`, or an **AI Module** that receives the whole list (used as Parser) and consolidates it.

> **One bundle, several documents**
>
> **Split** in **Smart Files** mode with instructions like "Separate the main contract from each annex" → **Map** over the pieces → inside: **Classifier** or **AI Module** per piece. Use `description` and `fileType` of each piece to decide what to do with it.

> **Batches: several files in one Input**
>
> A file Input can receive several files. Pass it to **Map** directly (**Over** = the Input) to run the same steps for each uploaded contract, or to **Split** first to get pages of all of them.

> **Only the pages that matter**
>
> **Crop** pages `1-2` → **AI Module** on the cropped file. Cheaper and more accurate than sending the whole document when the information is always in the same place.

> **Iterate over extracted items, not pages**
>
> An **AI Module** returns a list attribute (`line_items`) → **Map** over `Extract Data › line_items` → inside: an **Existing Canvas** that validates one item. Lists from Output Formats are valid Map inputs, not only files.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.