SpendRock Docs
Transactions

Edit amount/date/merchant/note/type/splits/budget month, untrack (empty splits), or remove the location (TXN-3, TXN-4, TXN-5)

Required scope: `transactions:write` (personal access tokens; sessions have every scope).

PATCH
/transactions/{transactionId}

Required scope: transactions:write (personal access tokens; sessions have every scope).

Authorization

bearerAuth
AuthorizationBearer <token>

Authorization: Bearer <token>: a mobile session token, or a personal access token (srp_…) created in Account → API tokens (DEV-1).

Personal access tokens:

  • Act as their user. The household comes from X-SpendRock-Household, else the user's default.
  • Carry scopes (DEV-2), and each operation's description names the one it needs: budget:read / budget:write (months, groups, items, funds, favorites, harvest), transactions:read / transactions:write (transactions, merchant suggestions), households:read / households:manage (households, members, invites), account:read / account:write (me, settings). A write scope includes its read scope. A call outside the token's scopes gets 403 insufficient_scope, with the needed scope in details.required_scope.
  • Can't manage tokens or passwords (403 session_required).
  • May expire (401 unauthenticated afterwards).
  • Are rate-limited (DEV-3): 120 requests/minute per token with bursts up to 120. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (seconds until the bucket is full again); over the limit the answer is 429 rate_limited with Retry-After (seconds). Limits are kept per server instance, so they're approximate.

Sessions (web cookie or mobile bearer) have every scope and aren't limited this way. Cross-origin browser calls (CORS, for the API docs playground) must use a bearer token; cookies are never accepted cross-origin.

In: header

Path Parameters

transactionId*string

ULID.

Match^[0-9A-HJKMNP-TV-Z]{26}$

Header Parameters

X-SpendRock-Household?string

The household to act on (HH-12). Defaults to the user's default household. 403 not_a_member if the caller isn't a current member (HH-16).

Match^[0-9A-HJKMNP-TV-Z]{26}$

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Only the fields present are changed. splits: [] untracks. location: null removes the location.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X PATCH "https://example.com/transactions/01J8Z3N4Q5R6S7T8V9W0X1Y2Z3" \  -H "Content-Type: application/json" \  -d '{}'
{  "transaction": {    "id": "01J8Z3N4Q5R6S7T8V9W0X1Y2Z3",    "type": "expense",    "amount": 1234,    "date": "2019-08-24",    "merchant": "string",    "note": "string",    "budget_month": "2026-12",    "splits": [      {        "item_id": "01J8Z3N4Q5R6S7T8V9W0X1Y2Z3",        "amount": 1234,        "item_name": "string"      }    ],    "status": "tracked",    "deleted_at": "2019-08-24T14:15:22Z",    "location": {      "lat": -90,      "lng": -180,      "accuracy_m": 0    },    "created_by": "string",    "created_by_name": "string",    "updated_by": "string",    "updated_by_name": "string",    "created_at": "2019-08-24T14:15:22Z",    "updated_at": "2019-08-24T14:15:22Z"  },  "months": [    {      "month": "2026-12",      "left_to_budget": 1234,      "groups": [        {          "id": "01J8Z3N4Q5R6S7T8V9W0X1Y2Z3",          "name": "string",          "color": "string",          "is_income": true,          "items": [            {              "id": "01J8Z3N4Q5R6S7T8V9W0X1Y2Z3",              "name": "string",              "kind": "income",              "is_fund": true,              "favorite": true,              "fund_target": 0,              "group_id": "01J8Z3N4Q5R6S7T8V9W0X1Y2Z3",              "planned": 1234,              "spent": 1234,              "received": 1234,              "remaining": 1234,              "note": "string",              "fund": {                "carry_in": 1234,                "adjustments": [                  {                    "amount": 1234,                    "at": "2019-08-24T14:15:22Z",                    "by": "string"                  }                ],                "ending": 1234              }            }          ],          "totals": {            "planned": 1234,            "spent": 1234,            "received": 1234,            "remaining": 1234          }        }      ],      "favorites": [        "01J8Z3N4Q5R6S7T8V9W0X1Y2Z3"      ],      "center": {        "planned": 1234,        "spent": 1234,        "remaining": 1234      },      "untracked_count": 0,      "copied_from": "2026-12",      "created_at": "2019-08-24T14:15:22Z"    }  ],  "untracked_count": 0}