Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
[1.0.0] - 2026-05-13¶
First stable release.
tango-pythonis now at full API parity with the Tango HTTP surface, the legacy subject-based webhook subscription mechanism has been removed in favor of filter alerts, the shape parser agrees byte-for-byte with the server's expand-alias handling, and the SDK's docs are auto-published todocs.makegov.com/sdks/python/via the composer pipeline (makegov/docs#15 / makegov/docs#16). From1.xon, we'll only do breaking changes on a major bump.Originally tracked as: API parity (PR #25), subject-based webhook removal (PR #27 / issue #2275), shape-validator alias support (PR #28 / issue #2266), and the docs-only content port (makegov/docs#16).
Added¶
orderingparameter onlist_forecasts,list_grants,list_subawards,list_gsa_elibrary_contracts, andlist_opportunities. Prefix with-for descending. Closes a parity gap with the API surface (these endpoints all accept?ordering=server-side).create_webhook_endpointacceptsname=(keyword-only) and now requires it. The Tango API enforces unique(user, name)on endpoints; omittingnamereturns a 400 server-side, so the SDK raisesTangoValidationErrorclient-side instead of round-tripping. (0.7.0 — never publicly released — emitted aDeprecationWarninginstead.)update_webhook_endpointacceptsname=for renaming an endpoint.- Webhook alerts (filter subscriptions):
list_webhook_alerts,get_webhook_alert,create_webhook_alert,update_webhook_alert,delete_webhook_alert— the canonical write surface over/api/webhooks/alerts/. NewWebhookAlertdataclass exported from the top-level package. resolve(name, target_type, ...)— POST/api/resolve/to rank entity / organization candidates from a free-text name. ReturnsResolveResultwithResolveCandidateentries (both exported).validate(identifier_type, value)— POST/api/validate/to validate the format of a PIID, solicitation number, or UEI. ReturnsValidateResult(exported).- Reference data:
list_departments,get_department,list_psc,get_psc,get_psc_metrics,get_naics,get_naics_metrics,get_business_type,list_assistance_listings,get_assistance_listing,list_mas_sins,get_mas_sin. - Entity sub-resources:
list_entity_contracts,list_entity_idvs,list_entity_otas,list_entity_otidvs,list_entity_subawards,list_entity_lcats,get_entity_metrics. All shape-aware where the underlying endpoint supports shaping. - IDV sub-resources:
list_idv_lcats. - Agency sub-resources:
list_agency_awarding_contracts,list_agency_funding_contracts. - Misc:
search_opportunity_attachments(q, top_k, include_extracted_text)for/api/opportunities/attachment-search/;get_version()for/api/version/;list_api_keys()for/api/api-keys/.
Changed¶
create_webhook_alertacceptsendpoint=(keyword-only). Required for accounts with multiple webhook endpoints; auto-resolves for single-endpoint accounts. Closes the multi-endpoint smoke-test gap (tango#2256).test_webhook_deliverynow sends the canonicalendpointbody key instead of the deprecatedendpoint_idalias (tango#2252). The Python kwarg name staysendpoint_id=for backwards compatibility; the wire payload is what changed.generate_signature(body, secret)now returns the full wire form"sha256=<hex>"instead of bare hex. Callers can assign the return value directly to theX-Tango-Signatureheader without wrapping in a format string. This is a breaking change for code that relied on the bare-hex return; pass it throughparse_signature_header()to recover the previous form.verify_signatureaccepts both prefixed and bare-hex inputs (unchanged), so receivers continue to work either way.
Removed¶
- Subject-based webhook subscription surface (tango#2275). Migrate to
create_webhook_alert(...)and the alerts API.- Methods:
list_webhook_subscriptions,get_webhook_subscription,create_webhook_subscription,update_webhook_subscription,delete_webhook_subscription. - Dataclasses:
WebhookSubscription,WebhookSubjectTypeDefinition. Both are no longer exported from the top-leveltangopackage — importing them raisesImportError. - Fields:
default_subject_typeremoved fromWebhookEventType;subject_typesandsubject_type_definitionsremoved fromWebhookEventTypesResponse. The server's/api/webhooks/event-types/response no longer carries these. - CLI: the entire
tango webhooks subscriptionsClick subgroup (list/get/create/delete). Use the SDK'sclient.create_webhook_alert(...)etc. directly — there is no CLI subgroup for alerts.
- Methods:
orderingkwarg fromlist_noticesandlist_protests. The notices and protests viewsets reject every?ordering=value at runtime (tango#2254); the kwarg silently sent unsupported values. Other five list methods retainordering.
Fixed¶
TangoClient._post()and_patch()accept bothjson_data=(positional) andjson=(keyword) for backward compatibility. Internal callers and docs examples that usejson=no longer fail withTypeError. Passing both now raisesTangoValidationErrorrather than silently preferring one — that ambiguity would hide caller bugs.get_psc_metrics/get_naics_metrics/get_entity_metricsdocstrings —period_groupingvalues are"month"/"quarter"/"year"(the path-segment values the API accepts), not"monthly"/"quarterly".docs/API_REFERENCE.md#get_agency— example usesclient.get_agency("GSA")consistently and notes the parameter accepts CGAC / FPDS / short code / abbreviation / canonical name.README.mdQuick Start —get_agency()returns anAgencydataclass, so the example uses attribute access (agency.name) instead ofagency['name']which wouldTypeError.scripts/smoke_api_parity.py—list_business_types(limit=1)is now wrapped in therun(...)helper so a failure on that call records FAIL instead of aborting the smoke run.tango webhooks endpoints createCLI now accepts and requires--name(passed through tocreate_webhook_endpoint(name=...)). Previously the option was absent, meaning the CLI could never set a custom endpoint name and every call would 400 server-side (the server enforcesunique(user, name)).WebhookAlert.query_typeandWebhookAlert.filterstightened fromOptionalto non-optional (stranddict[str, Any]respectively). Legacy nullable rows were purged by the tango#2275 migration; the server model and serializer guarantee non-null values for all current data.WebhookAlert.statusnarrowed fromstrtoLiteral["active", "paused"]— the server serializer produces exactly those two values.- Shape validator agrees with server on
naics(...)/psc(...)expansions. The client-sideShapeParser.validate()previously rejected the canonicalshape=naics(code,description)form (which the server has always accepted) and also rejected the aliasshape=naics_code(code,description). The parser now mirrors the server's_EXPAND_ALIASES(introduced in Tango PR makegov/tango#2259) and rewritesnaics_code(...)/psc_code(...)to their canonicalnaics(...)/psc(...)form at parse time. Bare scalar leaves (shape=naics_code/shape=psc_code) are left untouched and still return the raw column value, matching the server. Schemas forContract,Forecast,Opportunity,Notice, andVehiclegained explicitnaics/pscexpand entries backed by the existingCodeDescriptionnested model. Fixes makegov/tango#2266. Subawardschema matches the server'sSubawardSerializer. The previousSUBAWARD_SCHEMAdeclared two fields the server has never exposed (id,amount) and was missing every real field on the resource — includingpiid,key,awarding_office/funding_office/place_of_performance/subaward_details/fsrs_details/highly_compensated_officers/usaspending_permalink, and the denormalizedprime_awardee_*/recipient_*lookup columns. Shape strings that referenced any real field (e.g.shape="piid") would fail client-side validation withunknown_field, and conversely the SDK happily passedshape="id"/shape="amount"through to the server, where they were rejected.SUBAWARD_SCHEMAis now derived directly fromawards.serializers.subawards.SubawardSerializerand the resource's runtimeavailable_fields. TheSubawarddataclass intango/models.pywas updated to match. New nested schemasSubawardDetails,FsrsDetails,SubawardPlaceOfPerformance, andHighlyCompensatedOfficerare registered so the corresponding shape expansions validate end-to-end.
Documentation¶
- New
docs/ERRORS.md— full exception hierarchy, recovery patterns, and the shape-error classes (ShapeValidationError,ShapeParseError,TypeGenerationError,ModelInstantiationError). Ported fromdocs.makegov.com/sdks/python/errors.mdahead of the docs-site auto-pull cutover (makegov/docs#15 / makegov/docs#16). - New
docs/PAGINATION.md— page-based vs cursor-based strategies, iteration patterns, and thePaginatedResponsefield reference. Ported fromdocs.makegov.com/sdks/python/pagination.md. - New
docs/CLIENT.md—TangoClientconstructor reference,rate_limit_info/last_response_headersproperties, and retry-semantics note (the SDK has no built-in retry). Ported fromdocs.makegov.com/sdks/python/client.md.
CI¶
- New
.github/workflows/docs-dispatch.yml— fires on push tomainwhendocs/**,README.md, orCHANGELOG.mdchanges and dispatchesexternal_updatedatmakegov/docsso the public docs site rebuilds with the latest SDK content. Required for the makegov/docs#15 auto-pull pipeline.
[0.6.0] - 2026-05-07¶
Added¶
- Vehicles: new top-level fields
program_acronym,idv_count,total_obligated,is_synthetic_solicitation,latest_award_date,description,opportunity_id. - Vehicles: new
metrics(*)shape expansion bundling 12 computed metrics:avg_offers_received,award_concentration_hhi,order_concentration_hhi,competed_rate,using_agency_count,avg_order_value,max_order_value,top_recipient_share,recent_obligations_24mo,recent_orders_24mo,days_since_last_order,obligation_to_ceiling_ratio. Backed by a newVehicleMetricsschema. list_vehicle_orders(uuid, ...)for the new/api/vehicles/{uuid}/orders/endpoint, returning task orders under the vehicle's IDVs with two-phase pagination.list_vehiclesgained 21 explicit filter parameters per API 4.3.0:vehicle_type,type_of_idc,contract_type,set_aside(multi-value via|),who_can_use,naics_code,psc_code,program_acronym,agency,organization_id,total_obligated_min/max,idv_count_min/max,order_count_min/max,fiscal_year,award_date_after/before,last_date_to_order_after/before.list_vehicle_awardeesgained asearchparameter for entity-aware full-text search across IDV fields and recipient entity details (API 4.3.0).orderingparameter onlist_vehicles(whitelist:vehicle_obligations,latest_award_date,total_obligated,award_date,last_date_to_order,fiscal_year,idv_count,order_count) and onlist_vehicle_orders(whitelist:award_date,obligated,total_contract_value). Prefix with-for descending.ShapeConfig.VEHICLE_ORDERS_MINIMALdefault for the new orders endpoint.- Shaping: New
organization(*)expand onVehicle,Forecast,Grant,ITDashboardInvestment, andProtestschemas — returns the canonical 7-key office payload (organization_id,office_code,office_name,agency_code,agency_name,department_code,department_name). Selectable as the bare leaf (shape=...,organization) or as a sub-selectable expansion (shape=...,organization(office_code,...)). - Shaping: New
vehicle(*)expand onContract— request the parent vehicle inline from/api/contracts/(API 4.2.0). VehicleandVehicleMetricsare now exported from the top-leveltangopackage.tango.webhookssubpackage with HMAC-SHA256 signing helpers (verify_signature,generate_signature,parse_signature_header) that mirror the canonical Tango server scheme byte-for-byte. Importable from a defaultpip install tango-python(pure stdlib).WebhookReceiver: a stdlib-based local HTTP listener for development and integration tests. Verifies signatures, optionally forwards each delivery to a downstream URL, and records deliveries in memory for inspection. Usable as a context manager (with WebhookReceiver(secret=...).run() as rx: ...).tango.webhooks.simulate.deliver(...): locally sign and POST a payload to any URL — no Tango involvement. Useful for offline iteration on receiver code.- New
tango[webhooks]extra (addsclick) ships atangoconsole script covering the full webhook lifecycle for developer integrations:listen— local receiversimulate— sign a payload locally; with--to, also POST ittrigger— ask Tango to send a real test deliveryfetch-sample— print the canonical payload Tango emits for an event typelist-event-types— discover what's subscribableendpoints list|get|create|delete— manage delivery endpointssubscriptions list|get|create|delete— manage what events you receive Together these let a developer go from zero to receiving real Tango webhooks without leaving the shell or dropping into Python.
Changed¶
ShapeConfig.VEHICLES_MINIMALandVEHICLES_COMPREHENSIVEnow include the new top-level fields and theorganizationexpansion.VEHICLES_COMPREHENSIVEdefaults tometrics(*)and no longer pulls the deprecatedcompetition_details(*)blob.
Deprecated¶
- Vehicles shape fields
agency_details,competition_details, and theopportunityexpansion. The upstream API now sends aDeprecation: trueheader for these and recomputes them at request time. Explicit use inshape=...emits a PythonDeprecationWarning. Sunset timeline TBD upstream.
Notes¶
- Console script name
tangomay be revisited in a future release if it conflicts with sibling tooling (tango-scriptsreuses the bare name).
Documentation¶
- New
docs/WEBHOOKS.md— comprehensive guide covering install, concepts, a zero-to-receiving quickstart, full CLI reference, and programmatic patterns forWebhookReceiver/simulate.sign/simulate.deliverin pytest fixtures. docs/API_REFERENCE.md: filled inget_webhook_subscription, replaced the hand-rolled signature-verification snippet with a pointer totango.webhooks.verify_signature, and added a new "Webhook tooling (tango.webhooks)" section that documents every importable from the new subpackage.README.md: new "Webhook Tooling" section under Advanced Features, plus the new guide is linked from the Documentation index.
[0.5.0] - 2026-04-08¶
Added¶
- IT Dashboard investments:
list_itdashboard_investments,get_itdashboard_investment(/api/itdashboard/) with shaping and filter params (search,agency_code,agency_name,type_of_investment,updated_time_after,updated_time_before,cio_rating,cio_rating_max,performance_risk). Tier-gated by the API: free tier getssearch, pro adds structured filters, business+ adds CIO/performance analytics. NewITDashboardInvestmentmodel andShapeConfig.ITDASHBOARD_INVESTMENTS_MINIMAL/ITDASHBOARD_INVESTMENTS_COMPREHENSIVEdefaults.
[0.4.4] - 2026-03-25¶
Added¶
parent_piidfilter parameter onlist_contractsfor filtering orders under a specific parent IDV PIID.user_agentandextra_headersparameters onTangoClientfor custom request headers.TangoClient.last_response_headersproperty for accessing full HTTP headers from the most recent API response.
[0.4.3] - 2026-03-21¶
Added¶
TangoRateLimitErrornow exposeswait_in_seconds,detail, andlimit_typeproperties parsed from the API's 429 response body.RateLimitInfodataclass for structured access to rate limit headers (X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset, and per-window daily/burst variants).TangoClient.rate_limit_infoproperty returns rate limit info from the most recent API response.
Changed¶
_requestnow passes the full 429 response body toTangoRateLimitError(previously discarded), enabling callers to accesswait_in_secondsand the specific limit type that was exceeded.
[0.4.2] - 2026-03-04¶
Added¶
- Protests endpoints:
list_protests,get_protestwith shaping and filter params (source_system,outcome,case_type,agency,case_number,solicitation_number,protester,filed_date_after,filed_date_before,decision_date_after,decision_date_before,search).
Changed¶
- Lint CI workflow disabled for push/PR (runs only on manual trigger) until the private
makegov/tangorepo is accessible to the workflow. - Updated documents to reflect changes since v0.4.0
- Entities:
ENTITIES_COMPREHENSIVEnow usesfederal_obligations(*)expansion; the API treats federal obligations as an expansion rather than a plain shape field. - Docs:
SHAPES.mddocumentsfederal_obligations(*)as an expansion for entity shaping. - Integration tests:
test_parsing_nested_objects_with_missing_dataaccepts award office fields (office_code,agency_code,department_code) and empty nested objects when the API returns partial data.
Removed¶
- Assistance:
list_assistanceendpoint and all related tests, docs, and references. - IDV summaries:
get_idv_summaryandlist_idv_summary_awardsendpoints and related integration tests, cassettes, and API reference section.
[0.4.1] - 2026-03-03¶
Added¶
- GSA eLibrary contracts:
list_gsa_elibrary_contracts,get_gsa_elibrary_contractwith shaping and filter params (contract_number,key,piid,schedule,search,sin,uei).
Changed¶
- Conformance: replaced
**kwargs/**filterswith explicit filter parameters onlist_contracts,list_idvs,list_entities,list_forecasts,list_grants,list_notices,list_opportunitiesfor full filter/shape conformance. Backward compatibility preserved forlist_contracts(filters=SearchFilters(...)).
[0.4.0] - 2026-02-24¶
Added¶
- Offices, Organizations, OTAs, OTIDVs, Subawards, NAICS, and Assistance endpoints.
- Filter/shape conformance tooling and documentation.
Changed¶
- CI lint workflow runs filter/shape conformance when the manifest is available.
[0.3.0] - 2026-02-09¶
Added¶
- Vehicles endpoints:
list_vehicles,get_vehicle, andlist_vehicle_awardees(supports shaping + flattening). (refsmakegov/tango#1328) - IDV endpoints:
list_idvs,get_idv,list_idv_awards,list_idv_child_idvs,list_idv_transactions,get_idv_summary,list_idv_summary_awards. (refsmakegov/tango#1328) - Webhooks v2 client support: event type discovery, subscription CRUD, endpoint management, test delivery, and sample payload helpers. (refs
makegov/tango#1274)
Changed¶
- Expanded explicit schemas to support common IDV shaping expansions (award offices, officers, period of performance, etc.).
- HTTP client now supports PATCH/DELETE helpers for webhook management endpoints.
[0.2.0] - 2025-11-16¶
- Entirely refactored SDK