Response Shaping (Custom Fields)¶
Tango’s API lets you request only the fields you want by passing a shape query parameter. Shaped responses are built directly from your selection for speed and consistency. If you omit shape, the endpoint returns the default serializer output.
Endpoints with shaping¶
- Agencies (legacy lookups):
- Departments:
/api/departments/ - Agencies:
/api/agencies/ - Offices:
/api/offices/ - Reference data:
- Business Types:
/api/business_types/ - NAICS:
/api/naics/ - PSC:
/api/psc/ - Assistance Listings:
/api/assistance_listings/ - MAS SINs:
/api/mas_sins/ - Awards (canonical routes):
- Contracts:
/api/contracts/ - IDVs:
/api/idvs/ - OTAs:
/api/otas/ - OTIDVs:
/api/otidvs/ - Subawards:
/api/subawards/ - Vehicles:
/api/vehicles/ - GSA eLibrary Contracts:
/api/gsa_elibrary_contracts/ - CALC Rates (nested):
/api/idvs/{key}/lcats/,/api/entities/{uei}/lcats/ - Organizations:
/api/organizations/ - Entities:
/api/entities/ - Forecasts:
/api/forecasts/ - Grants:
/api/grants/ - Opportunities (canonical routes):
- Opportunities:
/api/opportunities/ - Opportunity Notices:
/api/notices/ - Protests:
/api/protests/
All standard filters, ordering, pagination, throttling, and rate‑limit headers still apply.
Shape syntax¶
- Root leaves:
key,piid,award_date - Expansions (related objects):
recipient(display_name,uei) - Multiple items:
key,piid,recipient(display_name),awarding_office(office_code,office_name) - Star in child selections:
recipient(*)returns all allowed fields ofrecipient - Aliasing:
field::aliasorchild(field::alias) - Bracket parameters:
expand[key=value](children)— pass configuration to an expansion
Bracket parameters¶
Some expansions accept parameters via bracket syntax. Parameters go between the expansion name and the child selection:
# Top 10 agencies in past_performance
/api/entities/?shape=uei,past_performance[top=10](*)
# Multiple params (comma-separated)
/api/entities/?shape=uei,past_performance[top=3](summary,top_agencies)
Parameters are validated server-side with type checking and range enforcement. Unknown or out-of-range parameters return a 400 error with details.
Leaves vs expansions¶
In the shape DSL there are two different kinds of selections:
- Leaf:
field_name - Expansion:
expand_name(child1,child2,...)
Some endpoints expose the same name as both a leaf and an expansion. In those cases, the API will keep the selection as a leaf unless the shaping runtime determines that treating the token as a leaf would be unsafe (see “Bare expansions” below).
Example (Opportunities set-aside):
# Leaf (code string)
/api/opportunities/?shape=opportunity_id,title,set_aside
# Expansion (structured form)
/api/opportunities/?shape=opportunity_id,title,set_aside(code,description)
Bare expansions (shorthand)¶
If you write an expansion name without parentheses, e.g. office instead of office(*), Tango will sometimes treat it as shorthand for office(*).
This shorthand is applied only when needed for safety:
- when the expansion is a relation fetch (
select_related/prefetch_related), or - when the expansion is a “virtual” expansion with
path="*"(builder reads from the parent object), unless the value is field-map-backed.
Examples (Notices):
# Bare expansions: office == office(*), opportunity == opportunity(*)
/api/notices/?shape=notice_id,opportunity_id,office,opportunity&limit=1
Example response (shape excerpt):
[
{
"notice_id": "d2e3f9bf-9c2e-4c58-84f1-2b2b8a1d3b4d",
"opportunity_id": "ff12a2d0-3b8a-4a1d-8d7f-7d8c2b6c0a11",
"office": {
"office_code": "W91QF5",
"office_name": "ACC-APG",
"agency_code": "9700",
"agency_name": "DEPT OF THE ARMY",
"department_code": "97",
"department_name": "DEPARTMENT OF DEFENSE"
},
"opportunity": {
"opportunity_id": "ff12a2d0-3b8a-4a1d-8d7f-7d8c2b6c0a11",
"link": "/api/opportunities/ff12a2d0-3b8a-4a1d-8d7f-7d8c2b6c0a11/"
}
}
]
Examples:
# Basic
/api/contracts/?shape=key,piid,recipient(display_name)
# Aliasing
/api/contracts/?shape=key::id,recipient(display_name::name)
# Star in nested expansion
/api/contracts/?shape=key,recipient(*),transactions(*)
Child field aliasing inside an expand:
Response:
Notes:
*is only valid inside a child selection (e.g.,recipient(*)). Root‑level*is not supported.- Shaping requests that include unknown fields/expands, malformed shapes, or
shapeon non-shaping endpoints return a 400 with a structured error payload.
Flattening¶
Add flat=true to flatten nested objects with a joiner (default .). Works with both paginated and single‑object responses.
curl -H "X-API-KEY: <key>" \
"https://tango.makegov.com/api/contracts/?shape=key,recipient(display_name)&flat=true&joiner=."
Response:
Notes:
- Flattening applies to nested objects (dicts). Lists remain arrays for readability and stability by default. Expansions like
relationships(entities) andattachments(opportunities/notices) will remain arrays of objects even whenflat=true. - Optional:
flat_lists=truewill additionally flatten lists of objects into indexed keys (e.g.,relationships.0.uei). This is opt‑in and defaults tofalse.
Examples:
# Flatten dicts only (default list behavior)
/api/entities/?shape=uei,relationships(uei,display_name)&flat=true
# Also flatten list elements into indexed keys
/api/entities/?shape=uei,relationships(uei,display_name)&flat=true&flat_lists=true&joiner=.
Validation & limits¶
- Unknown fields or expansions return a 400 with structured issues.
- Malformed shapes (syntax errors) return a 400 with a
parse_errorissue. - Passing
shapeto an endpoint that does not support shaping returns a 400 (instead of ignoringshape). - Default limits (subject to change):
SHAPE_MAX_DEPTH= 2SHAPE_MAX_FIELDS= 64 (for user-supplied?shape=params; server-controlled default shapes may exceed this)
Example errors:
{
"error": "Invalid shape",
"issues": [{"path": "foo", "reason": "unknown_field"}],
"available_fields": {
"fields": ["award_date", "key", "piid", "recipient"],
"expands": {"recipient": {"fields": ["uei", "display_name"], "expands": {}, "wildcard_fields": false}},
"wildcard_fields": false
}
}
{
"error": "Invalid shape",
"issues": [{"path": "$", "reason": "parse_error (Unclosed '(')"}],
"available_fields": {
"fields": ["award_date", "key", "piid", "recipient"],
"expands": {"recipient": {"fields": ["uei", "display_name"], "expands": {}, "wildcard_fields": false}},
"wildcard_fields": false
}
}
{
"error": "Invalid shape value(s): foo. Shaping is not available for /api/example/.",
"issues": [{"path": "$", "reason": "shape_not_supported"}]
}
Discovering available fields¶
Every shaped endpoint supports ?show_shapes=true for schema discovery. Truthy values: true, 1, yes, on.
It works in two modes:
Schema-only (no ?shape=)¶
Pass ?show_shapes=true without a ?shape= parameter to get just the schema — no data is fetched, no DB query is made:
{
"available_fields": {
"fields": ["award_date", "awarding_office", "description", "key", "naics_code", "piid", "recipient", "transactions"],
"expands": {
"awarding_office": {"fields": ["agency_code", "agency_name", "office_code", "office_name"], "expands": {}, "wildcard_fields": false},
"recipient": {"fields": ["cage_code", "display_name", "legal_business_name", "uei"], "expands": {}, "wildcard_fields": false},
"transactions": {"fields": ["action_type", "description", "modification_number", "obligated", "transaction_date"], "expands": {}, "wildcard_fields": false}
},
"wildcard_fields": false
}
}
Schema appended to data (with ?shape=)¶
Pass both ?shape=... and ?show_shapes=true to get the normal shaped response with a _shaping block appended:
{
"count": 1234,
"next": "...",
"previous": null,
"results": [
{"key": "CONT_AWD_...", "piid": "GS00Q14OADS134"}
],
"_shaping": {
"available_fields": {
"fields": ["award_date", "awarding_office", "description", "key", "naics_code", "piid", "recipient", "transactions"],
"expands": {
"awarding_office": {"fields": ["agency_code", "agency_name", "office_code", "office_name"], "expands": {}, "wildcard_fields": false},
"recipient": {"fields": ["cage_code", "display_name", "legal_business_name", "uei"], "expands": {}, "wildcard_fields": false},
"transactions": {"fields": ["action_type", "description", "modification_number", "obligated", "transaction_date"], "expands": {}, "wildcard_fields": false}
},
"wildcard_fields": false
}
}
}
Schema structure¶
Each level of the schema contains:
| Key | Type | Meaning |
|---|---|---|
fields | array | All valid shape keys at this level, including both leaf fields and expand names. |
expands | object | Expandable relations, each containing its own nested {fields, expands, wildcard_fields} schema. |
wildcard_fields | boolean | When true, the expansion accepts any field name (i.e., expand(*) returns all keys from the underlying data, and you can also request arbitrary keys by name). When false, only the fields listed in fields are valid. Most endpoints return false; wildcard_fields: true appears on expansions backed by freeform JSON (e.g., raw_data(*) on forecasts). |
Notes:
- Schema-only mode (
?show_shapes=truealone) makes no DB queries — safe to call frequently. _shapingis appended afterresultsin paginated responses and after all other keys in detail responses, so existing clients that ignore unknown keys are unaffected.- All 400 error responses for invalid shapes also include
available_fieldsat the top level (no?show_shapesneeded).
Date/time formatting¶
All datetimes in shaped responses are formatted using a consistent ISO‑8601 format.
Identity fallback for missing relations¶
When an expanded relation is missing (e.g., a join yields no row), the API returns a minimal identity object using the FK value instead of null:
Field reference by endpoint (excerpt)¶
Below is a concise reference of commonly used fields and expansions per endpoint. Use (*) inside an expansion to request all allowed fields for that relation.
Departments /api/departments/¶
- Leaves:
code,name,abbreviation,description,cgac,website,congressional_justification - No expansions.
Default response (no ?shape=): code,name,abbreviation
# Select specific fields
/api/departments/?shape=code,name
# Extended department info
/api/departments/?shape=code,name,description,cgac,website,congressional_justification
Agencies /api/agencies/¶
- Leaves:
code,name,abbreviation - Expansions:
department(code,name,abbreviation,description,cgac,website,congressional_justification)
Default response (no ?shape=): code,name,abbreviation,department(name,code)
# Just codes and names
/api/agencies/?shape=code,name
# Include department info
/api/agencies/?shape=code,name,department(name,code)
# Department with extended fields
/api/agencies/?shape=code,department(name,description,cgac,website)
# All department fields
/api/agencies/?shape=code,department(*)
Offices /api/offices/¶
- Leaves:
code,name, plus flat aliasesoffice_code,office_name,agency_code,agency_name,department_code,department_name - Expansions:
agency(code,name,abbreviation)department(code,name,abbreviation,description,cgac,website,congressional_justification)
Default response (no ?shape=): office_code,office_name,agency_code,agency_name,department_code,department_name (flat aliases)
# Default flat format
/api/offices/?shape=office_code,office_name,agency_name
# Direct leaves with nested expansions
/api/offices/?shape=code,name,agency(code,name,abbreviation)
# Office with department details
/api/offices/?shape=code,name,department(name,description,website)
# Both expansions
/api/offices/?shape=code,name,agency(code,name),department(code,name)
Business Types /api/business_types/¶
- Leaves:
name,code - No expansions.
Default response (no ?shape=): name,code
NAICS /api/naics/¶
- Leaves:
code,description - Expansions:
size_standards(employee_limit,revenue_limit)— SBA size standards for this NAICS code.revenue_limitis in whole dollars (e.g.,2250000).federal_obligations(total,active)— obligation rollups. Each sub-object containsawards_obligated(float) andawards_count(int).
Default response (list, no ?shape=): code,description
Default response (detail or show_limits=1): code,description,size_standards(*),federal_obligations(*)
Note: The legacy ?show_limits=1 parameter is still supported — it triggers the same response as ?shape=code,description,size_standards(*),federal_obligations(*). Prefer using ?shape= directly.
# List with just code and description (default)
/api/naics/?shape=code,description
# Include size standards and obligations (equivalent to ?show_limits=1)
/api/naics/?shape=code,description,size_standards(*),federal_obligations(*)
# Size standards only
/api/naics/541330/?shape=code,description,size_standards(employee_limit,revenue_limit)
# Obligations total only
/api/naics/541330/?shape=code,federal_obligations(total)
PSC /api/psc/¶
- Leaves:
code,parent,category,level_1_category,level_1_category_code,level_2_category,level_2_category_code - Expansions:
current(name,active,start_date,end_date,description,includes,excludes)— active or latest descriptionhistorical(name,active,start_date,end_date,description,includes,excludes)— all descriptions
Default response (no ?shape=): code,current(*),parent,category,level_1_category,level_1_category_code,level_2_category,level_2_category_code
# Just code and current description name
/api/psc/?shape=code,current(name)
# Code with current and historical descriptions
/api/psc/AD12/?shape=code,current(name,active),historical(name,active)
Assistance Listings /api/assistance_listings/¶
- Leaves:
number,title,published_date,archived_date,popular_name,objectives,applicant_eligibility,benefit_eligibility - No expansions.
Default response (list, no ?shape=): number,title
Note: Detail responses (/api/assistance_listings/{number}/) use the full serializer (includes all fields) when no ?shape= param is provided.
# Include extra fields
/api/assistance_listings/?shape=number,title,objectives
# Detail with specific fields
/api/assistance_listings/10.001/?shape=number,title,objectives,popular_name
MAS SINs /api/mas_sins/¶
- Leaves:
sin,large_category_code,large_category_name,sub_category_code,sub_category_name,psc_code,state_local,set_aside_code,service_comm_code,expiration_date,tdr,olm,naics_codes,title,description - No expansions.
Default response (no ?shape=): all 15 fields above.
Organizations /api/organizations/¶
Organizations uses a default shape — all responses go through the shaping pipeline even without ?shape=.
- Default shape:
key,fh_key,name,short_name,type,level,is_active,code,fpds_code,cgac,canonical_code,parent_fh_key,full_parent_path_name - Additional leaves:
fpds_org_id,aac_code,start_date,end_date,logo,summary,l1_fh_keythroughl8_fh_key,total_obligations,tree_obligations,mod_status,description,obligations,obligation_rank - Expansions:
parent(key,fh_key,name,short_name,type,level,is_active,code,cgac)ancestors(fh_key,name,short_name,level)children(key,fh_key,name,short_name,type,level,is_active,code,cgac)department(code,name,abbreviation)agency(code,name,abbreviation)
# Default response (all responses are shaped)
/api/organizations/
# Select specific fields
/api/organizations/?shape=fh_key,name,type,level
# Include department and agency expands
/api/organizations/?shape=fh_key,name,department(code,name),agency(code,name,abbreviation)
Contracts /api/contracts/¶
- Leaves:
key,piid,award_date,naics_code,psc_code,total_contract_value,description,base_and_exercised_options_value,fiscal_year,obligated,set_aside,award_type,transactions,subawards_summary - Expansions:
recipient(uei,display_name,legal_business_name,cage,duns,...)awarding_office(office_code,office_name,agency_code,agency_name,department_code,department_name)funding_office(...)place_of_performance(country_code,country_name,state_code,state_name,city_name,zip_code)parent_award(key,piid)period_of_performance(start_date,current_end_date,ultimate_completion_date)transactions(modification_number,transaction_date,obligated,description,action_type)subawards_summary(count,total_amount)competition(contract_type,extent_competed,number_of_offers_received,other_than_full_and_open_competition,solicitation_date,solicitation_identifier,solicitation_procedures)officers(highly_compensated_officer_1_name,highly_compensated_officer_1_amount,highly_compensated_officer_2_name,highly_compensated_officer_2_amount,highly_compensated_officer_3_name,highly_compensated_officer_3_amount,highly_compensated_officer_4_name,highly_compensated_officer_4_amount,highly_compensated_officer_5_name,highly_compensated_officer_5_amount)– returnsnullif no officers are on record. Not included in default serializers; available only via shaping.
Examples:
# Minimal contract fields
/api/contracts/?shape=key,piid,award_date
# Recipient and awarding office
/api/contracts/?shape=key,recipient(display_name),awarding_office(office_code,office_name)
# Period and transactions
/api/contracts/?shape=key,period_of_performance(start_date,current_end_date),transactions(modification_number,obligated)
# Officers (subset)
/api/contracts/?shape=key,officers(highly_compensated_officer_1_name,highly_compensated_officer_1_amount)
# Officers (all allowed fields)
/api/contracts/?shape=key,officers(*)
IDVs /api/idvs/¶
- Leaves:
key,piid,vehicle_uuid,solicitation_identifier,award_date,naics_code,psc_code,total_contract_value,description,fiscal_year,obligated,idv_type,multiple_or_single_award_idv,type_of_idc,set_aside,transactions,subawards_summary - Detail-only leaves:
commercial_item_acquisition_procedures,consolidated_contract,contingency_humanitarian_or_peacekeeping_operation,contract_bundling,contract_financing,cost_accounting_standards_clause,cost_or_pricing_data,dod_acquisition_program,dod_transaction_number,domestic_or_foreign_entity,email_address,epa_designated_product,evaluated_preference,fair_opportunity_limited_sources,fed_biz_opps,fee_range_lower_value,fee_range_upper_value,fixed_fee_value,foreign_funding,government_furnished_property,idv_website,inherently_governmental_functions,local_area_set_aside,major_program,number_of_actions,number_of_offers_source,ordering_procedure,performance_based_service_acquisition,program_acronym,recovered_materials_sustainability,research,sam_exception,simplified_procedures_for_certain_commercial_items,small_business_competitiveness_demonstration_program,subcontracting_plan,total_estimated_order_value,tradeoff_process,type_of_fee_for_use_of_service,undefinitized_action,who_can_use - Expansions:
recipient(uei,display_name,legal_business_name,cage,duns,...)awarding_office(office_code,office_name,agency_code,agency_name,department_code,department_name)funding_office(...)place_of_performance(country_code,country_name,state_code,state_name,city_name,zip_code)parent_award(key,piid)period_of_performance(start_date,last_date_to_order)— note: useslast_date_to_orderinstead of contracts'current_end_date/ultimate_completion_datetransactions(modification_number,transaction_date,obligated,description,action_type)subawards_summary(count,total_amount)idv_type(code,description)— IDV type as structured code/descriptionmultiple_or_single_award_idv(code,description)— single/multiple award designationtype_of_idc(code,description)— IDC type as structured code/descriptionset_aside(code,description)— set-aside typenaics(code,description)— resolved NAICS lookuppsc(code,description)— resolved PSC lookupcompetition(contract_type,extent_competed,number_of_offers_received,other_than_full_and_open_competition,solicitation_date,solicitation_identifier,solicitation_procedures)officers(...)— same fields as contracts;nullwhen absent; shaping-onlyawards(key,piid,award_date,naics_code,psc_code,total_contract_value,description,base_and_exercised_options_value,fiscal_year,obligated,transactions)— child awards under this IDVgsa_elibrary(schedule,contract_number,uei,sins,cooperative_purchasing,disaster_recovery_purchasing,file_urls,extracted_text,external_id,source_data)— GSA eLibrary enrichment (nullwhen no match)legislative_mandates(...)— legislative mandate flags
Default response (list, no ?shape=): award_date,awarding_office(*),description,fiscal_year,funding_office(*),gsa_elibrary(*),idv_type(*),key,legislative_mandates(*),multiple_or_single_award_idv(*),naics_code,obligated,parent_award(*),period_of_performance(*),piid,place_of_performance(*),psc_code,recipient(*),set_aside,solicitation_identifier,subawards_summary(*),total_contract_value,type_of_idc(*),vehicle_uuid
Default response (detail): adds all detail-only leaves plus competition(*) and officers(*)
# Minimal IDV fields
/api/idvs/?shape=key,piid,award_date
# Expand idv_type to get code + description
/api/idvs/?shape=key,piid,idv_type(code,description)
# IDV with recipient and awarding office
/api/idvs/?shape=key,piid,recipient(display_name,uei),awarding_office(office_name,agency_name)
# Period of performance with last_date_to_order
/api/idvs/?shape=key,piid,period_of_performance(start_date,last_date_to_order)
# GSA eLibrary enrichment
/api/idvs/?piid=GS-35F-0001X&shape=key,piid,gsa_elibrary(schedule,contract_number,sins,file_urls)
# Child awards under an IDV
/api/idvs/{key}/?shape=key,piid,awards(key,piid,total_contract_value)
Vehicles /api/vehicles/¶
- Leaves:
uuid,solicitation_identifier,agency_id,organization_id,vehicle_type,fiscal_year,agency_details,descriptions,competition_details,type_of_idc,contract_type,awardee_count,order_count,vehicle_obligations,vehicle_contracts_value,solicitation_title,solicitation_description,solicitation_date,naics_code,psc_code,set_aside - Expansions:
awardees(...): expands to the underlying IDVs that make up the vehicleopportunity(...): expands to the linked SAM.gov Opportunity (supports all Opportunity fields and expansions likeoffice,attachments,meta)competition_details(...): expands thecompetition_detailsJSON object (fields:extent_competed,number_of_offers_received,set_aside,solicitation_procedures, etc., or*for all)
Default response (list, no ?shape=): agency_details,award_date,awardee_count,competition_details(*),contract_type,description,fiscal_year,last_date_to_order,latest_award_date,naics_code,order_count,psc_code,set_aside,solicitation_date,solicitation_identifier,solicitation_title,type_of_idc,uuid,vehicle_contracts_value,vehicle_obligations,vehicle_type,who_can_use
Default response (detail): adds agency_id, organization_id, solicitation_description
Notes:
GET /api/vehicles/?search=...performs vehicle-level full-text search.- On
GET /api/vehicles/{uuid}/,?search=is reserved for filtering expandedawardees(...)(it does not filter the vehicle itself). - Opportunity-derived fields (
solicitation_title,solicitation_description,solicitation_date,naics_code,psc_code,set_aside) are populated from the linked SAM.gov Opportunity's latest notice when available.
Examples:
# Find vehicles by term
/api/vehicles/?search=schedule
# Vehicle detail + shaped award expansion
/api/vehicles/<vehicle-uuid>/?shape=uuid,solicitation_identifier,awardees(key,uuid,piid,award_date,recipient(display_name,uei))
# Include opportunity-derived fields
/api/vehicles/<vehicle-uuid>/?shape=uuid,solicitation_identifier,solicitation_title,solicitation_date,naics_code,psc_code
# Expand linked Opportunity with office details
/api/vehicles/<vehicle-uuid>/?shape=uuid,solicitation_identifier,opportunity(opportunity_id,title,first_notice_date,office(office_name,agency_name))
# Expand JSON detail fields to select specific sub-fields
/api/vehicles/<vehicle-uuid>/?shape=uuid,competition_details(extent_competed,number_of_offers_received),type_of_idc,contract_type
# Filter expanded awards within a vehicle
/api/vehicles/<vehicle-uuid>/?shape=uuid,awardees(key,uuid,recipient(display_name))&search=acme
OTAs /api/otas/¶
- Leaves:
key,piid,award_date,psc_code,total_contract_value,description,base_and_exercised_options_value,fiscal_year,obligated,award_type,type_of_ot_agreement,extent_competed,consortia,consortia_uei,dod_acquisition_program,non_governmental_dollars,non_traditional_government_contractor_participation,parent_award_modification_number,transactions - Expansions:
recipient(uei,display_name,legal_business_name,cage,duns,...)awarding_office(office_code,office_name,agency_code,agency_name,department_code,department_name)funding_office(...)place_of_performance(country_code,country_name,state_code,state_name,city_name,zip_code)parent_award(key,piid)period_of_performance(start_date,current_end_date,ultimate_completion_date)transactions(modification_number,transaction_date,obligated,description,action_type)psc(code,description)award_type(code,description)— OTA-specific choices ("O" = Other Transaction Non-Research, "R" = Other Transaction for Research)type_of_ot_agreement(code,description)extent_competed(code,description)
Default response (no ?shape=): award_date,award_type,awarding_office(*),base_and_exercised_options_value,consortia,consortia_uei,dod_acquisition_program,extent_competed,fiscal_year,funding_office(*),key,non_governmental_dollars,non_traditional_government_contractor_participation,parent_award(key,piid),parent_award_modification_number,period_of_performance(start_date,current_end_date,ultimate_completion_date),piid,place_of_performance(*),psc_code,recipient(*),type_of_ot_agreement
Note: OTAs have no naics_code field and no naics expand.
# Minimal OTA fields
/api/otas/?shape=key,piid,award_date
# Expand award_type to get OTA-specific code + description
/api/otas/?shape=key,piid,award_type(code,description)
# Expand extent competed and type of OT agreement
/api/otas/?shape=key,piid,extent_competed(code,description),type_of_ot_agreement(code,description)
# OTA with recipient and awarding office
/api/otas/?shape=key,piid,recipient(display_name,uei),awarding_office(office_name,agency_name)
OTIDVs /api/otidvs/¶
- Leaves:
key,piid,award_date,psc_code,total_contract_value,description,base_and_exercised_options_value,fiscal_year,obligated,idv_type,type_of_ot_agreement,extent_competed,consortia,consortia_uei,dod_acquisition_program,non_governmental_dollars,non_traditional_government_contractor_participation,transactions - Expansions:
recipient(uei,display_name,legal_business_name,cage,duns,...)awarding_office(office_code,office_name,agency_code,agency_name,department_code,department_name)funding_office(...)place_of_performance(country_code,country_name,state_code,state_name,city_name,zip_code)period_of_performance(start_date,current_end_date,ultimate_completion_date)transactions(modification_number,transaction_date,obligated,description,action_type)psc(code,description)type_of_ot_agreement(code,description)extent_competed(code,description)
Default response (no ?shape=): award_date,awarding_office(*),base_and_exercised_options_value,consortia,consortia_uei,dod_acquisition_program,extent_competed,fiscal_year,funding_office(*),idv_type,key,non_governmental_dollars,non_traditional_government_contractor_participation,period_of_performance(start_date,current_end_date,ultimate_completion_date),piid,place_of_performance(*),psc_code,recipient(*),type_of_ot_agreement
Note: OTIDVs have no naics_code field, no naics expand, and no parent_award expand.
# Minimal OTIDV fields
/api/otidvs/?shape=key,piid,award_date
# Expand extent competed and type of OT agreement
/api/otidvs/?shape=key,piid,extent_competed(code,description),type_of_ot_agreement(code,description)
# OTIDV with recipient
/api/otidvs/?shape=key,piid,recipient(display_name,uei),awarding_office(office_name,agency_name)
Subawards /api/subawards/¶
Subawards use a default shape — all responses go through the shaping pipeline even without ?shape=.
- Default response (no
?shape=):award_key,awarding_office(*),fsrs_details(*),funding_office(*),key,piid,place_of_performance(*),prime_recipient(uei,display_name),subaward_details(*),subaward_recipient(uei,display_name) - Leaves: identity + prime award metadata (
piid,prime_award_total_outlayed_amount, dates/NAICS/description, prime/subawardee identities, business types, andusaspending_permalink) - Expansions:
subaward_details(description,type,number,amount,action_date,fiscal_year)fsrs_details(last_modified_date,id,year,month)place_of_performance(city,state,zip,country_code)highly_compensated_officers(name,amount)prime_recipient(uei,display_name),subaward_recipient(uei,display_name,duns)awarding_office(*),funding_office(*)
# Default response (shaped automatically)
/api/subawards/
# Select specific fields
/api/subawards/?shape=key,piid,subaward_details(*)
# Recipient and office info
/api/subawards/?shape=key,prime_recipient(uei,display_name),awarding_office(*)
GSA eLibrary Contracts /api/gsa_elibrary_contracts/¶
- Leaves:
uuid,schedule,contract_number,sins,cooperative_purchasing,disaster_recovery_purchasing,file_urls - Expansions:
recipient(uei,display_name)idv(key,award_date)
# Basic fields
/api/gsa_elibrary_contracts/?shape=uuid,schedule,contract_number
# With recipient info
/api/gsa_elibrary_contracts/?shape=uuid,contract_number,recipient(uei,display_name)
Opportunities /api/opportunities/¶
- Leaves:
opportunity_id,latest_notice_id,archive_date,title,description,naics_code,psc_code,response_deadline,first_notice_date,last_notice_date,active,set_aside,award_number,solicitation_number,snippet,sam_url, plus relation id leaves:agency_id,department_id,office_id - Expansions:
attachments(attachment_id,extracted_text,mime_type,name,posted_date,resource_id,type,url)(shorthand:attachments→attachments(*))office(office_code,office_name,agency_code,agency_name,department_code,department_name)(shorthand:office→office(*))agency(*)(shorthand:agency→agency(*))department(*)(shorthand:department→department(*))latest_notice(notice_id,link)(shorthand:latest_notice→latest_notice(*))place_of_performance(street_address,city,state,zip,country)meta(notices_count,attachments_count,notice_type(code,type))set_aside(code,description)notice_history(index,notice_id,latest,title,deleted,posted_date,notice_type_code,solicitation_number,parent_notice_id,related_notice_id)primary_contact(title,full_name,email,phone,fax)secondary_contact(title,full_name,email,phone,fax)
Default response (list, no ?shape=): active,award_number,first_notice_date,last_notice_date,meta(*),naics_code,office(*),opportunity_id,place_of_performance(*),psc_code,response_deadline,sam_url,set_aside,solicitation_number,title
Default response (detail): adds attachments(*), description, notice_history(*), primary_contact(*)
# Expand set_aside to get code + description
/api/opportunities/?shape=opportunity_id,title,set_aside(code,description)
# Office + attachments using bare expand shorthand
/api/opportunities/?shape=opportunity_id,title,office,attachments&limit=1
# Detail with notice history
/api/opportunities/{id}/?shape=opportunity_id,title,notice_history(*)
# Contacts
/api/opportunities/{id}/?shape=opportunity_id,primary_contact(*),secondary_contact(*)
Notices /api/notices/¶
- Leaves:
notice_id,opportunity_id,title,description,naics_code,psc_code,posted_date,response_deadline,last_updated,active,set_aside,sam_url,attachment_count,award_number,solicitation_number - Expansions:
attachments(attachment_id,extracted_text,mime_type,name,posted_date,resource_id,type,url)(shorthand:attachments→attachments(*))address(city,state,zip,country)archive(date,type)place_of_performance(street_address,city,state,zip,country)primary_contact(title,full_name,email,phone,fax)secondary_contact(title,full_name,email,phone,fax)meta(parent_notice_id,related_notice_id,notice_type(code,type),link)office(office_code,office_name,agency_code,agency_name,department_code,department_name)(shorthand:office→office(*))opportunity(opportunity_id,link)(shorthand:opportunity→opportunity(*))set_aside(code,description)
Default response (list, no ?shape=): active,address(*),attachment_count,award_number,description,last_updated,meta(*),naics_code,notice_id,office(*),opportunity(*),place_of_performance(*),posted_date,psc_code,response_deadline,sam_url,set_aside,solicitation_number,title
Default response (detail): adds archive(*), primary_contact(*), secondary_contact(*)
# Expand set_aside to get code + description
/api/notices/?shape=notice_id,title,set_aside(code,description)
# Include archive and contacts on detail
/api/notices/{id}/?shape=notice_id,title,archive(*),primary_contact(*)
# Get linked opportunity reference
/api/notices/?shape=notice_id,opportunity(opportunity_id,link)
Entities /api/entities/¶
Entities default to the shaping pipeline. Default responses include core identity fields (list) or the full detail set (retrieve) with normalized field formats. Use ?shape= to customize.
- Leaves:
uei,uuid,display_name,legal_business_name,dba_name,cage_code,dodaac,registered,registration_status,primary_naics,psc_codes,email_address,entity_url,description,capabilities,keywords,sam_activation_date,sam_registration_date,sam_expiration_date,last_update_date,congressional_district,evs_source,uei_status,uei_expiration_date,uei_creation_date,public_display_flag,exclusion_status_flag,exclusion_url,entity_division_name,entity_division_number,entity_start_date,fiscal_year_end_close_date,submission_date - Expansions:
physical_address(address_line1,address_line2,city,state_or_province_code,zip_code,zip_code_plus4,country_code,country_name)— normalized snake_case keysmailing_address(...)— same fields asphysical_addressbusiness_types(code,description)— normalized[{code, description}]; auto-normalizes dict-format DSBS datasba_business_types(code,description,entry_date,exit_date)— normalized SBA certificationsnaics_codes(code,sba_small_business)— normalized; converts plain string arrays automaticallyfederal_obligations(total,active)— expand-only;totalandactivesub-objects with obligation metricshighest_owner(cage_code,legal_business_name,uei)— highest corporate ownerimmediate_owner(cage_code,legal_business_name,uei)— immediate parent entityrelationships(relation,type,uei,display_name)entity_structure(code,description)— falls back to ENTITY_STRUCTURE_MAP for descriptionentity_type(code,description)— falls back to BUSINESS_TYPE_MAP for descriptionprofit_structure(code,description)— falls back to BUSINESS_TYPE_MAP for descriptionorganization_structure(code,description)— falls back to BUSINESS_TYPE_MAP for descriptionstate_of_incorporation(code,description)— uses model descriptioncountry_of_incorporation(code,description)— falls back to django-genc (GENC country names)purpose_of_registration(code,description)— falls back to PURPOSE_OF_REGISTRATION_MAP for descriptionpast_performance[top=N](summary,top_agencies)— aggregated contract history;summaryhastotal_obligated,total_awards,agency_count,naics_count,psc_count;top_agencieslists top N agencies (default 5, max 100) withagency_code,agency_name,department_code,department_name,obligations,awards_count,top_naics,top_psc. Accepts bracket param[top=N].
# List with default shape (core identity fields)
/api/entities/
# Detail with all fields + normalized expands
/api/entities/ZQGGHJH74DW7/
# Custom shape: just UEI and business types
/api/entities/?shape=uei,business_types(code,description)
# Federal obligations for a specific entity
/api/entities/ZQGGHJH74DW7/?shape=uei,federal_obligations(total)
# Structured code/description fields
/api/entities/ZQGGHJH74DW7/?shape=uei,entity_structure(*),purpose_of_registration(*)
# Owner info
/api/entities/ZQGGHJH74DW7/?shape=uei,highest_owner(*),immediate_owner(*)
# Past performance (default top 5 agencies)
/api/entities/ZQGGHJH74DW7/?shape=uei,past_performance(*)
# Past performance with top 10 agencies
/api/entities/ZQGGHJH74DW7/?shape=uei,past_performance[top=10](summary,top_agencies)
Forecasts /api/forecasts/¶
- Leaves:
id,source_system,external_id,agency,title,description,anticipated_award_date,fiscal_year,naics_code,is_active,status,created,modified,primary_contact,place_of_performance,estimated_period,set_aside,contract_vehicle,raw_data - Expansions:
display(title,description,agency,anticipated_award_date,fiscal_year,naics_code,status,primary_contact,place_of_performance,estimated_period,set_aside,contract_vehicle)— normalized view of the forecast's display dataraw_data(*)— the raw JSON data from the source system; accepts wildcard fields
# Basic forecast fields
/api/forecasts/?shape=id,title,agency,anticipated_award_date,status
# With display expansion for normalized view
/api/forecasts/?shape=id,title,display(agency,anticipated_award_date,primary_contact,place_of_performance)
# Include raw source data
/api/forecasts/?shape=id,title,raw_data(*)
Grants /api/grants/¶
- Leaves:
agency_code,applicant_eligibility_description,description,forecast,funding_activity_category_description,grant_id,grantor_contact,last_updated,opportunity_history,opportunity_number,status,synopsis,title - Expansions:
cfda_numbers(number,title)— associated CFDA/Assistance Listing numbersapplicant_types(code,description)category(code,description)— opportunity categoryfunding_categories(code,description)funding_instruments(code,description)status(code,description)— expanded status with code and label (use this when you want the structured form;statusalone is treated as a leaf unless the runtime must expand it for safety)important_dates(posted_date,response_date,response_date_description,estimated_synopsis_post_date,estimated_application_response_date,estimated_application_response_date_description,estimated_project_start_date)— key dates (fields vary by status: posted opportunities returnposted_date/response_date; forecasted ones returnestimated_*fields)funding_details(award_ceiling,award_floor,estimated_total_funding,expected_number_of_awards)grantor_contact(name,phone,email)additional_info(link,description)attachments(mime_type,name,posted_date,resource_id,type,url)
# Basic grant fields
/api/grants/?shape=grant_id,title,status,agency_code
# With CFDA numbers and applicant types
/api/grants/?shape=grant_id,title,cfda_numbers(number,title),applicant_types(code,description)
# Expanded status and funding instruments
/api/grants/?shape=grant_id,title,status(code,description),funding_instruments(code,description)
Protests /api/protests/¶
Both list and detail return case-level objects identified by case_id. Dockets are available via the dockets(...) expansion.
- Leaves:
case_id,source_system,case_number,title,protester,agency,solicitation_number,case_type,outcome,filed_date,posted_date,decision_date,due_date,docket_url,decision_url,digest - Expansions:
dockets(source_system,case_number,docket_number,title,protester,agency,solicitation_number,case_type,outcome,filed_date,posted_date,decision_date,due_date,docket_url,decision_url,digest)
Default response (no ?shape=): case_id,source_system,case_number,title,protester,agency,solicitation_number,case_type,outcome,filed_date,posted_date,decision_date,due_date,docket_url,decision_url (no nested dockets)
Notes:
case_numberis the base B-number (e.g.b-424214) identifying the case.docket_number(e.g.b-424214.1) identifies a specific sub-docket; only available insidedockets(...).digestis opt-in only (decision summary text fromraw_data).
# Case-level fields with nested dockets
/api/protests/?shape=case_id,case_number,title,dockets(docket_number,filed_date,outcome)
# Case-level only
/api/protests/?shape=case_id,title,outcome,decision_date
# Detail with dockets
/api/protests/{case_id}/?shape=case_id,title,dockets(docket_number,filed_date)