Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
name: Linting

# Disabled: requires checkout of private makegov/tango repo for filter_shape conformance check.
# Re-enable when that repo is accessible (e.g. add TANGO_API_REPO_ACCESS_TOKEN secret).
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:
# push:
# branches: [ main, develop ]
# pull_request:
# branches: [ main, develop ]

jobs:
lint:
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.4.2] - 2026-03-04

### Added
- Protests endpoints: `list_protests`, `get_protest` with 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/tango` repo is accessible to the workflow.
- Updated documents to reflect changes since v0.4.0
- Entities: `ENTITIES_COMPREHENSIVE` now uses `federal_obligations(*)` expansion; the API treats federal obligations as an expansion rather than a plain shape field.
- Docs: `SHAPES.md` documents `federal_obligations(*)` as an expansion for entity shaping.
- Integration tests: `test_parsing_nested_objects_with_missing_data` accepts award office fields (`office_code`, `agency_code`, `department_code`) and empty nested objects when the API returns partial data.

### Removed
- Assistance: `list_assistance` endpoint and all related tests, docs, and references.
- IDV summaries: `get_idv_summary` and `list_idv_summary_awards` endpoints and related integration tests, cassettes, and API reference section.

## [0.4.1] - 2026-03-03

### Added
Expand Down
84 changes: 56 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A modern Python SDK for the [Tango API](https://tango.makegov.com) by MakeGov, f

- **Dynamic Response Shaping** - Request only the fields you need, reducing payload sizes by 60-80%
- **Full Type Safety** - Runtime-generated TypedDict types with accurate type hints for IDE autocomplete
- **Comprehensive API Coverage** - All major Tango API endpoints (contracts, entities, forecasts, opportunities, notices, grants, webhooks) [Note: the current version does NOT implement all endpoints, we will be adding them incrementally]
- **Comprehensive API Coverage** - All major Tango API endpoints (contracts, IDVs, OTAs, entities, forecasts, opportunities, notices, grants, protests, webhooks, and more)
- **Flexible Data Access** - Dictionary-based response objects with validation
- **Modern Python** - Built for Python 3.12+ using modern async-ready patterns
- **Production-Ready** - Comprehensive test suite with VCR.py-based integration tests
Expand Down Expand Up @@ -152,14 +152,33 @@ contracts = client.list_contracts(
**Response Options:**
- `shape`, `flat`, `flat_lists` - Response shaping options

### IDVs, OTAs, OTIDVs

```python
# List IDVs (keyset pagination)
idvs = client.list_idvs(limit=25, awarding_agency="4700")

# Get single IDV with shaping
idv = client.get_idv("IDV_KEY", shape=ShapeConfig.IDVS_COMPREHENSIVE)

# OTAs and OTIDVs follow the same pattern
otas = client.list_otas(limit=25)
otidvs = client.list_otidvs(limit=25)
```

### Vehicles

```python
vehicles = client.list_vehicles(search="GSA schedule", shape=ShapeConfig.VEHICLES_MINIMAL)
vehicle = client.get_vehicle("UUID", shape=ShapeConfig.VEHICLES_COMPREHENSIVE)
awardees = client.list_vehicle_awardees("UUID")
```

### Entities (Vendors/Recipients)

```python
# List entities
entities = client.list_entities(
page=1,
limit=25
)
# List entities with filters
entities = client.list_entities(search="Booz Allen", state="VA", limit=25)

# Get specific entity by UEI or CAGE code
entity = client.get_entity("ZQGGHJH74DW7")
Expand All @@ -168,47 +187,49 @@ entity = client.get_entity("ZQGGHJH74DW7")
### Forecasts

```python
# List contract forecasts
forecasts = client.list_forecasts(
agency="GSA",
limit=25
)
forecasts = client.list_forecasts(agency="GSA", fiscal_year=2025, limit=25)
```

### Opportunities

```python
# List opportunities/solicitations
opportunities = client.list_opportunities(
agency="DOD",
limit=25
)
opportunities = client.list_opportunities(agency="DOD", active=True, limit=25)
```

### Notices

```python
# List contract notices
notices = client.list_notices(
agency="DOD",
limit=25
)
notices = client.list_notices(agency="DOD", notice_type="award", limit=25)
```

### Grants

```python
# List grant opportunities
grants = client.list_grants(
agency_code="HHS",
limit=25
)
grants = client.list_grants(agency="HHS", status="forecasted", limit=25)
```

### Protests

```python
protests = client.list_protests(source_system="gao", outcome="Sustained", limit=25)
protest = client.get_protest("CASE_UUID")
```

### GSA eLibrary Contracts

```python
contracts = client.list_gsa_elibrary_contracts(schedule="MAS", limit=25)
contract = client.get_gsa_elibrary_contract("UUID")
```

### Business Types
### Reference Data

```python
# List business types
# Offices, organizations, NAICS, subawards, business types
offices = client.list_offices(search="acquisitions")
organizations = client.list_organizations(level=1)
naics = client.list_naics(search="software")
subawards = client.list_subawards(prime_uei="UEI123")
business_types = client.list_business_types()
```

Expand Down Expand Up @@ -421,9 +442,16 @@ tango-python/
│ ├── test_entities_integration.py
│ ├── test_forecasts_integration.py
│ ├── test_grants_integration.py
│ ├── test_naics_integration.py
│ ├── test_notices_integration.py
│ ├── test_offices_integration.py
│ ├── test_opportunities_integration.py
│ ├── test_organizations_integration.py
│ ├── test_otas_otidvs_integration.py
│ ├── test_protests_integration.py
│ ├── test_reference_data_integration.py
│ ├── test_subawards_integration.py
│ ├── test_vehicles_idvs_integration.py
│ └── test_edge_cases_integration.py
├── docs/ # Documentation
│ ├── API_REFERENCE.md # Complete API reference
Expand Down
Loading