> This page is for API.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.spreadspace.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.spreadspace.app/_mcp/server.

# Loan workbooks

A loan's spread comes out as two workbooks: one of tables and one of
statements. Both are built from the loan's data as it stands when you ask, so
there is nothing to request ahead of time. Ask for a workbook, and SpreadSpace
builds a new one whenever the loan's data has changed since the last.

## What each workbook holds

**Tables** holds every table the spread builds, for each filer on the loan,
followed by every cash flow measure. Each table is titled, and the rows a
figure is derived from sit indented under that figure.

**Statements** holds every line of each statement with its derivation indented
beneath it: the profit and loss statement and the balance sheet on your chart
of accounts, and the cash flow statement as printed. Every cash flow measure
follows.

Money is written as currency in both workbooks, so the cells add up and format
as numbers.

## The loop

Two operations, one per workbook, in the Loan Workbooks group of the
[API reference](/api). Both need the `spreads:read` scope and answer the same
way.

| Workbook   | Operation                                  |
| ---------- | ------------------------------------------ |
| Tables     | `GET /api/loans/{loan_id}/xlsx/tables`     |
| Statements | `GET /api/loans/{loan_id}/xlsx/statements` |

Request the operation until it answers `200`:

| Status | Meaning                                                                                                                                                                                          |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `200`  | A workbook is ready, and `url` is its download link.                                                                                                                                             |
| `202`  | The first request since the loan's data changed, with no earlier workbook to hand out. A new one is being built: request the same URL again after `Retry-After` (also in `retry_after_seconds`). |
| `503`  | `render_failed`: the latest build for this data failed, and the message says why. Request again after `Retry-After` and a new build starts.                                                      |

The `200` carries `url`, `expires_in_seconds`, `rendered_at` and `stale`.
`stale` true means the loan's data changed after this workbook was built. The
link still opens the older workbook, and a newer one is already being built,
so request again shortly to get it. `rendered_at` says when the workbook you
hold was built.

## The link

`expires_in_seconds` is a guaranteed-valid floor of 300 seconds; the link
itself lives five to ten minutes. Do not store it: request the operation again
when you need another one. While the loan's data is unchanged, a request hands
out the same workbook under a fresh link and builds nothing.

## Two independent workbooks

The two workbooks are built separately. A tables workbook being built never
holds up the statements workbook, and each operation answers for its own.