---
title: "How much of this book can still walk"
method: GET
path: "/api/v1/order-book/firmness"
tags: ["order_book"]
---

# How much of this book can still walk

`GET /api/v1/order-book/firmness`

## Request

- Base URL: `https://api.app.tightly.io`
- URL: `https://api.app.tightly.io/api/v1/order-book/firmness`
- Auth: HTTP bearer

How much of a season's committed value is firm, how much can still walk, and how much nobody has said: the three-way split for the scope, the same split per account ordered by walkable value, and the date each piece stops being walkable.

On wholesale, committed is a retailer's option: a booked order inside its cancellation window can still walk, so open to buy computed as envelope minus committed overstates what is safe. `season_code` is required; `commitment_id` and `as_of` narrow as elsewhere.

Three buckets, never two. `unknown` is value on accounts with no recorded cancellation term, or on an in-window line with no cancel date, and it is folded into neither firm (which would keep the overstatement) nor walkable (which would invent an exposure). An unshipped line past its cancel date (the trade's cancel-after day) is walkable, never firm: the retailer may refuse it. Soft lines, drafts and holds, are in none of the three and not in committed either: they are served in their own `soft` block with value summed over priced lines only.

`firmness` is null when the scope has no book at all. A season whose every line is cancelled is a true zero and is served as one.

This says what CAN walk. get_order_book_signals says what IS walking, the claims retailers have actually made, and get_order_book_summary carries the same totals beside the envelope.

Sold with Essentials+: without Tightly Connect the answer is 403 `plan_excludes`.

Scope: `order_book:read`.

## Query parameters

- `season_code` string, required
- `commitment_id` string
- `as_of` string, date-time

## Headers

- `Tightly-Version` string

## Response `200`

The three-way split for the scope, the same split per account, and the walkable value by the date each piece stops being walkable. `measured_on` is the day the cancel dates were compared against, fixed from `as_of` rather than taken from the session's clock.

- object
  - `data` object
    - `accounts` object[], nullable: One row per account, ordered by walkable value.
    - `as_of` string, date-time
    - `currency` object: What the figures below are in. `functional` is the book's own currency and the denomination every amount here carries. `_usd` in a key name is the book's functional currency for historical reasons, never a claim of dollars. `transaction` is what the lines were agreed in where they agree on one, and null where they do not; `reporting` is what a reader of this organisation asked to see, with `rate` the dated rate between the last two, served, never applied, and dated to this read's `as_of` so a re-read of a past instant cannot move. `basis` is one of same, converted or unconverted, and `reason` carries the absence word where the block cannot say something.
    - `firmness` object, nullable: committed_value_usd, committed_qty, committed_lines, the three buckets, unknown_reasons, walkable_reasons (one entry per walkable rule, summing to walkable, each with its sentence) and the soft block. Null where the scope holds no lines.
    - `measured_on` string, date
    - `scope` object
    - `scope_reason` string, nullable
    - `walkable` object, nullable: Walkable value by the date it stops being walkable (`by_deadline`), the at-will value that has no deadline (`without_deadline`), and `past_cancel_date`, the value whose cancel date has passed with the goods not shipped in full, with the oldest passed date, the days since and the sentence. Null blocks where nothing is in them.
  - `message` object: severity, service and desc.

## Other responses

- `400`: A required parameter is missing, or a date could not be read.
- `401`: No usable key: malformed, unknown, revoked, expired or stopped. One refusal covers all five, telling a caller which is which maps the surface for them. A request with no Authorization header at all is refused 400 before any key is looked for.
- `403`: The key may not reach this operation. `plan_excludes` when Order book is sold with Essentials+ and this organisation's plan does not include it; `scope_missing` when the key does not hold Order book; `organization_mismatch` when the path names an organisation that is not the key's; `ip_not_allowed` when the caller's address is outside the key's allowlist; `account_mismatch` when a key issued to one account calls this read, whose figure covers every account on the book; the sentence names `GET /order-book/account-styles` and `GET /order-book/account-anchor`, which are that account's own.
- `429`: The key has spent its allowance for this minute. 600 reads and 120 writes a minute, counted per key, refused calls included. `Retry-After` says how long to wait.
- `503`: The database is briefly out of reach, which is what a failover or a full connection pool looks like from outside. Wait the seconds `Retry-After` names and send the request again. A read is safe to repeat. A write is not, because the connection was lost in the middle of it, so read the object back before sending it a second time. Branch on the status rather than on `code`, which is `POSTGRES_UNAVAILABLE` from one of the two seams that raise this and `SERVICE_UNAVAILABLE` from the other.

---

[API](https://skmtc.dev/tightly/apis/tightly-api.md) · [All operations](https://skmtc.dev/tightly/apis/tightly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tightly/apis/tightly-api/revisions/199f7eb35afb?raw)
