schema_version with
advance notice and an overlap window — your integration always knows which
shape it’s reading, because every result declares its version.
2026-08
-
Extractions are more accurate and take longer; the documented durations
now match. We moved rent-roll extraction to a stronger model after
finding it was misreading columns — square footage landing in market rent,
market rent landing in rent, unit status dropped entirely. On the
documents where we could measure the same file under both models, that
cost 1.4x to 5.5x in run time. The published figures had said “1-5
minutes” for everything, which was no longer true for rent rolls. Measured
over 79 live extractions: a T-12, offering memorandum or other document
usually finishes in 2-5 minutes (91% within five); a rent roll runs a
second consolidation phase and is the slow path, with most within 10
minutes and a large one reaching 30. The 60-minute ceiling is unchanged,
and no refund, polling or webhook behaviour changed. If your integration
hard-codes a timeout under ten minutes, raise it —
poll_after_secondsand thewaitlong-poll are there so you never have to guess. -
asset_classis now required onPOST /v1/extractions. It was optional, which read as a hint but behaved as a cliff. Without a class, rent-roll consolidation fell back to the cross-class column subset — 14 standard columns instead of multifamily’s 29 — somarket_rent,area,bedrooms,bathrooms,bed_bath,move_in,move_out,deposit,concession,other_income,floor,furnished,escalation,subsidizedandsubsidy_amountstopped being standard fields and came back undercustom__*keys named after whatever the source document’s header happened to say. Two rent rolls of the same asset class could therefore disagree —custom__sqftin one,custom__sq_feetin the next — and nothing in the response explained why. Requests without the field now return400 invalid_requestnamingasset_class, rather than quietly returning the narrower shape. Accepted values are unchanged:multifamily,self-storage,industrial-outdoor-storage,commercial,industrial,office,retail,hotel. Theasset_classargument on thecreate_extractionMCP tool is required to match. Adding the field is the whole migration; callers already sending it are unaffected.
2026-07
- Per-product account access, and an errors reference. Accounts are now
enabled per product, so an endpoint your account hasn’t bought returns
403with the newproduct_not_enabledcode and a message naming what to do about it, rather than working. The existingmissing_scopecode now means something narrower: the account has the product, but the key you used was issued without it. Both are documented alongside every other code the API returns on the new Errors page. Two related changes:/v1/underwriting-inputsnow belongs to the underwriting product rather than extraction, and the MCP server advertises only the tools your key can use. No change for accounts enabled for everything. - T-12 month headers: Spanish abbreviations, and a coverage check.
Column headers written in Spanish (
Dic-25,Ene-25,Abr-25,Ago-25,Set-25) now map to months like their English equivalents. Previously such a column was dropped fromheadersand from everyline_itemsentry, so a statement’s monthly figures could silently under-report the year by a month. A newt12_column_coveragevalidation check reportswarningwhenever a column that carried data was dropped because its header could not be interpreted —t12_month_mappingonly describes the columns that were read, so it could not surface this. - Long polling and richer job status.
GET /v1/extractions/{id}andGET /v1/underwritings/{id}accept?wait=(0-45 seconds), holding the request until the job finishes so you don’t need a sleep loop; a wait that elapses returns the in-flight state as a normal200. In-flight responses now includepoll_after_seconds(mirrored in aRetry-Afterheader) andelapsed_seconds, and rent-roll documents reportphase(extracting→consolidating) so two-phase jobs are visibly progressing. The samewaitargument is available on theget_extractionandget_underwritingMCP tools. All additive — existing polling code is unaffected. - MCP server.
https://api.trycactus.com/mcpexposes the API as tools for Claude, Cursor, and any other MCP client, authenticated with your existing API key. See MCP Server. - Typed T-12 and offering memorandum results. T-12 extractions now
return
t12.v1: report metadata, the statement’s line items with every monthly value and its source cell, and aheadersarray typing each spreadsheet column as a calendarmonth, a namedtotal, orunknown. Filter totype: monthfor the trailing-twelve series — statements routinely carry extra columns, and a column is only called a total when the document names it one. Offering memorandum extractions now returnoffering_memorandum.v1: every extracted fact organized into the document’s own sections, plus apropertysummary of the key property attributes. Extractions that produce no data at all now fail and are refunded in full instead of returning an empty result. - Typed rent roll results. Rent-roll extractions now return
rent_roll.v1: a normalized unit table (typed headers, one entry per unit) and the as-of date. If the structured result cannot be produced, the extraction fails and the charge is refunded in full — you are never billed for output you didn’t receive. - Initial release. Documents, extractions, usage, and webhook endpoints
are live. Other document types return the
facts.v1schema — extracted values with confidence scores and source locations.