Skip to content

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

shape       := field ("," field)*
field       := name ["::" alias] ["(" fields | "*" ")"]
  • field1,field2 -- select specific top-level fields
  • nested(child1,child2) -- select fields within a nested object
  • nested(*) -- select all fields of a nested object
  • field::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.