A tide window is a promise
Why the API answers with the hours a draft clears, and never with a table to read by hand.
A tide table lists heights. A crew needs hours: when the water over the sill is deep enough for the keel, and when it stops being so.
From heights to hours
The window route takes a berth and a draft. It adds the charted depth to each predicted height, keeps the hours the sum clears the draft plus a margin, and returns the first and last.
{ "draft": 3.2, "opens": "08:05", "closes": "12:50" }
Why a promise
A window names its datum and its station, so a crew can check it. When the gauge disagrees with the prediction, the next call says so.