Skip to content

Changelog

This is the most up-to-date change log for Tango and the Tango API.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Production Badge

[Unreleased]

[4.2.0] - 2026-04-30

Added

  • G2X integration (#1881): new /api/news/ and /api/events/ endpoints (G2X User group required), a /api/company/rag/ endpoint for unified company/people/news lookups, and g2x_about / g2x_ai_summary / g2x_employee_count fields available via ?shape= on /api/entities/ when a linked G2X profile exists
  • eBuy opportunities now available on /api/opportunities/ via ?domain=ebuy (eBuy only) or ?domain=sam,ebuy (union with SAM). eBuy results are served live from the G2X GraphQL API — no stored snapshot; filter by request_type, contract_type, set_aside_type, buyer_department, closes_after, or search. On upstream outage, ?domain=sam,ebuy degrades to SAM-only with an upstream_warnings field so SAM queries stay up
  • vehicle is now available as a shape expand on /api/contracts/. Use ?shape=vehicle(uuid,solicitation_title) to attach the contract's parent vehicle to each result, or ?shape=vehicle(*) for the curated field set (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). Contracts without a parent IDV — or whose parent IDV is not part of any vehicle — return null. For richer vehicle detail (awardees, opportunity, totals), follow the returned uuid to /api/vehicles/{uuid}/. Resolution adds one query per page, not per row.

Changed

Breaking

Fixed

[4.1.1] - 2026-04-27

Added

  • cage is now an alias for cage_code across the API. Query entities with ?cage= or ?cage_code= (sending both is rejected — pick one). Award recipient shapes accept either key: recipient(cage) returns cage, recipient(cage_code) returns cage_code, and recipient(*) returns cage_code only. If you want the short cage key, ask for it explicitly (refs #1350).

Fixed

  • Filtering subawards by ?awarding_agency=<name|code> or ?funding_agency=<name|code> now uses the same hierarchical resolution as the contracts and opportunities endpoints. Department queries (e.g. ?awarding_agency=DOE, ?awarding_agency=089) return all subawards under that department's subtree; agency codes (e.g. ?awarding_agency=8900 for DOE, ?awarding_agency=7530 for CMS) return that agency's subtree; abbreviations (e.g. ?awarding_agency=CMS) resolve via the canonical alias table. Result counts will shift compared to the previous literal-code-match behavior — most notably, name-based queries that previously returned 0 (e.g. ?awarding_agency=CMS) now return the full agency subtree, semantically aligned with /api/contracts/?awarding_agency=.... Closes #2076.

[4.1.0] - 2026-04-26

Internal / Infra

  • Awards tables in PostgreSQL are now kept fresh by the tango-etl Polars export pipeline (FPDS, USAspending, SAM), replacing the legacy Spark-based lakehouse export. Three per-source ECS jobs run on a staggered morning schedule (04:00, 05:00, 06:30 ET) followed by the PG sync at 07:30 ET. Both scheduled and poll-triggered fire paths share a per-source singleton lock so duplicate runs are silently skipped. No change to the API surface or query behavior (refs #2082).

[4.0.14] - 2026-04-26

Changed

  • Metrics materialized views (entity totals + time series, NAICS + PSC monthly time series, contract aggregates) are now regular tables populated directly from the tango-etl parquet pipeline, replacing the in-DB REFRESH MATERIALIZED VIEW cascade. The user-facing API surface is unchanged — the same /metrics/ endpoints with ?group_by=agency / ?group_by=department parameters continue to work. Under the hood they now resolve agency and department at query time via a single JOIN to agencies_organization instead of reading denormalized columns, which preserves PostgreSQL's buffer cache during syncs (latency spikes from scheduled MV refreshes should be noticeably smaller).
  • Filtering opportunities or notices by ?agency=<name|code> now uses the same hierarchical resolution as the contracts agency filter. Department queries (e.g. ?agency=DOE, ?agency=089) return the whole department subtree; agency codes (e.g. ?agency=8900 for DOE, ?agency=8960 for FERC) return just that agency's subtree. Result counts will shift compared to the previous full-text-search behavior — the new counts are semantically correct subtree matches rather than token co-occurrence. Closes #2058.

Fixed

  • Forecasts loader: reduced log noise and false Sentry alerts. sanitize_year data-quality events are now DEBUG-level; empty records is a no-op rather than an error; partial validation failures log as warnings (visible in admin, no Sentry alert). Closes #1974, closes #1935.
  • Filtering contracts by awarding_agency or funding_agency using a real (but currently inactive) agency code such as 5706, 8933, or 8944 now returns an HTTP 200 response with the matching contracts, instead of an HTTP 400 "No agency found matching" error. Queries for agency codes that don't exist at all continue to return 400 as before. Closes #2057.
  • Filtering contracts by a numeric agency code (e.g. awarding_agency=8900, funding_agency=8900) now returns the correct subtree of contracts instead of narrowing to a single sub-office. A 4-digit FPDS code resolves to that agency and its descendants; a 3-digit CGAC code resolves to the whole department (matching what awarding_agency=DOE returns). Name queries are unchanged. Closes #2056.
  • Filtering opportunities or notices by a numeric agency code (e.g. ?agency=8900) now resolves to the correct subtree instead of matching agencies whose search index happens to contain that token. Fixes over-broad matches for short numeric queries and makes sibling-agency queries (like DOE 8900 vs FERC 8960 under the same department) correctly distinct. Closes #2058.

[4.0.12] - 2026-04-22

Added

  • The /welcome/ page now displays your active API key(s) with copy-to-clipboard and visibility toggle — no longer need to navigate to your profile to find your key after signing up

Changed

  • The welcome page's API keys card now matches the richer layout used on your profile: full-width card at the top of the page with your daily requests remaining, per-key name + "Active" badge, click-to-copy, show/hide, and created date + rate limits. "Your plan" and "Quick links" now sit side-by-side below it so nothing important is hidden below the fold

[4.0.11] - 2026-04-21

  • No user-facing changes

[4.0.10] - 2026-04-21

  • No user-facing changes

[4.0.9] - 2026-04-20

  • No user-facing changes

[4.0.8] - 2026-04-20

  • No user-facing changes

[4.0.7] - 2026-04-18

  • No user-facing changes

[4.0.6] - 2026-04-17

  • No user-facing changes