Response Shaping¶
Response shaping lets you request only the fields you need, reducing payload sizes by 60-80% and giving you precise control over the response structure.
For full details on the shaping query syntax, see the Response Shaping guide.
Predefined Shapes (ShapeConfig)¶
Every shaped endpoint has a default shape applied automatically. You can also pass any ShapeConfig constant explicitly:
from tango import TangoClient, ShapeConfig
client = TangoClient()
# Uses ShapeConfig.CONTRACTS_MINIMAL by default
resp = client.list_contracts(limit=10)
# Or specify a shape explicitly
resp = client.list_contracts(limit=10, shape=ShapeConfig.CONTRACTS_MINIMAL)
Available Shape Constants¶
| Constant | Fields | Used by |
|---|---|---|
CONTRACTS_MINIMAL | key, piid, award_date, recipient(display_name), description, total_contract_value | list_contracts() |
ENTITIES_MINIMAL | uei, legal_business_name, cage_code, business_types | list_entities() |
ENTITIES_COMPREHENSIVE | All core fields + naics_codes, psc_codes, address, federal_obligations(*), etc. | get_entity() |
FORECASTS_MINIMAL | id, title, anticipated_award_date, fiscal_year, naics_code, status | list_forecasts() |
OPPORTUNITIES_MINIMAL | opportunity_id, title, solicitation_number, response_deadline, active | list_opportunities() |
NOTICES_MINIMAL | notice_id, title, solicitation_number, posted_date | list_notices() |
PROTESTS_MINIMAL | case_id, case_number, title, source_system, outcome, filed_date | list_protests() |
GRANTS_MINIMAL | grant_id, opportunity_number, title, status(*), agency_code | list_grants() |
IDVS_MINIMAL | key, piid, award_date, recipient(display_name,uei), description, total_contract_value, obligated, idv_type | list_idvs() |
IDVS_COMPREHENSIVE | All core fields + competition, transactions, etc. | get_idv() |
OTAS_MINIMAL | key, piid, award_date, recipient(display_name,uei), description, total_contract_value, obligated | list_otas() |
OTIDVS_MINIMAL | key, piid, award_date, recipient(display_name,uei), description, total_contract_value, obligated, idv_type | list_otidvs() |
SUBAWARDS_MINIMAL | award_key, prime_recipient(uei,display_name), subaward_recipient(uei,display_name) | list_subawards() |
VEHICLES_MINIMAL | uuid, solicitation_identifier, organization_id, awardee_count, order_count, etc. | list_vehicles() |
VEHICLES_COMPREHENSIVE | All core fields + competition_details, etc. | get_vehicle() |
VEHICLE_AWARDEES_MINIMAL | uuid, key, piid, award_date, title, order_count, recipient(display_name,uei), etc. | list_vehicle_awardees() |
ORGANIZATIONS_MINIMAL | key, fh_key, name, level, type, short_name | list_organizations() |
GSA_ELIBRARY_CONTRACTS_MINIMAL | uuid, contract_number, schedule, recipient(display_name,uei), idv(key,award_date) | list_gsa_elibrary_contracts() |
ITDASHBOARD_INVESTMENTS_MINIMAL | uii, agency_name, bureau_name, investment_title, type_of_investment, etc. | list_itdashboard_investments() |
ITDASHBOARD_INVESTMENTS_COMPREHENSIVE | Adds agency_code, bureau_code | get_itdashboard_investment() |
Custom Shapes¶
Pass a shape string to request exactly the fields you want:
# Simple field selection
resp = client.list_contracts(
shape="key,piid,award_date,obligated",
limit=10,
)
# Nested field selection
resp = client.list_contracts(
shape="key,piid,recipient(display_name,uei),awarding_office(name)",
limit=10,
)
# Wildcard -- all fields of a nested object
resp = client.list_contracts(
shape="key,piid,recipient(*)",
limit=10,
)
# Field aliasing
resp = client.list_contracts(
shape="key,piid,recipient(display_name::vendor_name,uei)",
limit=10,
)
for c in resp.results:
print(c.recipient.vendor_name) # aliased field
Shape String Syntax¶
field1,field2-- select specific top-level fieldsnested(child1,child2)-- select fields within a nested objectnested(*)-- select all fields of a nested objectfield::alias-- rename a field in the response
Accessing Shaped Results¶
Shaped responses return ShapedModel objects that support both dictionary and attribute access:
resp = client.list_contracts(
shape="key,piid,recipient(display_name,uei)",
limit=5,
)
for contract in resp.results:
# Dictionary access
print(contract["piid"])
print(contract["recipient"]["display_name"])
# Attribute access
print(contract.piid)
print(contract.recipient.display_name)
Accessing a field that wasn't included in the shape raises AttributeError with a helpful message suggesting available fields.
Flattening¶
Use flat=True to flatten nested objects into dot-notation keys:
resp = client.list_contracts(
shape="key,piid,recipient(display_name,uei)",
flat=True,
limit=5,
)
for c in resp.results:
print(c["recipient.display_name"])
Use flat_lists=True to also flatten arrays with indexed keys (e.g., naics_codes.0.code).
IDV, OTA, OTIDV, vehicle, GSA eLibrary, IT Dashboard, and organization endpoints also accept a joiner parameter (default ".") to control the separator used when flattening.