# Combine

> Bring two lists together: one after the other, or matched on a field they share.

The **Combine** step takes two lists and returns one. It either places the second list after the first, or matches records from each on a field they have in common.

> Dock: Data · Lists · Takes: two lists · Returns: one combined list

Reach for it when the data you need is split across two places: contacts in one system and their orders in another, incidents from a ticketing tool and the service levels that apply to them.

```mermaid
flowchart LR
    A[Get Customers] --> C[Combine]
    B[Get Orders] --> C
    C --> D[Send Summary]
```

## Setting it up

### Connect two branches to it

Combine takes exactly two incoming connections, each from a different step, and each supplies one of the two lists. It always waits for both branches before it runs; the **AND** chip on its input shows this. If you add a third connection, or a second one from the same step, the canvas declines it and says why. See [Merging Parallel Branches](/build/core-concepts/steps-and-the-canvas#merging-parallel-branches).

### Choose how to combine

**Append lists** places the second list's items after the first list's. **Match fields** pairs records that share a value.

### Pick the two lists

**First list** and **Second list** each read from one of the connected branches. The branch you pick for the first list is no longer offered for the second, so each list comes from its own step. You can also paste a JSON list into either field.

### Name the field to match on, if you are matching

**Field in first list** and **Field in second list** name the field in each. They do not have to be spelled the same: `customer.id` on one side can meet `account.externalId` on the other.

## Deciding what happens to records with no partner

**Keep unmatched records** is the setting that decides the shape of the answer, and it is worth understanding once rather than guessing.

Two lists sharing a field `id`:

```
First list   [{"id": 1, "name": "Lovelace"}, {"id": 2, "name": "Hopper"}, {"id": 3, "name": "Turing"}]
Second list  [{"id": 1, "total": 100}, {"id": 2, "total": 250}, {"id": 9, "total": 7}]
```

Records 1 and 2 exist in both. Record 3 is only in the first list, record 9 only in the second.

| Setting              | What comes back                                                                 |
| -------------------- | ------------------------------------------------------------------------------- |
| **Matches only**     | The two matched records, merged. Nothing else.                                  |
| **From both lists**  | The two matches, then `{"id": 3, "name": "Turing"}` and `{"id": 9, "total": 7}` |
| **From first list**  | The two matches, then `{"id": 3, "name": "Turing"}`                             |
| **From second list** | The two matches, then `{"id": 9, "total": 7}`                                   |

**Choose by what a missing partner means to you.** A customer with no orders is still a customer, so _From first list_ keeps them. An order with no customer record is a problem worth seeing, so _From both lists_ surfaces it.

## When both records use the same field name

A matched pair can carry the same field twice, when both lists have a `name` with different values. **When field names collide** decides which one survives.

Set it to **Second list wins**, the default, and the second list's value is kept; **First list wins** keeps the first's. The two match fields count as ordinary fields here: when they have different names, both stay in the merged record, and when they share a name this setting picks the value like any other field.

## Capital letters matter unless you say otherwise

Matching is exact by default: `ACME` and `acme` are two different customers, and neither finds the other.

**Ignore letter case** is off to begin with. Turn it on and they match. Codes that arrive from different systems are the usual reason: one exports upper case, the other lower.

## One record can match several

Nothing stops a record in one list from matching more than one in the other. **Every match is returned, one row each.**

One customer against two orders for the same `id` gives two rows, both carrying the customer's fields:

```
[{"id": 1, "name": "Lovelace", "total": 100},
 {"id": 1, "name": "Lovelace", "total": 999}]
```

That is usually what you want. It also means the result can be longer than either input, which is worth knowing before you count rows downstream.

## What it passes on

Combine returns an object with two fields: `results` holds the combined list and `resultCount` holds its size.

```
{{ 5.results }}
```

A step after it can iterate over that list, or read a single entry:

```
{{ 5.results.0.name }}
```

`{{ 5.resultCount }}` gives the number of records without counting them yourself.

## Limits

Each input list can hold up to 10,000 records, and the combined result up to 100,000. A run over either ceiling fails with a message naming the list. Narrow each branch with [Filter](/build/action-steps/filter-items) before combining, or split the work across runs.

## Examples to copy

### Attach service levels to incidents

Incidents arrive from a ticketing tool; the service level for each client lives in a Custom Variables step.

- **How to combine**: Match fields
- **Field in first list**: `clientId`
- **Field in second list**: `clientId`
- **Keep unmatched records**: From first list
- **Ignore letter case**: on

_From first list_ keeps an incident whose client has no service level recorded. Those are the ones worth noticing, and dropping them would hide the gap. Ignoring case covers clients whose id is written differently by the two systems.

### Put two exports one after the other

Two branches each fetch a page of results, and you want them as one list.

- **How to combine**: Append lists

The first list's items come first, then the second list's. No field names are involved.

## What's Next?

- [Filter](/build/action-steps/filter-items) — split one list into what you keep and what you discard
- [Custom Variables](/build/action-steps/custom-variables) — hold a lookup table for matching against
- [Variable Reference Syntax](/reference/variable-syntax) — how to read a list entry by position
