Skip to main content
Read the same spreadsheet documents you use in the Finta editor. Start with document and worksheet metadata, then request only the cells you need. For AI tool calls, see Sheets MCP tools. All HTTP paths below are relative to /api/v1. A sheet is a document with an sht_ ID; a worksheet is a tab inside that document, with its own stable ID and user-facing name. The document URL opens the Finta editor. Worksheet IDs are not zero-based tab positions. The revision belongs to the entire document. Existing API authentication, live company permissions, subscription/entitlement checks and rate limits still apply. API key use requires API access Manage in addition to the endpoint’s Forecast permission. Use credentials for the intended company; no company ID is supplied to these operations. A sheet from another company is not exposed by supplying its ID.

List documents and page through results

GET /sheets returns document summaries without any cell data. Optional query performs a case-insensitive document-name substring search (1–256 characters). limit defaults to 100 and accepts 1–500. Order is creation time descending, then internal ID descending. Pass the returned next_cursor unchanged and URL-encoded as starting_after, keeping the query unchanged. Do not derive or decode cursors, even when their current representation resembles a sheet ID. A cursor unavailable under the current company/filter returns 404. This list is not a revision-pinned workbook snapshot.
url on the list envelope is the relative API collection path; url on each document is the absolute editor link on the configured Finta app host. Empty/final pages have has_more: false and next_cursor: null. Document summaries do not currently contain an object discriminator.

Inspect a document before selecting cells

GET /sheets/{id} without ranges returns id, name, url, revision and worksheets. Each worksheet has id, name, used_range, row_count and column_count. used_range is the unqualified bounding A1 rectangle of nonempty authored cells (including formulas), or null when no such cells exist; formatting alone does not make a used range. Grid dimensions describe existing bounds, not used-data dimensions. Read cells by repeating the literal query key ranges[]: ranges[]=Plan!A1:B3&ranges[]=Plan!D1:D3. A single ranges string is also accepted. For example, curl can URL-encode the query safely:
Qualified A1 selections specify the worksheet name: 'Plan'!A1:B2. Double an apostrophe inside a quoted worksheet name: 'Bob''s Plan'!A1. Alternatively pass a stable worksheet_id and an unqualified range such as A1:B2. An unqualified range without a worksheet ID is only unambiguous when the document has one worksheet. If both the range name and worksheet ID are supplied, they must identify the same tab. Worksheet names are labels, not positional indices. Ranges must be bounded cells or rectangles, in ascending order and inside the current grid. Whole-column/whole-row selections such as A:A and 1:10 are not read-range syntax. Up to 100 selections and 10,000 selected cells total are accepted per read. Overlapping ranges each contribute their cell count. Discover the grid from metadata before requesting large selections. The view enum controls the returned matrices:
  • values (default): return calculated values for selected cells, without a formula matrix.
  • formulas: return saved formula strings beginning with = and null for non-formula cells. No financial evaluation runs and no calculation object is returned.
  • both: return the formula matrix alongside calculated values, allowing callers to inspect assumptions and results together.
Matrices are rectangular and row-major. A selected A1:B2 has two rows and two entries per row. Blank cells are null in the value matrix; formula-error cells can also be null, so inspect calculation.errors to distinguish them. The include HTTP parameter is a comma-separated selection: charts includes embedded chart definitions on worksheets, and formats includes explicit formatting entries for selected cells. Both are opt-in. A chart definition is not a rendered image. Requesting formats without ranges does not retrieve all cell formats.
Dimensions in this example illustrate existing metadata; they are not a creation-default contract.

Cell units and live calculation

Spreadsheet values are generic cell values and preserve worksheet units. A sheet amount of $20,000 is 20000, not 2000000. Do not divide cell values by 100 merely because other Finta endpoints use integer _cents monetary fields. Formatting does not convert the underlying number. Authored whitespace-only strings remain text in calculated output rather than becoming numeric zero. This exception is limited to generic spreadsheet arrays; transactions, reports and other financial resource fields retain their cents contracts. Selected values use the existing spreadsheet evaluator, including supported FINTA financial functions and existing authorization. Saved formulas are distinct from their results. Supported FINTA functions follow the existing sheet evaluator; a saved number stays a snapshot rather than becoming a live financial formula. Calculation is synchronous and bounded; it does not create a pending job or a polling endpoint. Clients must inspect calculation.status even after HTTP 200:
  • complete: evaluation completed without formula errors. Warnings can still be present.
  • error: one or more formulas failed. Corresponding cells have null values and errors identify the cell and/or formula where available. Other results can still be returned.
  • unavailable: evaluation could not complete. Value matrices are omitted, not fabricated. Readable formulas remain available with view=both; retry the selected GET ranges when appropriate.
Each error has code and message, with optional worksheet_id, cell and formula. Warnings include code/message and may include the formula and a count. In particular, uncategorized_transactions means uncategorized transactions may affect that financial result. Treat new error/warning codes defensively rather than failing to display the whole response. These diagnostic codes are open strings.

Find authored cells

GET /sheets/{id}/cells requires a nonempty query (maximum 1,000 characters). It searches saved authored input and formula text, not evaluated financial results or displayed formatting. A request for a number will therefore not find every formula whose current result equals that number. Matching is case-insensitive:
  • contains (default): the authored text contains the query.
  • exact: the full authored text equals the query, ignoring case.
Omit worksheet_id to search every tab, or supply a stable worksheet ID to restrict the search. Results are traversed in worksheet order, then row/column order. Each match includes worksheet_id, worksheet_name, unqualified cell and authored string input. It does not include calculated values. Blank authored cells are skipped.
Pagination accepts the same 1–500 limit, default 100. Search cursors bind the document, query, match mode, worksheet filter and document revision. Keep those filters unchanged between pages. A cursor from a different search returns 400; a document changed during pagination returns 409 revision_conflict. Restart from the first page without starting_after after inspecting the changed document; do not keep retrying a stale cursor.

Delete the whole document safely

DELETE /sheets/{id}?base_revision=3 requires the revision from a current read. It accepts no request body, including an empty JSON object. The revision is compared under a lock before deletion. A stale revision returns 409 and does not delete the document. Reread and decide whether the changed document should still be deleted; do not automatically substitute the new revision and retry a destructive action. This permanently deletes the document and all its worksheets. It is not a way to clear a range or remove one tab. Success returns HTTP 204 with no JSON body:
The corresponding MCP tool returns a small confirmation {"id":"sht_example","deleted":true} after the HTTP 204. A second HTTP deletion of the missing ID returns 404; do not assume an additional 204 confirmation.

Errors, headers and recovery

Sheets use the existing error envelope: error.type, error.code, error.message, error.doc_url, optional error.param, and optional error.current_revision. There is no revision HTTP header; use the JSON revision and error.current_revision fields. Error messages are human-readable guidance, not stable machine identifiers. 400 is a caller input failure, including unknown parameters, invalid range syntax/selection, unsupported view/match, too many cells/ranges, invalid limits or wrong-search cursors. Correct the request before retrying.
404 resource_missing covers an absent or inaccessible document, and unavailable list cursors. Verify company context and rediscover accessible resources rather than assuming a guessed ID exists.
Deletion conflicts include the current revision:
Search pagination has a separate recovery action even though it uses the same conflict code:
401 and 403 preserve existing distinctions: obtain a valid credential for authentication failures, restore required company/product access for permission failures. Existing 429 rate_limit_exceeded uses Retry-After; monthly monthly_limit_exceeded is not retryable in the short term and deliberately omits that header. See Usage Limits for the shared headers and retry rules.