Skip to content

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

  • Awards (canonical routes):
    • Contracts: /api/contracts/
    • IDVs: /api/idvs/
    • OTAs: /api/otas/
    • OTIDVs: /api/otidvs/
    • Subawards: /api/subawards/
  • Entities: /api/entities/
  • Forecasts: /api/forecasts/
  • Grants: /api/grants/
  • Opportunities (canonical routes):
    • Opportunities: /api/opportunities/
    • Opportunity Notices: /api/notices/

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 of recipient
  • Aliasing: field::alias or child(field::alias)

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:

/api/contracts/?shape=key,awarding_office(agency_name::foo)

Response:

[
  {
    "key": "CONT_AWD_...",
    "awarding_office": { "foo": "General Services Administration" }
  }
]

Notes:

  • * is only valid inside a child selection (e.g., recipient(*)). Root‑level * is not supported.
  • Shaping requests that include unknown fields or expands 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:

[
  {
    "key": "CONT_AWD_...",
    "recipient.display_name": "ACME CORP"
  }
]

Notes:

  • Flattening applies to nested objects (dicts). Lists remain arrays for readability and stability by default. Expansions like relationships (entities) and attachments (opportunities/notices) will remain arrays of objects even when flat=true.
  • Optional: flat_lists=true will additionally flatten lists of objects into indexed keys (e.g., relationships.0.uei). This is opt‑in and defaults to false.

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
  • Default limits (subject to change):
    • SHAPE_MAX_DEPTH = 2
    • SHAPE_MAX_FIELDS = 64

Example error:

{
  "error": "Invalid shape",
  "issues": [{"path": "foo", "reason": "unknown_field"}]
}

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:

{
  "parent_award": {"key": "PARENT-123"}
}

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.

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) – returns null if 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, award_date, naics_code, psc_code, total_contract_value, description, base_and_exercised_options_value, fiscal_year, obligated, idv_type, multiple_or_single_award_idv, type_of_idc, transactions, subawards_summary
  • Expansions: same pattern as contracts with period_of_performance(start_date,last_date_to_order), awards(*) for child awards list, and officers(...) (same fields as contracts; null when absent; shaping‑only).

OTAs /api/otas/ and OTIDVs /api/otidvs/

  • Leaves: common award leaves plus award_type, type_of_ot_agreement, extent_competed, consortia (OTAs) or idv_type, consortia (OTIDVs)
  • Expansions: recipient, place_of_performance, parent_award (when applicable), awarding_office, funding_office, period_of_performance, transactions

Subawards /api/subawards/

  • Leaves (serializer‑aligned): identity + prime award metadata (piid, prime_award_total_outlayed_amount, dates/NAICS/description, prime/subawardee identities, business types, and usaspending_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(*), subaward_recipient(*)
    • awarding_office(*), funding_office(*)

Opportunities /api/opportunities/

  • Leaves: opportunity_id, title, description, naics_code, psc_code, response_deadline, first_notice_date, last_notice_date, active, set_aside, office, place_of_performance, primary_contact, secondary_contact, meta, sam_url, award_number, solicitation_number
  • Expansions:
    • attachments(attachment_id,mime_type,name,posted_date,resource_id,type,url)
    • office(office_code,office_name,agency_code,agency_name,department_code,department_name)
    • place_of_performance(street_address,city,state,zip,country)
    • meta(notices_count,attachments_count,notice_type(code,type))

Notices /api/notices/

  • Leaves: notice_id, title, description, naics_code, psc_code, posted_date, response_deadline, last_updated, active, address, place_of_performance, psc_code, set_aside, sam_url, attachment_count, office, opportunity, solicitation_number, meta
  • Expansions:
    • attachments(attachment_id,mime_type,name,posted_date,resource_id,type,url)
    • address(city,state,zip,country)
    • place_of_performance(street_address,city,state,zip,country)
    • primary_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)

Entities /api/entities/

  • Leaves: uei, display_name, legal_business_name, dba_name, cage_code, registered, registration_status, purpose_of_registration_code, primary_naics, naics_codes, psc_codes, business_types, sba_business_types, email_address, entity_url, description, capabilities, keywords, sam_activation_date, sam_registration_date, sam_expiration_date, physical_address, mailing_address, federal_obligations, congressional_district, relationships
  • Expansions:
    • physical_address(line1,line2,city,state,zip,country_code,country_name)
    • mailing_address(line1,line2,city,state,zip,country_code,country_name)
    • relationships(relation,type,uei,display_name)