Method-by-method reference for every public function and method on *tango.Client plus the supporting types. ~94 methods in total. For client construction options, see CLIENT.md; for response shaping, see SHAPES.md; for webhook signing + receiving, see WEBHOOKS.md.
All methods take context.Context first. Options structs are always passed by pointer; nil is valid and means "use SDK / server defaults". List methods return *PaginatedResponse[Record] (where Record = map[string]any); a handful of typed-return methods are flagged inline. Detail methods return Record or a typed *<Resource>Record struct (also flagged).
import "github.com/makegov/tango-go"
client := tango.NewClient(tango.WithAPIKey(os.Getenv("TANGO_API_KEY")))- Agencies
- Organizations / Offices / Departments
- Business types
- Contracts
- IDVs (+ sub-resources)
- OTAs / OTIDVs
- Subawards
- Vehicles (+ sub-resources)
- Entities (+ sub-resources)
- Opportunities / Notices / Forecasts / Grants
- Protests
- IT Dashboard
- GSA eLibrary
- LCATs
- Metrics
- Lookups (NAICS / PSC / MAS SINs / Assistance Listings)
- Resolve / Validate
- Webhooks
- Meta (Version / API keys)
GET /api/agencies/. List federal departments and subagencies.
page, err := client.ListAgencies(ctx, &tango.ListAgenciesOptions{
Page: 1, Limit: 25, Search: "Defense",
})ListAgenciesOptions is intentionally minimal: Page, Limit (max 100; the SDK caps), Search.
GET /api/agencies/{code}/. Fetch a single agency by its CGAC code (e.g. "9700" for Defense, "2000" for Treasury).
Typed return. Returns
*AgencyRecord, notRecord. Pointer fields (AgencyID,Name,Abbreviation,Code) distinguish "absent" from "empty";Extra map[string]anypreserves forward-compatible fields.
agency, err := client.GetAgency(ctx, "9700")
if agency.Name != nil {
fmt.Println(*agency.Name)
}ListAgencyAwardingContracts(ctx, code string, *AgencyContractsOptions) (*PaginatedResponse[Record], error)
GET /api/agencies/{code}/contracts/awarding/. List contracts where the given agency is the awarding agency.
ListAgencyFundingContracts(ctx, code string, *AgencyContractsOptions) (*PaginatedResponse[Record], error)
GET /api/agencies/{code}/contracts/funding/. List contracts where the given agency is the funding agency.
Both methods accept AgencyContractsOptions: embeds ListOptions plus Joiner (for Flat: true), Ordering, Search, and Extra for unknown filters.
GET /api/organizations/. The canonical agency/department/office hierarchy. Use this in preference to the deprecated ListDepartments.
Filter fields: Search, Type, Level ("1" = department, "2" = agency, "3" = sub-agency, ...), CGAC, Parent, IncludeInactive *bool.
orgs, _ := client.ListOrganizations(ctx, &tango.ListOrganizationsOptions{
Level: "1",
Search: "Defense",
})GET /api/organizations/{key}/.
GET /api/offices/. Federal contracting offices (FPDS-NG hierarchy). Filter via Search.
GET /api/offices/{code}/. Code is the FPDS-NG office code.
Deprecated upstream.
GET /api/departments/. Retained for parity. PreferListOrganizationswithLevel: "1".
GET /api/departments/{code}/. Code is typically the CGAC department code.
GET /api/business_types/. SBA / SAM.gov socioeconomic and structural designations (8(a), woman-owned, veteran-owned, non-profit, etc.).
GET /api/business_types/{code}/. Returns *NotFoundError when the code is unknown.
GET /api/contracts/. Search and list federal contract records.
page, _ := client.ListContracts(ctx, &tango.ListContractsOptions{
ListOptions: tango.ListOptions{Shape: tango.ShapeContractsMinimal, Limit: 25},
AwardingAgency: "9700",
FiscalYear: "2025",
Keyword: "cloud services",
Sort: "award_date",
Order: "desc",
})Filter aliases. ListContractsOptions mirrors the Node and Python SDKs' SDK-friendly aliases:
| SDK-friendly field | Wire param | Notes |
|---|---|---|
Keyword |
search |
|
NAICSCode |
naics |
also NAICS accepted |
PSCCode |
psc |
also PSC accepted |
RecipientName |
recipient |
also Recipient accepted |
RecipientUEI |
uei |
also UEI accepted |
SetAsideType |
set_aside |
also SetAside accepted |
When both an alias and a canonical field are set, the alias wins (mirrors Node).
Sorting. Two ways:
opts.Ordering = "-award_date" // wire format
// or
opts.Sort = "award_date"
opts.Order = "desc" // "asc" (default) or "desc"Pagination. Both ?page= and ?cursor= are supported. Set Cursor for deep pagination; set Page for shallow. They're mutually exclusive — Cursor wins if both are set.
Date / FY / dollar fields are all strings on the wire (e.g. "2024-01-01", "2024"). See the godoc on ListContractsOptions for the full filter set.
Walks every contract matching opts. Auto-follows ?page= or ?cursor= based on the server's next URL.
for c, err := range client.IterateContracts(ctx, opts).Seq() {
if err != nil { return err }
fmt.Println(c["piid"])
}IDVs (indefinite delivery vehicles) are parent "vehicle award" records that can have child awards/orders under them.
GET /api/idvs/. Cursor-paginated.
GET /api/idvs/{key}/. Pass &GetEntityOptions{Shape: tango.ShapeIDVsComprehensive} for a full-fidelity envelope.
GET /api/idvs/{key}/awards/. Lists task-order child awards under a parent IDV. Re-uses ListIDVsOptions for filter fidelity.
GET /api/idvs/{key}/idvs/. Child IDVs nested under a parent IDV.
GET /api/idvs/{key}/transactions/. Raw transaction history backing an IDV. Only accepts pagination params (no filters).
Deprecated.
GET /api/idvs/{identifier}/summary/. The current server returns404for this endpoint. Retained for parity with the Node SDK. Migrate toGetIDVwith a richerShape.
Deprecated.
GET /api/idvs/{identifier}/summary/awards/. Server returns404. Migrate toListIDVAwards.
GET /api/idvs/{key}/lcats/. Labor Categories attached to an IDV. Re-uses EntityLcatsOptions because the entity and IDV lcats endpoints share a parameter shape.
OTAs (Other Transaction Authority awards) and OTIDVs (umbrella OT agreements with child awards) are FAR-exempt awards used by DoD and others for prototype + research work.
GET /api/otas/. Cursor-paginated. Filters: AwardingAgency, FundingAgency, PIID, Recipient, UEI, FiscalYear[Gte/Lte], AwardDate[Gte/Lte], ExpiringGte/Lte, PopStartDate[Gte/Lte], PopEndDate[Gte/Lte], PSC, Search, Ordering, Joiner (for Flat).
GET /api/otas/{key}/.
GET /api/otidvs/. Same filter set as ListOTAsOptions.
GET /api/otidvs/{key}/.
GET /api/otidvs/{key}/awards/. Child awards under an OTIDV parent. Same filter set as ListOTAsOptions.
GET /api/subawards/. Filters: AwardKey, PrimeUEI, SubUEI, AwardingAgency, FundingAgency, FiscalYear[Gte/Lte], Recipient, Ordering.
Ordering allowlist. The server rejects all ordering values except
"last_modified_date"and"-last_modified_date". Other values return400(tango#2254).
Shape constraints. Use
ShapeSubawardsMinimal— the server rejectsidandamountin subaward shapes.
Vehicles provide a solicitation-centric grouping of related IDVs.
GET /api/vehicles/. Filters: Search (full-text), VehicleType, TypeOfIDC, ContractType, SetAside, WhoCanUse, NAICSCode, PSCCode, ProgramAcronym, Agency, OrganizationID, dollar/count bounds, fiscal year, award/last-date-to-order date ranges, Ordering, Joiner.
Ordering allowlist. Server enforces a strict allowlist; other values return
400.
GET /api/vehicles/{uuid}/. On the detail endpoint, search filters expanded awardees(...) when included in your shape (it does not filter the vehicle itself).
GET /api/vehicles/{uuid}/awardees/. The entities holding child IDVs under a vehicle. Use ShapeVehicleAwardeesMinimal for the common preset.
GET /api/vehicles/{uuid}/orders/. Task orders placed under a vehicle's child IDVs.
Python-only method on the sibling SDKs — included here for full parity.
GET /api/entities/. Federal vendors / recipients. Filters: Search, CageCode, NAICS, Name, PSC, PurposeOfRegistrationCode, Socioeconomic, State, TotalAwardsObligated[Gte/Lte], UEI, ZipCode.
GET /api/entities/{key}/. Key is the UEI or CAGE code. When Shape is empty, the server returns its comprehensive default; pass ShapeEntitiesMinimal for a slimmer payload.
All take a UEI plus *EntitySubresourceOptions (embeds ListOptions + Joiner + Ordering + Search + Extra), except ListEntitySubawards (uses EntitySubawardsOptions) and ListEntityLcats (uses EntityLcatsOptions).
| Method | Endpoint |
|---|---|
ListEntityContracts(ctx, uei, *EntitySubresourceOptions) |
GET /api/entities/{uei}/contracts/ |
ListEntityIDVs(ctx, uei, *EntitySubresourceOptions) |
GET /api/entities/{uei}/idvs/ |
ListEntityOTAs(ctx, uei, *EntitySubresourceOptions) |
GET /api/entities/{uei}/otas/ |
ListEntityOTIDVs(ctx, uei, *EntitySubresourceOptions) |
GET /api/entities/{uei}/otidvs/ |
ListEntitySubawards(ctx, uei, *EntitySubawardsOptions) |
GET /api/entities/{uei}/subawards/ |
ListEntityLcats(ctx, uei, *EntityLcatsOptions) |
GET /api/entities/{uei}/lcats/ |
All return *PaginatedResponse[Record]. Empty UEI is rejected client-side as *ValidationError.
GET /api/entities/{uei}/metrics/{months}/{periodGrouping}/. See Metrics below.
GET /api/opportunities/. SAM.gov opportunities. Filters: Active *bool, Agency, FirstNoticeDate[After/Before], LastNoticeDate[After/Before], NAICS, NoticeType, Ordering, PlaceOfPerformance, PSC, ResponseDeadline[After/Before], Search, SetAside, SolicitationNumber.
GET /api/opportunities/attachment-search/. Semantic search over the extracted text of opportunity attachments (SOWs, PWSs, J&As, etc.).
res, err := client.SearchOpportunityAttachments(ctx, tango.SearchOpportunityAttachmentsOptions{
Q: "cybersecurity zero trust",
TopK: 10,
IncludeExtractedText: false,
})Q is required; empty Q raises *ValidationError before any network call. TopK: 0 means "use the server default".
GET /api/notices/. Filters: Active *bool, Agency, NAICS, NoticeType, PostedDate[After/Before], PSC, ResponseDeadline[After/Before], Search, SetAside, SolicitationNumber.
No ordering. The notices viewset rejects every
?ordering=value, soListNoticesOptionsdeliberately omits anOrderingfield (mirrors Python and Node).
GET /api/forecasts/. Filters: Agency, AwardDate[After/Before], FiscalYear[Gte/Lte], Modified[After/Before], NAICSCode, NAICSStartsWith, Ordering, Search, SourceSystem, Status.
GET /api/grants/. Filters: Agency, ApplicantTypes, CFDANumber, FundingCategories, FundingInstruments, OpportunityNumber, Ordering, PostedDate[After/Before], ResponseDate[After/Before], Search, Status.
GET /api/protests/. Bid protests from GAO + COFC. Filters: SourceSystem, Outcome, CaseType, Agency, CaseNumber, SolicitationNumber, Protester, Search, FiledDate[After/Before], DecisionDate[After/Before].
No ordering. The viewset rejects ordering;
ListProtestsOptionsdeliberately omits the field.
GET /api/protests/{caseNumber}/.
Typed return. Returns
*ProtestRecordwith named fields (CaseID,CaseNumber,SourceSystem,Outcome,CaseType,FiledDate,DecisionDate,Agency,Protester,ResolvedAgency,ResolvedProtester,Docket []map[string]any,Extra map[string]any).
Use shape: "...,docket(...)" to include the nested docket entries.
GET /api/itdashboard/. Federal IT investments. Filters are tier-gated by the API:
- Free:
Search - Pro:
AgencyCode,TypeOfInvestment,UpdatedTime[After/Before] - Business+:
AgencyName,CIORating,CIORatingMax,PerformanceRisk
Hitting a gated filter on a lower tier returns 403 (surfaces as *APIError with StatusCode 403).
CIO ratings: 1 = High Risk, 2 = Moderately High, 3 = Medium, 4 = Moderately Low, 5 = Low.
GET /api/itdashboard/{uii}/. UII is the Unique Investment Identifier.
GET /api/gsa_elibrary_contracts/. Filters: Schedule, ContractNumber, Key, PIID, UEI, SIN, Search, Ordering.
GET /api/gsa_elibrary_contracts/{uuid}/. Python-only on the sibling SDKs; included here for parity.
Labor Categories. LCATs live under owner resources in the Tango API — there is no top-level /api/lcats/ endpoint. ListLcats dispatches based on which field on *ListLcatsOptions is set:
UEIset →GET /api/entities/{uei}/lcats/IDVKeyset →GET /api/idvs/{key}/lcats/- Both set → UEI wins (mirrors the Node SDK)
- Neither set → returns
*ValidationError
The embedded EntityLcatsOptions carries Ordering, Search, plus the standard ListOptions (Page / Limit / Cursor / Shape / Flat / FlatLists).
Same dispatch rules as ListLcats; the iterator walks pages of the dispatched endpoint.
See also: ListEntityLcats(ctx, uei, *EntityLcatsOptions) and ListIDVLcats(ctx, key, *EntityLcatsOptions) for direct sub-resource calls when you already know the owner type.
Rolling-window metrics aggregated by NAICS, PSC, or entity. All three concrete getters take (code, months, periodGrouping) where months > 0 and periodGrouping is typically "month", "quarter", or "year".
GET /api/naics/{code}/metrics/{months}/{periodGrouping}/.
GET /api/psc/{code}/metrics/{months}/{periodGrouping}/.
GET /api/entities/{uei}/metrics/{months}/{periodGrouping}/.
Convenience dispatcher that routes to one of the three above based on opts.OwnerType (tango.MetricsOwnerNAICS / MetricsOwnerPSC / MetricsOwnerEntity).
m, err := client.ListMetrics(ctx, tango.ListMetricsOptions{
OwnerType: tango.MetricsOwnerNAICS,
OwnerID: "541511",
Months: 12,
PeriodGrouping: "month",
})Empty OwnerID, non-positive Months, empty PeriodGrouping, or unknown OwnerType all return *ValidationError client-side.
GET /api/naics/. Filters: Search, RevenueLimit[Gte/Lte], EmployeeLimit[Gte/Lte].
GET /api/naics/{code}/.
GET /api/psc/.
GET /api/psc/{code}/.
GET /api/mas_sins/. MAS (Multiple Award Schedule) Special Item Numbers.
GET /api/mas_sins/{sin}/.
GET /api/assistance_listings/. The CFDA (Catalog of Federal Domestic Assistance) program catalog.
GET /api/assistance_listings/{number}/. Number is the CFDA number (e.g. "10.001").
POST /api/resolve/. Fuzzy-match a free-text name to ranked entity or organization candidates.
result, err := client.Resolve(ctx, tango.ResolveInput{
Name: "Lockheed Martin",
TargetType: tango.ResolveEntity, // or tango.ResolveOrganization
State: "MD", // optional disambiguator
})
for _, c := range result.Candidates {
fmt.Println(c.Identifier, c.DisplayName, c.MatchTier)
}Typed return.
*ResolveResult(withCount int,Candidates []ResolveCandidate). Each candidate hasIdentifier,DisplayName,MatchTier(Pro+ only — Free responses omit this), andExtra map[string]anyfor forward-compatible fields.
Required fields: Name, TargetType ("entity" | "organization"). Both validated client-side.
POST /api/validate/. Validate the format of an identifier.
result, err := client.Validate(ctx, tango.ValidateInput{
Type: tango.ValidateUEI, // or ValidatePIID / ValidateSolicitation
Value: "ABCDEF123456",
})
fmt.Println(result.Result) // "valid" | "invalid" | "low_confidence"Value is required client-side. Result.Errors carries structured failures when the result is non-valid.
See WEBHOOKS.md for the full guide. Quick reference:
| Method | Endpoint |
|---|---|
ListWebhookEventTypes(ctx) → *WebhookEventTypesResponse |
GET /api/webhooks/event-types/ |
ListWebhookEndpoints(ctx, *ListOptions) → *PaginatedResponse[WebhookEndpoint] |
GET /api/webhooks/endpoints/ |
GetWebhookEndpoint(ctx, id) → *WebhookEndpoint |
GET /api/webhooks/endpoints/{id}/ |
CreateWebhookEndpoint(ctx, WebhookEndpointCreateInput) → *WebhookEndpoint |
POST /api/webhooks/endpoints/ |
UpdateWebhookEndpoint(ctx, id, WebhookEndpointUpdateInput) → *WebhookEndpoint |
PATCH /api/webhooks/endpoints/{id}/ |
DeleteWebhookEndpoint(ctx, id) error |
DELETE /api/webhooks/endpoints/{id}/ |
TestWebhookEndpoint(ctx, endpointID) → *WebhookTestDeliveryResult |
POST /api/webhooks/endpoints/test-delivery/ |
GetWebhookSamplePayload(ctx, eventType) → *WebhookSamplePayloadResponse |
GET /api/webhooks/endpoints/sample-payload/?event_type={eventType} |
CreateWebhookEndpoint validates Name + CallbackURL client-side (both required; Name is unique per user server-side).
| Method | Endpoint |
|---|---|
ListWebhookAlerts(ctx, *ListOptions) → *PaginatedResponse[WebhookAlert] |
GET /api/webhooks/alerts/ |
GetWebhookAlert(ctx, id) → *WebhookAlert |
GET /api/webhooks/alerts/{id}/ |
CreateWebhookAlert(ctx, WebhookAlertCreateInput) → *WebhookAlert |
POST /api/webhooks/alerts/ |
UpdateWebhookAlert(ctx, id, WebhookAlertUpdateInput) → *WebhookAlert |
PATCH /api/webhooks/alerts/{id}/ |
DeleteWebhookAlert(ctx, id) error |
DELETE /api/webhooks/alerts/{id}/ |
CreateWebhookAlert validates Name, QueryType, non-empty Filters client-side. QueryType is singular ("contract", not "contracts").
GET /api/version/. Returns the server's version metadata (build commit, deployed-at, etc.).
GET /api/api-keys/. Returns the authenticated user's API keys. Non-paginated — returns a structured Record with the caller's keys and metadata.
These aren't resource methods but are part of the public surface — useful when wiring up logging, metrics, or per-environment configuration. See CLIENT.md for full details.
| Method | Returns | Purpose |
|---|---|---|
Client.BaseURL() |
string |
The resolved base URL the client is hitting. |
Client.RateLimitInfo() |
*RateLimitInfo |
Snapshot of the rate-limit headers from the most recent response. nil before any request. |
Client.LastResponseHeaders() |
http.Header |
Headers from the most recent response (X-Request-Id, etc.). nil before any request. |
context.Contextis always first. Even for methods that have no other knobs (GetVersion,ListAPIKeys),ctxis the first arg.- Options structs are pointers. Passing
nilis valid for any*Xxxopts argument and means "use SDK / server defaults". The SDK never panics on a nil opts. - Required path segments are validated client-side. Empty
uei,key,code,id, etc. return*ValidationErrorwithStatusCode: 0before any network call. - Date fields are strings. Wire format is
YYYY-MM-DDfor dates, ISO 8601 with timezone for timestamps, integer-as-string for fiscal years (e.g."2024"). Notime.Timeparsing layer in the SDK. Recordismap[string]any. Use it as you would anymap; serialize withencoding/json; cast to your own struct viajson.Marshal→json.Unmarshalwhen you want field safety.- The full method count is ~94. This page lists every one. If you find a sibling-SDK method that isn't here, file an issue.