Skip to content

List run rate movements

GET
/v1/run_rate_movements
curl "https://api.summerbase.com/v1/run_rate_movements" \
-H "Authorization: Bearer sb_..."

Every change to revenue in the project, newest first — or one customer’s, with customer_id, or one subscription’s, with subscription_id.

One row per change to a subscription item: they subscribed, they upgraded, they moved plan, they left, they came back. Each row carries what the item was on and worth before and after, so it explains itself. These are the same changes the metrics report’s movement values add up, so a month’s movement and the rows inside it always agree.

A customer’s rows sharing a counts_at are one movement, because the project’s collapse window folds changes made close together into one: a customer who cancels one plan and takes another two days later has not changed what they are worth, so both rows read no_change. Rows come ordered by counts_at, then customer, then occurred_at, so a movement’s rows are next to each other; group by counts_at and customer_id to see movements, and read the rows to see what made them. A page boundary can fall inside a movement.

Amounts are in the currency the customer is billed in. Expand customer, price, previous_price, plan and previous_plan to get them on each row. A row’s plans are its prices’ as they stand now, so a price moved to another plan reads under that plan as far back as it goes.

customer_id
string

Only this customer’s. A Summerbase id, or any source’s identity for them like stripe:cus_123. A customer nobody has is a 404, not an empty list.

subscription_id
string

Only this subscription’s: the rows of changes to its items. A Summerbase id, or any source’s identity for it like stripe:sub_123. A subscription nobody has is a 404, not an empty list. A row’s movement_type is still its customer’s movement, which may tell a different story from this subscription’s own delta.

movement_type
string
Allowed values: new reactivation expansion contraction churn no_change

Only rows of movements of this type.

limit
integer
default: 20 >= 1 <= 100

How many records to return, 1 to 100. Defaults to 20.

cursor
string

The next_cursor of the previous page, to read the page after it.

expand[]
Array<string>
<= 10 items
Allowed values: customer plan previous_plan previous_price price

Relationships to include in the response instead of fetching separately. A dotted path expands what an expanded record can expand in turn — at most 4 deep, 10 paths a request, and never back to a record already on the path.

Returns a list of run rate movement objects, a page at a time. See Pagination.

Media typeapplication/json

Example

{
"data": [
{
"arr": "15000.00",
"counts_at": "2026-06-12T15:47:09Z",
"currency_code": "USD",
"customer_id": "0199a7c2-4e1b-7f38-b9d2-5a6c8e0f1d73",
"delta": "250.00",
"movement_type": "expansion",
"mrr": "1250.00",
"object": "run_rate_movement",
"occurred_at": "2026-06-12T15:47:09Z",
"plan_id": "0198f1a4-1d2e-7a40-9b31-5c6d7e8f9a0b",
"previous_arr": "12000.00",
"previous_mrr": "1000.00",
"previous_plan_id": "0198f1a4-1d2e-7a40-9b31-5c6d7e8f9a0b",
"previous_price_id": "0198f1a4-2e5f-7b80-a1c2-3d4e5f6a7b8c",
"previous_quantity": "20",
"previous_status": "active",
"price_id": "0198f1a4-2e5f-7b80-a1c2-3d4e5f6a7b8c",
"quantity": "25",
"revenue_type": "recurring",
"status": "active",
"subscription_id": "0199a7c2-5b3e-7a14-8c6d-2f9e4b7a1c05",
"subscription_item_id": "0199a7c2-5b41-7c62-9d3e-6a1f8b2c4d97"
}
],
"has_more": false,
"next_cursor": null,
"object": "list"
}