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

# Transactions

> Transactions: Set Aside Money developer API reference.

Read, filter, create, and update transactions.

## List transactions

> **GET** `/v1/transactions` · Required scope: `data.read`

Paginated. See [pagination](/api-reference/pagination) for reading more than one page.

| Parameter | Type | Notes |
| - | - | - |
| `page` | integer | Defaults to 1. |
| `limit` | integer | Defaults to 50, maximum 200. |
| `type` | string | `expense`, `income`, or `transfer`. |
| `account_id` | uuid | Restrict to one account. |
| `category_id` | uuid | Restrict to one category. |
| `expense_goal_id` | uuid | Only transactions assigned to this Expense. |
| `search` | string | Case-insensitive match on the merchant text. |
| `from` | date | Inclusive, `YYYY-MM-DD`. |
| `to` | date | Inclusive, `YYYY-MM-DD`. |
| `sort` | string | `booked_at` (default) or `created_at`. |

```bash theme={null}
curl "https://api.setaside.money/v1/transactions?from=2026-07-01&to=2026-07-31&type=expense&limit=100" \
  -H "Authorization: Bearer $SETASIDE_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "id": "7c1e93a4-2f60-4b18-a5d2-9e3f0c7b6a51",
      "account_id": "3f9a1c22-88b1-4a0e-9d77-2c5e6b0f1a44",
      "concept": "Blue Bottle Coffee",
      "amount": -1250,
      "booked_at": "2026-07-14",
      "type": "expense",
      "category_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "expense_goal_id": null
    }
  ],
  "total": 213,
  "page": 1,
  "pages": 3
}
```

**Amounts are integer cents. Spending is negative, income is positive.**

## Summarize transactions

> **GET** `/v1/transactions/summary` · Required scope: `data.read`

Totals for the same filters as the list endpoint, without transferring the rows.

## Get one transaction

> **GET** `/v1/transactions/{id}` · Required scope: `data.read`

## Create a transaction

> **POST** `/v1/transactions` · Required scope: `data.write`

Records a manual transaction, for cash or anything a bank feed will not deliver.

| Field | Required | Notes |
| - | - | - |
| `account_id` | yes | Which account it belongs to. |
| `amount` | yes | Integer cents. Negative for spending. |
| `concept` | yes | The merchant or description, up to 200 characters. |
| `booked_at` | yes | `YYYY-MM-DD`. |
| `type` | no | `expense`, `income`, or `transfer`. Inferred from the sign otherwise. |
| `category_id` | no | |
| `expense_goal_id` | no | Assign it to an Expense at the same time. |
| `notes` | no | Up to 2000 characters. |

```bash theme={null}
curl -X POST https://api.setaside.money/v1/transactions \
  -H "Authorization: Bearer $SETASIDE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cash-2026-08-08-market" \
  -d '{
    "account_id": "3f9a1c22-88b1-4a0e-9d77-2c5e6b0f1a44",
    "amount": -2400,
    "concept": "Farmers market",
    "booked_at": "2026-08-08"
  }'
```

Send an `Idempotency-Key` so that a script retrying after a timeout does not create a second
transaction. Derive it from the source event rather than generating a random value per attempt.

## Update a transaction

> **PATCH** `/v1/transactions/{id}` · Required scope: `data.write`

Send only the fields you are changing. Sending an empty body is a `400`, not a no-op, so a bug in
your code cannot look like a successful write.

```bash theme={null}
curl -X PATCH https://api.setaside.money/v1/transactions/7c1e93a4-2f60-4b18-a5d2-9e3f0c7b6a51 \
  -H "Authorization: Bearer $SETASIDE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "concept": "Blue Bottle", "category_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" }'
```

## Assign a transaction to an Expense

> **POST** `/v1/transactions/{id}/expense` · Required scope: `data.write`

Files the transaction against an Expense, which draws down that Expense's balance exactly as it does
in the app. Pass `null` to clear an assignment.

```bash theme={null}
curl -X POST https://api.setaside.money/v1/transactions/7c1e93a4-2f60-4b18-a5d2-9e3f0c7b6a51/expense \
  -H "Authorization: Bearer $SETASIDE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "expense_goal_id": "5d4c3b2a-1f0e-4d9c-8b7a-6e5f4d3c2b1a" }'
```

This is the endpoint most automations end up using: match a merchant, assign the Expense, done.


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