Protests Data Dictionary¶
This document describes the fields available in the Protests API endpoints (/api/protests/). For filtering, ordering, and pagination, see the Protests API Reference.
Overview¶
Protests are bid protest records from GAO, the U.S. Court of Federal Claims (COFC), and SBA OHA (the Small Business Administration's Office of Hearings and Appeals). The API exposes a narrow set of client-facing fields. Source ingest payload details and internal fields (e.g. external_id, data_quality) are not exposed. Filter by source_system (gao, cofc, or sba_oha) to scope results to a single venue.
Contract Disputes Act appeals — disputes under a contract already awarded, heard by the CBCA and the ASBCA — are a separate resource: Contract appeals. No record appears in both.
SBA OHA decisions are size and status appeals — a challenge to whether a firm qualifies as small, or as a service-disabled veteran-owned, women-owned, or HUBZone concern — rather than challenges to an award. They therefore populate a different set of fields: most name the challenged firm and the NAICS code at issue, and most carry no procuring agency at all.
COFC records come from the court's CM/ECF system, which publishes dockets and opinions rather than structured procurement metadata. They carry the case, the plaintiff, the dates and links to the court's own documents. agency and outcome are read from the court's opinion, so a case the court has not yet issued an opinion in carries an empty agency and no outcome; solicitation_number, naics_code, size_standard, outcome_reason, challenged_party and judge are not available from this source. A case arrives as a filing or as an opinion depending on which part of the court's system published it, so about 60% carry filed_date and docket_url and about 45% carry decision_date and decision_url.
Authentication: Protests endpoints require authentication (API key or OAuth2).
Coverage: The API covers protest decisions from 2015 onward for GAO and SBA OHA — the effective floor for the filed_date and decision_date filters alike. Pre-2015 records exist in the database but are not available through the API. COFC coverage starts in 2026 and moves forward: the court publishes a rolling twelve months of opinions, so earlier material is outside what this source offers.
Note: Both list and detail endpoints return case-level objects. Each case is identified by case_id (a deterministic UUID from source_system + base_case_number). Detail lookup uses case_id in the URL path: GET /api/protests/{case_id}/. Use ?shape=...,dockets(...) to expand nested docket records. The default (unshaped) response does not include dockets.
Update Frequency¶
GAO and SBA OHA protest data is refreshed by loader schedule and available source files. SBA OHA decisions arrive daily. COFC filings and opinions are collected daily.
Fields (API response)¶
Only the following fields are returned in list and detail responses (and are available via shape):
| Field | Type | Description | Source |
|---|---|---|---|
case_id | UUID | Deterministic case UUID derived from source_system + base_case_number. Use for detail lookup: GET /api/protests/{case_id}/. | Tango |
source_system | String | Source venue identifier: gao, cofc, or sba_oha. | Tango |
case_number | String | Base case for grouping sub-dockets (for example b-424214 from B-424214.1). Model field: base_case_number. Use with decision_date for decision-level counting. | Derived |
docket_number | String | Source docket identifier (for example b-424214.1, b-424214.2). Model field: case_number. Only available inside the dockets(...) expansion. Use to distinguish sub-dockets under the same case_number. | Source |
title | String | Protest title. | Source |
protester | String | Protester name. | Source |
agency | String | Protested agency, as Department : Sub-unit when the sub-unit is known (for example Department of the Navy : Naval Sea Systems Command). COFC and SBA OHA read it from the opinion or decision text; empty when the text names none. | Source |
solicitation_number | String | Solicitation number when provided. Not available on COFC. | Source |
case_type | String | Protest case type. GAO uses values like Bid Protest; COFC is always Bid Protest; SBA OHA uses SIZE, NAICS, VSBC, CVE, BDPE, SDVOSB, BDPT, WOSB, and HUBZONE. | Source |
outcome | String | Protest outcome, when available. GAO returns Denied, Dismissed, Withdrawn, or Sustained; SBA OHA additionally returns Granted, Remanded, Reversed, or Vacated. COFC returns Sustained, Denied, or Dismissed once the court issues an opinion. | Source |
filed_date | Date | Date the protest was filed. | Source |
posted_date | Date | Date the protest was posted. | Source |
decision_date | Date | Decision date, when available. | Source |
due_date | Date | Protest due date, when available. | Source |
docket_url | String | Source docket URL. On COFC, the court's CM/ECF docket report, on cases that arrived as a filing. | Source |
decision_url | String | Source decision URL, when available. | Source |
Opt-in via shape only: digest — when requested with ?shape=...,digest, the value from raw_data.digest (e.g. decision summary text) is returned. Not included in the default list/detail response.
Opt-in via shape only, SBA OHA: the five fields below are populated on SBA OHA decisions and are null on GAO and COFC records. Because they are null for most of the table, they are excluded from the default response — request them explicitly, for example ?shape=case_id,case_number,challenged_party,naics_code. They are available on every plan.
| Field | Type | Description |
|---|---|---|
challenged_party | String | The firm whose size or socioeconomic status was challenged. |
naics_code | String | The NAICS code at issue in the appeal. Also available as a filter: ?naics_code=541512. |
size_standard | String | The applicable size standard as written, for example $33.5 million or 1,000 employees. |
outcome_reason | String | Why a case was dismissed: untimely, moot, withdrawn, lack of jurisdiction, lack of standing, or insufficient specificity. |
judge | String | The authoring administrative judge. |
Resolution Fields (shape expansions)¶
Protests support entity and organization resolution via the Bayesian resolver. These fields are available as shape expansions and return null when no confident match exists.
resolved_protester(...) — Entity Resolution¶
| Field | Type | Description |
|---|---|---|
uei | String | Unique Entity Identifier of the matched entity. |
name | String | Display name of the matched entity. |
match_confidence | String | "confident" (high confidence, auto-linkable) or "review" (medium confidence, needs human review). |
rationale | String | Human-readable explanation (e.g. "Exact name match", "Similar name match; multiple entities share this name"). |
resolved_agency(...) — Organization Resolution¶
| Field | Type | Description |
|---|---|---|
key | String (UUID) | UUID primary key of the matched organization in Tango. |
name | String | Display name of the matched organization. |
match_confidence | String | "confident" or "review". |
rationale | String | Human-readable explanation (e.g. "Exact name match; parent agency confirmed"). |
Confidence mapping: Internal resolution tiers map to public labels as follows: high → "confident", medium → "review". Low-confidence and no-match results are excluded (return null).
The following are not exposed in the API: external_id, data_quality, source_last_updated, created, modified, raw_data, field_provenance.
Data Quality (internal)¶
Every protest record has an internal data_quality tier (not exposed in the API response). Records with quarantined or unknown quality are always excluded from API responses. Quality is recomputed on each ingestion cycle.
Shaping¶
Both list and detail return case-level objects. shape lets you request a subset of fields. Use the dockets(...) expansion to include nested docket records.
Allowed shape fields (case-level):
case_id,source_system,case_number,title,protester,agencysolicitation_number,case_type,outcomefiled_date,posted_date,decision_date,due_datedocket_url,decision_urldigest(fromraw_data.digest; opt-in only)dockets(expand with docket fields, e.g.dockets(case_number,docket_number,filed_date))resolved_protester(expand:uei,name,match_confidence,rationale)resolved_agency(expand:key,name,match_confidence,rationale)
Inside dockets(...), these additional fields are available:
docket_number(specific sub-docket identifier, e.g.b-424214.1)
Examples:
# List: case-level and nested dockets
GET /api/protests/?shape=case_id,case_number,title,dockets(docket_number,filed_date,outcome)
# List: case-level only
GET /api/protests/?shape=case_id,title,outcome,decision_date
# Detail with nested dockets
GET /api/protests/{case_id}/?shape=case_id,title,dockets(docket_number,filed_date)
raw_data and field-level provenance metadata are internal-only and not exposed in API responses.
Data Sources¶
- GAO – primary source for protest records.
- SBA OHA – size and status appeal decisions from the Small Business Administration's Office of Hearings and Appeals.
- Tango –
case_id(deterministic case UUID) and normalized API behavior.