Guide
Changes
What the API promises about change, and what has changed, newest first.
What you can rely on#
- Changes are additive. A new field, argument, enum value or operation can appear at any time; a query you wrote keeps working.
- Nothing is removed without notice. A field or argument that is going away is marked deprecated in the schema, with the reason and what to use instead, and stays for at least six months after that.
- A new enum value can appear in a field you already read. Handle a value you do not know as "other" rather than failing.
- Error codes and
extensions.reasonvalues are part of the contract; a new reason can appear, an existing one is not renamed. - The Markdown pages and
llms.txtfollow the same rules, so an assistant that learned the API keeps its footing.
Deprecations appear in the reference as a tag on the field, and here with their date.
Not in the API yet#
What this documentation does not promise, because the product does not do it yet. Each will appear above, dated, when it lands.
- A "changed since" filter. A system that mirrors the portfolio reads it in full, as Keeping in sync shows.
- An assessment's own revisions. Every assessment is revision 0, and a value read again replaces the figure on the same one.
- The
INGESTEDbill status, theQUEUED,OCR_RUNNING,MATCH_FAILEDandCONFIRMEDextraction states, and theMAILED_PDF,EMAIL,SFTP_FEEDandUPLOADways a unit makes its bill available: in the schema, recorded for no unit and set by nothing today. Handle them as "other".
16 October 2026#
- Two changes need a change to your calls. Every review decision and every change to an appeal now names the version it was made from:
acceptBill,flagBillForClient,rejectBillandundoBillReviewtakeexpectedVersion, the bill'sversionas you read it, andupdateAppealStatusandrecordAppealOutcometake the appeal's. When the bill or the appeal changed after you read it, the call is refused withCONFLICT(extensions.reasonisSTALE_VERSION) and nothing is written. AndDeadline.parcelcan be null: a unit's own appeal window, which belongs to no parcel, is listed once with its unit. - A bill the unit re-issues with other charges (on a page that lists none, another total) is the bill's next
revision, under akeyof its own and waiting for review; the revision it replaces readsSUPERSEDED, a new status, and counts nowhere. A payment posted or interest grown still updates the bill in place.correctBillrecords a person's correction of a reading as the next revision, checked like any reading, andenterBillenters a bill by hand from a tax bill page no reading turned into one. - Documents:
startDocumentUploadgives a link, good once for fifteen minutes, toPUTa PDF, CSV or Excel file to; a bill PDF from a county the product reads exactly is read as a bill, and anything else is kept on the parcel as evidence.createDocumentLinkgives a five-minute path that opens a document without a header. A document is kept seven years; after that its route answers 410file_removed, and one that cannot be opened at the moment answers 503documents_unavailable. - Your own payment records:
recordPaymentandimportPayments(up to 2,000 rows a call, withdryRun) record payments, refunds and adjustments beside the county's figures, never into them.TaxBillInstallment.paymentsandpaidPerRecords,TaxBill.paidPerRecords,Deadline.paidPerRecordsandOutstandingTotal.installmentsPaidPerRecordssay what they show. - Bills:
annualTotal,chargesTotal,installmentsTotalandpenaltyIncludedgive the county's stated total, the charges and the installments apart.PAIDandCLOSEDare deprecated and never returned: a status is the review state alone, and what is paid isamountPaidandpaymentKnown, from the county, andpaymentsandpaidPerRecords, from your records.Validation.resolutionNoteandValidation.historykeep who resolved each check and why;Extraction.fieldsandpagessay where each figure was printed. - Dates are kept:
Deadline.idnames one,acknowledgeDeadlinemarks it handled, andsupersedessays what a moved date was.deadlineGenerationsays when the dates were last worked out.Deadline.paidPerRecordsneedsBILL_READ, asexposuredoes. - Appeals:
updateAppealchanges what an open or filed appeal asks for and when its window closes, and its note at any status;Appeal.versionandruleDeadlineOnare new. The evidence pack (APPEAL_EVIDENCE_PACK) is made for named appeals withReportFilter.appealIds, and as aZIPholds the documents themselves.rerunReportasks again for a report that failed or expired. - Owners and units:
legalEntitiesInPortfoliobreaks the portfolio down by owner of record;setLegalEntityTaxIdandclearLegalEntityTaxIdkeep an owner's tax identification number encrypted and show onlytaxIdLast4.assessingJurisdictions,Jurisdiction.rulesandJurisdiction.appealRequirementsgive each unit's dated rules with their evidence and what an appeal there needs;reportRuleandruleReportstell retrieve-IQ a rule looks wrong and show what became of it.ParcelInput.stateandParcelImportRowInput.statename a county outside California. - Engagements: the record says when the client approved it, under what reference and by whom, and when it was revoked and why. Revoking one stops your access the moment it is recorded; a report or an upload under way at that moment is not kept, and its message says so.
- The file feed is version 3: a bill a failed check holds back, or one a reviewer rejected, keeps its rows with its amounts empty,
figures_withheldtrue andwithheld_reasonsaying why, and its charges likewise;validation_warningslists only the checks still standing.
14 October 2026#
- Every operation's entry names every scope it needs. A change that returns a record needs the scope to read it as well as the scope to make it:
acceptBillneedsBILL_REVIEWandBILL_READ,upsertParcelneedsPARCEL_WRITEandPARCEL_READ,openAppealneedsAPPEAL_WRITEandPARCEL_READ.ingestionStatus,billInbox,inboxSummaryandportfolioSummaryneedPARCEL_READbeside their own scope. Each MCP tool's entry names its scopes. - A key's scopes hold wherever its work runs: a report is produced with the engagement's scopes capped by the key's,
requestReportrefuses a key or an engagement without the scopes a report reads with (reportCataloglists them asscopes), and a queued report fails if that access ends before it runs.Deadline.exposure, the balance at stake on a payment, needsBILL_READ; the dates still need onlyPARCEL_READ, and a calendar feed made withoutBILL_READcarries the dates alone. - Revoking a key ends what it made: a calendar feed it created answers 403 from then on, and a report it requested that has not run yet fails. An unknown, revoked or expired key answers 401, as a missing token does; switch on
extensions.codeall the same. deadlinesand the calendar feed cover the whole portfolio; the first 500 parcels by parcel number was the earlier limit.portfolioSummaryis computed from the portfolio as it stands when it is read.jurisdictionsasks for a state, a level or a search, takeslevelandfirst(500 when omitted, up to 5,000), and answers in state and name order.teamlists the people who can sign in, to a person signed in to the app and not to a key.acceptBillrefuses a bill with an error-level check standing on any of its installments, not only the ones named.countiesInPortfoliobreaks a tie on the amount owed by name.upsertParcelandimportParcelsrefuse the state's own name as a county.ReportJob.erroris a sentence for the person who asked, not a note for the operator.Portalno longer carries the survey's own notes, rule codes and reader codes.- The examples select only what their scopes allow, and the Keeping in sync read is two queries, each held under the limits; the earlier one did not fit.
- Descriptions say what is reserved rather than what is planned: every bill and assessment is
revision0 and a fetch refreshes it in place;INGESTED,PAIDandCLOSEDare set by nothing today; a rejected bill is not reopened by a later fetch; a decided appeal cannot be changed. - The file feed as it is written:
fetched_atmoves whenever an account is read again, so two nights rarely match byte for byte;validation_warningssits on the bill's first installment row and lists the checks no person has resolved, cleared ones included;line_items.csvjoins to that same row; a client whose fetch failed is left out of the files; the feed's ids differ in form from the API's. - The Python first request uses the standard library only.
13 October 2026#
- This documentation: every query, mutation, type, field and argument described, the scope each operation needs on its entry, an example for each operation, and the tool list of the MCP server.
- Common tasks, Keeping in sync and AI assistants pages added.
- The schema is served at
/docs/schema.graphql.