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/
  • 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.

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: 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)

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)