---
updatedAt: 2026-08-24T09:14:57.000Z
agentTools:
  projectIndex: https://developers.vibe.co/llms.txt
---

# List cash operations

Lists cash operations for the authenticated account over an optional window, most recent first. Operations are grouped into one entry per calendar day per type, in the account timezone, matching what the Vibe app shows. Amounts are in cents: `amount_cents` is rounded per entry, so use `total_amount_cents` for an exact total over the window.

The window is bounded by how many operations it covers rather than by how long it is: a window covering more than 50,000 operations is rejected with `400`. Ad spend is recorded hourly, so a one-year window is well inside that; only windows spanning several years of continuous spend approach it. Narrow `from`/`to` if you hit it: the window is aggregated before `limit`/`offset` are applied, so paging cannot bring an oversized one under the limit.
**Scopes:**
`billing:read`
<br>*Rate limits*:<br>Burst: `10/s`<br>Steady: `300/m`


# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "paths": {
    "/billing/operations": {
      "get": {
        "description": "Lists cash operations for the authenticated account over an optional window, most recent first. Operations are grouped into one entry per calendar day per type, in the account timezone, matching what the Vibe app shows. Amounts are in cents: `amount_cents` is rounded per entry, so use `total_amount_cents` for an exact total over the window.\n\nThe window is bounded by how many operations it covers rather than by how long it is: a window covering more than 50,000 operations is rejected with `400`. Ad spend is recorded hourly, so a one-year window is well inside that; only windows spanning several years of continuous spend approach it. Narrow `from`/`to` if you hit it: the window is aggregated before `limit`/`offset` are applied, so paging cannot bring an oversized one under the limit.\n**Scopes:**\n`billing:read`\n<br>*Rate limits*:<br>Burst: `10/s`<br>Steady: `300/m`\n",
        "operationId": "listAccountOperations",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Start of the window (inclusive): a calendar day in the account timezone.",
            "schema": {
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "example": "2026-06-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "End of the window (exclusive): a calendar day in the account timezone. The whole preceding day is included.",
            "schema": {
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "example": "2026-06-08",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of operations to return",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "Number of operations to skip",
            "schema": {
              "minimum": 0,
              "type": "number"
            }
          },
          {
            "name": "account_id",
            "required": false,
            "in": "query",
            "description": "Required only for embedded apps.",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Operation list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationList"
                }
              }
            }
          },
          "400": {
            "description": "Bad request error response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missingApiKey": {
                    "summary": "Missing API key",
                    "value": {
                      "error": {
                        "type": "validation",
                        "message": "Missing API Key",
                        "status": 400,
                        "detail": null,
                        "request_id": "req_8f3a4b2c",
                        "doc_url": null
                      }
                    }
                  },
                  "validationError": {
                    "summary": "Validation error",
                    "value": {
                      "error": {
                        "type": "validation",
                        "message": "Validation error",
                        "status": 400,
                        "detail": {
                          "validation": [
                            "id must be a string"
                          ]
                        },
                        "request_id": "req_8f3a4b2c",
                        "doc_url": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized error response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidApiKey": {
                    "summary": "Invalid API key",
                    "value": {
                      "error": {
                        "type": "invalid_token",
                        "message": "Unauthorized",
                        "status": 401,
                        "detail": null,
                        "request_id": "req_8f3a4b2c",
                        "doc_url": "https://developers.vibe.co/errors/invalid-token"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope error response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "insufficientScope": {
                    "summary": "Missing required scope",
                    "value": {
                      "error": {
                        "type": "insufficient_scope",
                        "message": "Missing required scope",
                        "status": 403,
                        "detail": {
                          "required": "billing:read",
                          "granted": [
                            "test"
                          ]
                        },
                        "request_id": "req_8f3a4b2c",
                        "doc_url": "https://developers.vibe.co/reference/oauth2token"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "summary": "List cash operations",
        "tags": [
          "Billing"
        ],
        "x-rate-limit": {
          "rps": 10,
          "rpm": 300
        },
        "x-scopes": [
          "billing:read"
        ]
      }
    }
  },
  "info": {
    "title": "Vibe Public API",
    "description": "Vibe Public API revision 2026-06-01",
    "version": "2026-06-01",
    "contact": {}
  },
  "tags": [
    {
      "name": "Billing",
      "description": "Read-only views of what an Account owes and has spent. All amounts are in cents.\n\nThe balance is the authoritative figure for what is owed. It is read from a running total rather than summed from the cash-operations list, so the two are not expected to match exactly.\n\nCash operations are grouped into one entry per calendar day per type, in the account timezone, matching what the Vibe app shows. `amount_cents` is rounded per entry, so use `total_amount_cents` for an exact total over a window.\n\n> ⚠️ **Gotcha — operation windows are bounded by volume, not duration**\n>\n> A window covering more than 50,000 operations is rejected with `400`. Ad spend is recorded hourly, so a one-year window is well inside that; only windows spanning several years of continuous spend approach it. Narrow `from`/`to` if you hit it: the window is aggregated before `limit`/`offset` are applied, so paging cannot bring an oversized one under the limit."
    }
  ],
  "servers": [
    {
      "url": "https://api.vibe.co",
      "description": "Production API"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http"
      }
    },
    "schemas": {
      "ErrorDetail": {
        "type": "object",
        "properties": {
          "required": {
            "type": "string",
            "example": "audiences:write"
          },
          "granted": {
            "example": [
              "audiences:read",
              "reporting:read"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "required",
          "granted"
        ]
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "insufficient_scope",
              "invalid_token",
              "validation",
              "internal_error"
            ]
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "number",
            "example": 403
          },
          "detail": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ErrorDetail"
              }
            ]
          },
          "request_id": {
            "type": "string",
            "example": "req_8f3a4b2c"
          },
          "doc_url": {
            "type": "string",
            "example": "https://developers.vibe.co/reference/oauth2token",
            "nullable": true
          }
        },
        "required": [
          "type",
          "message",
          "status",
          "request_id"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ApiError"
          }
        },
        "required": [
          "error"
        ]
      },
      "Operation": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Operation type"
          },
          "amount_cents": {
            "type": "number",
            "description": "Signed amount in cents (integer, no decimals) for this day and type. Negative for ad spend, positive for credits and card payments. Rounded from a sub-cent total, so summing these values is approximate — use `total_amount_cents` for an exact window total."
          },
          "operation_date": {
            "type": "string",
            "description": "Calendar day the operations were recorded, in the account timezone. Operations are grouped by day and type, so this and `type` together identify the item.",
            "format": "date",
            "example": "2026-06-01"
          }
        },
        "required": [
          "type",
          "amount_cents",
          "operation_date"
        ]
      },
      "OperationList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Operation"
            }
          },
          "total": {
            "type": "number",
            "description": "Total number of daily operation entries matching filters"
          },
          "total_amount_cents": {
            "type": "number",
            "description": "Exact signed total in cents for the whole requested window, summed before rounding and unaffected by pagination. Reconcile against this rather than against the sum of `data`."
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of items returned"
          },
          "offset": {
            "type": "number",
            "description": "Number of items skipped"
          }
        },
        "required": [
          "data",
          "total",
          "total_amount_cents",
          "limit",
          "offset"
        ]
      }
    }
  },
  "security": [
    {
      "bearer": []
    }
  ]
}
```