---
title: Sorting
description: Sort API results by fields, direction, and multiple criteria in TraceRTM
---

# Sorting

TraceRTM provides flexible sorting capabilities to order API results by one or more fields. This guide covers single-field sorting, multi-field sorting, and sorting combined with filters and pagination.

## Basic Sorting

### Sort Parameters

| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `sort` | string | Field to sort by | `created_at` |
| `order` | string | Sort direction: `asc` or `desc` | `desc` |

### Simple Sort

```bash
# Sort by creation date (newest first - default)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items" \
  -H "Authorization: Bearer rtm_live_sk_..."

# Sort by creation date (oldest first)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=created_at&order=asc" \
  -H "Authorization: Bearer rtm_live_sk_..."

# Sort by title alphabetically
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=title&order=asc" \
  -H "Authorization: Bearer rtm_live_sk_..."

# Sort by last updated
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=updated_at&order=desc" \
  -H "Authorization: Bearer rtm_live_sk_..."
```

---

## Sortable Fields

### Item Fields

| Field | Description | Notes |
|-------|-------------|-------|
| `id` | Item ID | Lexicographic sort |
| `key` | Item key (e.g., REQ-001) | Natural sort available |
| `title` | Item title | Case-insensitive |
| `type` | Item type | Alphabetical |
| `status` | Item status | Alphabetical |
| `priority` | Priority level | Custom order |
| `assignee` | Assigned user | By name |
| `created_at` | Creation timestamp | Date sort |
| `updated_at` | Last update timestamp | Date sort |
| `due_date` | Due date | Date sort, nulls handling |
| `custom.*` | Custom fields | Type-dependent |

### Link Fields

| Field | Description |
|-------|-------------|
| `id` | Link ID |
| `type` | Link type |
| `created_at` | Creation timestamp |
| `source_id` | Source item ID |
| `target_id` | Target item ID |

### Project Fields

| Field | Description |
|-------|-------------|
| `id` | Project ID |
| `name` | Project name |
| `key` | Project key |
| `created_at` | Creation timestamp |
| `updated_at` | Last update timestamp |

---

## Sort Direction

### Ascending (asc)

```bash
# Oldest items first
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=created_at&order=asc"

# A-Z alphabetical
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=title&order=asc"

# Lowest priority first
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=asc"
```

### Descending (desc)

```bash
# Newest items first
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=created_at&order=desc"

# Z-A alphabetical
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=title&order=desc"

# Highest priority first
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=desc"
```

---

## Priority Sorting

Priority fields use a custom sort order rather than alphabetical:

### Default Priority Order

| Priority | Sort Order (asc) | Sort Order (desc) |
|----------|------------------|-------------------|
| `critical` | 1 | 5 |
| `high` | 2 | 4 |
| `medium` | 3 | 3 |
| `low` | 4 | 2 |
| `trivial` | 5 | 1 |

```bash
# Highest priority first (critical → trivial)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=desc"

# Lowest priority first (trivial → critical)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=asc"
```

---

## Status Sorting

Status fields can use workflow-defined order:

### Default Status Order

| Status | Sort Order |
|--------|------------|
| `backlog` | 1 |
| `todo` | 2 |
| `in_progress` | 3 |
| `in_review` | 4 |
| `done` | 5 |
| `archived` | 6 |

```bash
# Sort by workflow order
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=status&order=asc"
```

### Custom Status Order

If your project uses custom statuses, define sort order in project settings:

```json
{
  "status_order": {
    "draft": 1,
    "pending_review": 2,
    "approved": 3,
    "implemented": 4,
    "verified": 5,
    "released": 6
  }
}
```

---

## Natural Sorting

For fields like keys (REQ-1, REQ-2, REQ-10), use natural sorting:

```bash
# Natural sort - REQ-1, REQ-2, REQ-10 (not REQ-1, REQ-10, REQ-2)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=key&order=asc&sort_natural=true"
```

### Comparison

| Without Natural Sort | With Natural Sort |
|---------------------|-------------------|
| REQ-1 | REQ-1 |
| REQ-10 | REQ-2 |
| REQ-2 | REQ-10 |
| REQ-20 | REQ-20 |
| REQ-3 | REQ-3 |

---

## Null Value Handling

Control where null values appear in sorted results:

| Parameter | Values | Description |
|-----------|--------|-------------|
| `nulls` | `first`, `last` | Position of null values |

```bash
# Nulls at the end (default)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=due_date&order=asc&nulls=last"

# Nulls at the beginning
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=assignee&order=asc&nulls=first"
```

---

## Sorting with Filters

Combine sorting with filters for precise results:

```bash
# High priority requirements, sorted by due date
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?type=requirement&priority=high&sort=due_date&order=asc"

# Recent approved items
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?status=approved&sort=updated_at&order=desc"

# Unassigned items by priority
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?assignee[null]=true&sort=priority&order=desc"
```

---

## Sorting with Pagination

Sorting is preserved across paginated results:

### Offset Pagination

```bash
# Page 1: sorted by priority
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=desc&limit=20&offset=0"

# Page 2: same sort order maintained
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=desc&limit=20&offset=20"
```

### Cursor Pagination

```bash
# First page
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=desc&limit=20"

# Next page (cursor encodes sort order)
curl "https://api.tracertm.dev/v1/projects/proj_abc123/items?sort=priority&order=desc&limit=20&cursor=eyJ..."
```

---

## SDK Examples

### Python

```python
from tracertm import TraceRTMClient

client = TraceRTMClient(api_key="rtm_live_sk_...")

# Simple sort
items = client.items.list(
    project_id="proj_abc123",
    sort="created_at",
    order="desc"
)

# Sort with filters
items = client.items.list(
    project_id="proj_abc123",
    type="requirement",
    status="approved",
    sort="priority",
    order="desc"
)

# Sort with null handling
items = client.items.list(
    project_id="proj_abc123",
    sort="due_date",
    order="asc",
    nulls="last"
)

# Natural sort for keys
items = client.items.list(
    project_id="proj_abc123",
    sort="key",
    order="asc",
    sort_natural=True
)

# Custom field sort
items = client.items.list(
    project_id="proj_abc123",
    sort="custom.risk_score",
    order="desc"
)

# Iterate sorted results
for item in client.items.iterate(
    project_id="proj_abc123",
    sort="priority",
    order="desc"
):
    print(f"{item.priority}: {item.title}")
```

### TypeScript

```typescript
import { TraceRTMClient } from '@tracertm/sdk';

const client = new TraceRTMClient({ apiKey: 'rtm_live_sk_...' });

// Simple sort
const items = await client.items.list({
  projectId: 'proj_abc123',
  sort: 'created_at',
  order: 'desc'
});

// Sort with filters
const filtered = await client.items.list({
  projectId: 'proj_abc123',
  type: 'requirement',
  status: 'approved',
  sort: 'priority',
  order: 'desc'
});

// Natural sort
const naturalSorted = await client.items.list({
  projectId: 'proj_abc123',
  sort: 'key',
  order: 'asc',
  sortNatural: true
});

// Sort builder pattern
const results = await client.items
  .filter({ type: 'requirement' })
  .sort('priority', 'desc')
  .sort('created_at', 'asc')  // Secondary sort
  .list({ projectId: 'proj_abc123' });

// Paginated sorted iteration
for await (const item of client.items.iterate({
  projectId: 'proj_abc123',
  sort: 'updated_at',
  order: 'desc'
})) {
  console.log(`${item.updated_at}: ${item.title}`);
}
```

### Go

```go
package main

import (
    "context"
    "fmt"
    "github.com/tracertm/tracertm-go"
)

func main() {
    client := tracertm.NewClient("rtm_live_sk_...")
    ctx := context.Background()

    // Simple sort
    items, _ := client.Items.List(ctx, &tracertm.ListItemsRequest{
        ProjectID: "proj_abc123",
        Sort:      "created_at",
        Order:     "desc",
    })

    // Sort with filters
    filtered, _ := client.Items.List(ctx, &tracertm.ListItemsRequest{
        ProjectID: "proj_abc123",
        Type:      "requirement",
        Status:    "approved",
        Sort:      "priority",
        Order:     "desc",
    })

    // Natural sort
    naturalSorted, _ := client.Items.List(ctx, &tracertm.ListItemsRequest{
        ProjectID:   "proj_abc123",
        Sort:        "key",
        Order:       "asc",
        SortNatural: true,
    })

    // Null handling
    withNulls, _ := client.Items.List(ctx, &tracertm.ListItemsRequest{
        ProjectID: "proj_abc123",
        Sort:      "due_date",
        Order:     "asc",
        Nulls:     "last",
    })

    // Iterate with sort
    iter := client.Items.Iterate(ctx, "proj_abc123", &tracertm.IterateOptions{
        Sort:  "priority",
        Order: "desc",
    })

    for iter.Next() {
        item := iter.Item()
        fmt.Printf("%s: %s\n", item.Priority, item.Title)
    }
}
```

---

## Response Example

Sorted results include sort information in the response:

```json
{
  "data": [
    {
      "id": "item_req_005",
      "key": "REQ-005",
      "title": "Critical Security Feature",
      "priority": "critical",
      "status": "in_progress",
      "created_at": "2024-01-20T10:00:00Z"
    },
    {
      "id": "item_req_003",
      "key": "REQ-003",
      "title": "High Priority Auth",
      "priority": "high",
      "status": "approved",
      "created_at": "2024-01-19T15:30:00Z"
    },
    {
      "id": "item_req_001",
      "key": "REQ-001",
      "title": "Medium Priority Task",
      "priority": "medium",
      "status": "draft",
      "created_at": "2024-01-18T09:00:00Z"
    }
  ],
  "sort": {
    "field": "priority",
    "order": "desc",
    "natural": false,
    "nulls": "last"
  },
  "pagination": {
    "total": 156,
    "limit": 20,
    "offset": 0,
    "has_more": true
  }
}
```

---

## Best Practices

### 1. Use Indexes for Common Sorts

The following fields are indexed for efficient sorting:
- `created_at`
- `updated_at`
- `priority`
- `status`
- `type`
- `key`

### 2. Consistent Sort for Pagination

Always use the same sort parameters across paginated requests:

```python
# Good: Consistent sort across pages
params = {"sort": "created_at", "order": "desc"}
page1 = client.items.list(project_id, limit=50, offset=0, **params)
page2 = client.items.list(project_id, limit=50, offset=50, **params)

# Bad: Changing sort between pages
page1 = client.items.list(project_id, sort="created_at", order="desc", offset=0)
page2 = client.items.list(project_id, sort="title", order="asc", offset=50)  # Different!
```

### 3. Add Secondary Sort for Stability

When sorting by non-unique fields, add a secondary sort for deterministic results:

```bash
# Good: Secondary sort ensures stable order for items with same priority
curl "...?sort=priority,created_at&order=desc,desc"

# Bad: May have different order for items with same priority
curl "...?sort=priority&order=desc"
```

---

## Related Documentation

- [Multi-Sort](/docs/api-reference/rest-api/multi-sort) - Sort by multiple fields
- [Filtering](/docs/api-reference/rest-api/filtering) - Filter results
- [Pagination](/docs/api-reference/rest-api/pagination) - Paginate sorted results
