Contract Appeals Data Dictionary¶
This document describes the fields available on the Contract Appeals API endpoint (/api/contract_appeals/). For filtering, ordering, and pagination, see the Contract Appeals API Reference.
Overview¶
Contract appeals are decisions of the two boards of contract appeals — the Civilian Board of Contract Appeals (CBCA), covering most civilian agencies from 2007 forward, and the Armed Services Board of Contract Appeals (ASBCA), covering the Department of Defense, NASA and the CIA from 2010 forward. About 8,200 decisions are available across the two boards.
These are Contract Disputes Act appeals: a contractor disputes a contracting officer's final decision under a contract it already holds — a claim, a termination, delay, or the amount owed — and appeals it to the board with jurisdiction. They are not bid protests, which challenge an award or a solicitation and live in a separate resource, Protests. No record appears in both.
One row is one decision as the board's own listing publishes it. A decision resolving several consolidated appeals is one row carrying several dockets.
Authentication: Contract appeal endpoints require authentication (API key or OAuth2).
Plans: every field except decision_text is available on every plan, including Free — as is the full-text search that runs over the decision text. decision_text itself requires an Enterprise plan; see The decision body below.
Note: Contract appeals are a flat resource with no expandable relations. The full field set is available via the shape query parameter. See Response Shaping.
Update Frequency¶
Both boards' listings are read daily, and new decisions appear in the API the same day they are picked up. Decision text is extracted from the boards' own documents on its own cadence, so a decision can be queryable before its text is.
Identity¶
The primary key and detail-lookup value is uuid. It is derived from the board and the decision's identity on that board's listing, not assigned sequentially, so it is stable across rebuilds of the dataset and safe to store alongside your own records.
document_id identifies the underlying decision document. It is usually one-to-one with uuid, but not always: a handful of CBCA listing rows link the same document, so a document_id can appear on more than one decision.
Dockets¶
docket_numbers is an array of strings, because a single decision can resolve several consolidated appeals.
Dockets are normalized to the form the board writes minus the board's own name: CBCA 3288-R is stored as 3288-R, and an ASBCA docket is stored as the bare number, 59116. The listing's verbatim text is kept in docket_raw.
A quantum or remand docket can name its source dockets in parentheses — 7092-C(6682, 6765, 6767). That whole string is one docket, commas and all; the commas are part of the value, not a separator between values.
docket_source says where the dockets came from:
| Value | Meaning |
|---|---|
listing | Parsed from the board's listing table — the usual case. |
text | Recovered from the decision document itself, where the listing published none. |
admin | Corrected by MakeGov staff after review. |
null | No docket was found for this decision. |
ASBCA decisions before 2014 generally have no dockets. That board's listing gained a docket-number column in 2014, and nothing earlier is reverse-engineered from a filename. ?docket= therefore cannot reach most pre-2014 ASBCA decisions; ?appellant= and ?search= can.
Dates¶
decision_date is the decision's own date as the board's listing gives it, parsed to a real date.
Both listings are typed by hand, and the parsing is conservative:
decision_date_rawkeeps the listing's cell verbatim, always, so you can see what was published.decision_dateis null where the cell cannot be read as a date with confidence. It is not guessed from the page it sits on.decision_date_repairedistrueon the small number of rows where a transposed year was put back — a cell readingApril 29, 2104on the Board's 2014 page. The repair is applied only when un-swapping the digits yields the page's own year; anything else stays null. The original cell is still indecision_date_raw.
first_listed_at is Tango's timestamp, not a board's: when the decision was first observed on a listing. It is the right field to poll on for "everything new since my last call", and the wrong field to read as a publication date — decision_date is that.
Listing state¶
listed is true while the board's newest listing still carries the decision.
When a board drops a decision from its listing, listed flips to false and the row is kept. Nothing is deleted: a uuid you stored last year still resolves. Filter ?listed=true for what the boards currently publish, or ?listed=false to see what has come off.
listing_url and listing_year say which listing page the decision came from.
The decision body¶
decision_text is the extracted text of the board's decision document, and it is the one Enterprise-only field on this resource.
Three facts about it, in order of how often they surprise people:
- Searching it is free.
?search=runs over the decision text on every plan including Free, and returns matching decisions with no fragment of the body. Buying the body buys the body, not better search. - Below Enterprise, naming it in a
shapereturns 200 with the field omitted and an entry inmeta.upgrade_hints. It is not an error, and the rest of the response is unaffected. - It can be null at any plan, because text extraction runs on its own cadence and some documents yield no text.
text_statusandtext_char_countreport that on every plan, so you can tell "we hold no text" from "the text did not match" without an Enterprise plan.
text_status | Meaning |
|---|---|
completed | Text was extracted and is held. |
empty | Extraction succeeded and produced no characters — almost always a scanned document. |
failed | Extraction was attempted and did not succeed. |
null | Extraction has not been attempted for this document yet. |
Fields¶
| Field | Type | Description | Source |
|---|---|---|---|
uuid | String (UUID) | Stable primary key and detail-lookup value. | Tango |
board | String | cbca or asbca. | Tango |
docket_numbers | Array of String | The decision's dockets, board prefix stripped. Several on a consolidated appeal; empty where the listing published none. | Board / Tango |
docket_source | String | Where the dockets came from: listing, text, admin, or null. | Tango |
docket_raw | String | The listing's docket cell, verbatim. | Board |
decision_date | Date | Date of the decision. Null where the published cell could not be read as a date. | Board |
decision_date_raw | String | The listing's decision-date cell, verbatim. | Board |
decision_date_repaired | Boolean | Whether a transposed year was repaired from the listing page's own year. | Tango |
appellant | String | The appealing party as the listing names it. | Board |
judge | String | The authoring judge as the listing names them. | Board |
decision_type | String | CBCA only: Decision, Dismissal, Order, Full Board Order, or the listing's own wording where it matches none of those. Null on every ASBCA decision and on CBCA decisions before 2015, when that column was added. | Board / Tango |
decision_type_raw | String | The listing's type cell, verbatim. Null wherever decision_type is. | Board |
url | String | The board's own link to the decision document. Available on every plan. | Board |
document_id | String | Identifier for the underlying decision document. Not unique: a few CBCA listing rows link the same document. | Tango |
listing_url | String | The board listing page the decision was read from. | Board |
listing_year | Integer | The year of that listing page. | Board |
first_listed_at | Datetime | When Tango first observed the decision on a listing. The field to poll on. | Tango |
listed | Boolean | Whether the board's newest listing still carries the decision. A delisted decision is kept with false. | Tango |
text_status | String | completed, empty, failed, or null — see The decision body. | Tango |
text_char_count | Integer | Character count of the extracted text, whether or not this response carries the text. | Tango |
decision_text | String | The extracted decision body. Enterprise plans only; omitted with an upgrade_hints entry below that. Null until extraction completes. | Board / Tango |
Default shapes¶
- List returns:
uuid,board,docket_numbers,decision_date,appellant,judge,decision_type,url. - Detail returns the list fields plus
docket_raw,docket_source,decision_date_repaired,decision_type_raw,listing_year,first_listed_at,listed,text_status,text_char_count.
decision_date_raw, document_id, listing_url and decision_text are in neither default; name them in ?shape= to get them.
Usage Notes¶
- Do not look for a bid protest here. GAO, Court of Federal Claims and SBA OHA cases are Protests; the two resources share no records.
- There is no agency, no UEI, and no contract number. The boards' listings publish the appellant, the docket, the judge, the date and the document — they do not publish the procuring agency, a resolved vendor identity, or the contract under appeal. Those facts are often in the decision's own text, which is why
?search=runs over it. - Alerts follow the record, including its delisting.
contract_appealis an alertable query type; a decision appearing, being delisted, or gaining its extracted text all fire. See Webhooks.
Data Sources¶
- CBCA — the Civilian Board of Contract Appeals' published decision listing, from 2007 forward.
- ASBCA — the Armed Services Board of Contract Appeals' published decision listings, from 2010 forward.
- Tango —
uuid, docket and date normalization,first_listed_at,listed, and the extracted decision text.