# Sort

Order records by one or more keys; ties keep their input order.

## When to use it

Choose one or more keys and their direction. Input order is preserved for ties. Sorting before limiting or keeping the first duplicate makes those operations predictable.

## Add and configure

1. Add **Sort** from the workflow step picker.
2. Give the step a recognisable name and connect its required inputs.
3. Set the options below. Nested names identify fields within an object or a list item.
4. Validate the recipe, inspect the test result, then run it on the intended data.

The step identifier used in the editor’s code view is `sort`.

## Settings

| Setting | Accepted value | Required | Default | What it controls |
| --- | --- | --- | --- | --- |
| Keys (`keys`) | list of object or string; minimum items 1 | Yes | Not specified | Sort keys, most significant first. A bare JSONPath string is an ascending `auto` key. |

## Inputs and outputs

| Direction | Port | Content | Required | Multiple records |
| --- | --- | --- | --- | --- |
| Inputs | `in` | records | Yes | Yes |
| Outputs | `out` | records | Yes | Yes |

## Effects, testing, and recovery

Transforms or passes records without a declared external side effect.

The declared preview behaviour is to execute this step. Reads, processing, or model usage can therefore be real. Read [dry runs](/docs/workflows/dry-runs) before using a preview with live connections.

No duplicate-prevention key is declared for this step. The step declares safe replay for its supported recovery path.

## Example: Newest first, undated last

Step settings:

```json
{
  "keys": [
    {
      "direction": "desc",
      "path": "$.published_at",
      "type": "datetime"
    }
  ]
}
```

Input records:

```json
[
  {
    "published_at": "2026-09-01T08:00:00Z",
    "title": "old"
  },
  {
    "title": "undated"
  },
  {
    "published_at": "2026-09-02T08:00:00+02:00",
    "title": "new"
  }
]
```

Expected output for this example:

```json
[
  {
    "published_at": "2026-09-02T08:00:00+02:00",
    "title": "new"
  },
  {
    "published_at": "2026-09-01T08:00:00Z",
    "title": "old"
  },
  {
    "title": "undated"
  }
]
```

## Example: By team, then highest score first

Step settings:

```json
{
  "keys": [
    "$.team",
    {
      "direction": "desc",
      "path": "$.score"
    }
  ]
}
```

Input records:

```json
[
  {
    "score": 7,
    "team": "b"
  },
  {
    "score": 3,
    "team": "a"
  },
  {
    "score": 9,
    "team": "a"
  }
]
```

Expected output for this example:

```json
[
  {
    "score": 9,
    "team": "a"
  },
  {
    "score": 3,
    "team": "a"
  },
  {
    "score": 7,
    "team": "b"
  }
]
```

## Example: Numeric strings as numbers

Step settings:

```json
{
  "keys": [
    {
      "path": "$.price",
      "type": "number"
    }
  ]
}
```

Input records:

```json
[
  {
    "price": "10"
  },
  {
    "price": "9.5"
  },
  {
    "price": "n/a"
  }
]
```

Expected output for this example:

```json
[
  {
    "price": "9.5"
  },
  {
    "price": "10"
  },
  {
    "price": "n/a"
  }
]
```

## Check the result

Inspect the selected run’s status, counts, errors, and output records. An empty collection can be a valid result, and a completed step can contain per-record failures where the step defines that behaviour. Check the next step’s expected record shape before publishing or delivering the result.
