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

  • 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/
  • IT Dashboard: /api/itdashboard/
  • 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 of recipient
  • Aliasing: field::alias or child(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:

/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/expands, malformed shapes, or shape on 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:

[
  {
    "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.
  • Malformed shapes (syntax errors) return a 400 with a parse_error issue.
  • Passing shape to an endpoint that does not support shaping returns a 400 (instead of ignoring shape).
  • Default limits (subject to change):
  • SHAPE_MAX_DEPTH = 2
  • SHAPE_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:

/api/contracts/?show_shapes=true
{
  "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:

/api/contracts/?shape=key,piid&show_shapes=true
{
  "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=true alone) makes no DB queries — safe to call frequently.
  • _shaping is appended after results in 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_fields at the top level (no ?show_shapes needed).

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.

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 aliases office_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

# Select a single field
/api/business_types/?shape=name

NAICS /api/naics/

  • Leaves: code, description
  • Expansions:
  • size_standards(employee_limit,revenue_limit) — SBA size standards for this NAICS code. revenue_limit is in whole dollars (e.g., 2250000).
  • federal_obligations(total,active) — obligation rollups. Each sub-object contains awards_obligated (float) and awards_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 description
  • historical(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.

# Select a subset of fields
/api/mas_sins/?shape=sin,title,description

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_key through l8_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) – returns null if no officers are on record. Not included in default serializers; available only via shaping.
  • vehicle(uuid,solicitation_identifier,solicitation_title,solicitation_description,agency_id,vehicle_type,type_of_idc,contract_type,who_can_use,solicitation_date,award_date,last_date_to_order,fiscal_year,naics_code,psc_code,set_aside,description) — the contract's parent vehicle, resolved through its parent IDV. Returns null when the contract has no parent IDV, or when the parent IDV is not part of any vehicle. For richer vehicle detail (awardees, opportunity, totals), follow the returned uuid to /api/vehicles/{uuid}/. Shaping-only.

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(*)

# Parent vehicle (uuid + label)
/api/contracts/?shape=key,piid,vehicle(uuid,solicitation_title)

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: uses last_date_to_order instead of contracts' current_end_date/ultimate_completion_date
  • transactions(modification_number,transaction_date,obligated,description,action_type)
  • subawards_summary(count,total_amount)
  • idv_type(code,description) — IDV type as structured code/description
  • multiple_or_single_award_idv(code,description) — single/multiple award designation
  • type_of_idc(code,description) — IDC type as structured code/description
  • set_aside(code,description) — set-aside type
  • naics(code,description) — resolved NAICS lookup
  • psc(code,description) — resolved PSC lookup
  • competition(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; null when absent; shaping-only
  • awards(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 IDV
  • gsa_elibrary(schedule,contract_number,uei,sins,cooperative_purchasing,disaster_recovery_purchasing,file_urls,extracted_text,external_id,source_data) — GSA eLibrary enrichment (null when 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 vehicle
  • opportunity(...): expands to the linked SAM.gov Opportunity (supports all Opportunity fields and expansions like office, attachments, meta)
  • competition_details(...): expands the competition_details JSON 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 expanded awardees(...) (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, 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(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: attachmentsattachments(*))
  • office(office_code,office_name,agency_code,agency_name,department_code,department_name) (shorthand: officeoffice(*))
  • agency(*) (shorthand: agencyagency(*))
  • department(*) (shorthand: departmentdepartment(*))
  • latest_notice(notice_id,link) (shorthand: latest_noticelatest_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: attachmentsattachments(*))
  • 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: officeoffice(*))
  • opportunity(opportunity_id,link) (shorthand: opportunityopportunity(*))
  • 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 keys
  • mailing_address(...) — same fields as physical_address
  • business_types(code,description) — normalized [{code, description}]; auto-normalizes dict-format DSBS data
  • sba_business_types(code,description,entry_date,exit_date) — normalized SBA certifications
  • naics_codes(code,sba_small_business) — normalized; converts plain string arrays automatically
  • federal_obligations(total,active) — expand-only; total and active sub-objects with obligation metrics
  • highest_owner(cage_code,legal_business_name,uei) — highest corporate owner
  • immediate_owner(cage_code,legal_business_name,uei) — immediate parent entity
  • relationships(relation,type,uei,display_name)
  • entity_structure(code,description) — falls back to ENTITY_STRUCTURE_MAP for description
  • entity_type(code,description) — falls back to BUSINESS_TYPE_MAP for description
  • profit_structure(code,description) — falls back to BUSINESS_TYPE_MAP for description
  • organization_structure(code,description) — falls back to BUSINESS_TYPE_MAP for description
  • state_of_incorporation(code,description) — uses model description
  • country_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 description
  • past_performance[top=N](summary,top_agencies) — aggregated contract history; summary has total_obligated, total_awards, agency_count, naics_count, psc_count; top_agencies lists top N agencies (default 5, max 100) with agency_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 data
  • raw_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 numbers
  • applicant_types(code,description)
  • category(code,description) — opportunity category
  • funding_categories(code,description)
  • funding_instruments(code,description)
  • status(code,description) — expanded status with code and label (use this when you want the structured form; status alone 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 return posted_date/response_date; forecasted ones return estimated_* 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)

IT Dashboard /api/itdashboard/

IT Dashboard exposes tiered shaping: Free gets basic investment metadata, Micro+ adds the funding and details expansions, and Medium+ adds nested sub-tables (contracts, projects, CIO evaluations, performance metrics, etc.) plus the business_case_html leaf. Fields or expansions above the caller's tier are silently stripped from the response, and removed nodes are listed in meta.upgrade_hints. For the full tier/field matrix, see the IT Dashboard API Reference.

  • Leaves (all tiers): uii, agency_code, agency_name, bureau_code, bureau_name, investment_title, type_of_investment, part_of_it_portfolio, updated_time, url
  • Medium+ leaf: business_case_html
  • Expansions (Micro+):
  • funding(*) — fiscal-year internal funding and contributions (FY2020–FY2025)
  • details(*) — extended metadata: description, previous/current UII, classification, business case URL, public URLs
  • Expansions (Medium+): cio_evaluation(*), contracts(*), projects(*), cost_pools_towers(*), funding_sources(*), performance_metrics(*), performance_actual(*), operational_analysis(*)

Default response (no ?shape=):

  • List: uii,agency_name,bureau_name,investment_title,type_of_investment,part_of_it_portfolio,updated_time,url
  • Detail: adds agency_code,bureau_code
# Free tier: basic metadata
/api/itdashboard/?shape=uii,investment_title,agency_name,url

# Micro+ tier: funding and details
/api/itdashboard/?shape=uii,investment_title,funding(*),details(*)

# Medium+ tier: nested sub-tables + business case HTML
/api/itdashboard/{uii}/?shape=uii,investment_title,cio_evaluation(*),performance_metrics(*),business_case_html

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_number is 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 inside dockets(...).
  • digest is opt-in only (decision summary text from raw_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)