This document provides the full API reference for the Node.js / TypeScript version of the Tango SDK. It is a translation of the Python SDK documentation, rewritten for JavaScript runtime semantics, async/await, and the TypeScript type system.
import { TangoClient, ShapeConfig } from "@makegov/tango-node";
// Models (optional)
import type { Contract } from "@makegov/tango-node/models";All methods are async and return Promises.
List federal departments and subagencies.
const resp = await client.listAgencies({ page: 1, limit: 25 });| Name | Type | Description |
|---|---|---|
page |
number |
Page number (default 1). |
limit |
number |
Max results per page (default 25, max 100). |
PaginatedResponse<AgencyLike>
Fetch a single agency by its code.
const agency = await client.getAgency("2000");Returns a shaped Agency object. Responses are materialized via the dynamic model pipeline (dates parsed, nested objects built).
Lists SBA/USASpending business type entries.
const types = await client.listBusinessTypes();Search and list contract records.
const resp = await client.listContracts({
keyword: "cloud",
naics_code: "541511",
shape: ShapeConfig.CONTRACTS_MINIMAL,
flat: true,
});These mirror the Python SDK:
| Filter | Maps to API param |
|---|---|
keyword |
search |
naics_code |
naics |
psc_code |
psc |
recipient_name |
recipient |
recipient_uei |
uei |
set_aside_type |
set_aside |
Sorting:
sort: "award_date",
order: "desc" // -> ordering="-award_date"Pagination + shaping options:
shape: string,
flat: boolean,
flatLists: boolean,
page: number,
limit: numberPaginatedResponse<Contract> materialized according to the requested shape. Date/datetime fields are parsed, decimals normalized to strings, nested recipients, agencies, and locations are objects.
Vehicles provide a solicitation-centric grouping of related IDVs.
const resp = await client.listVehicles({
search: "GSA schedule",
shape: ShapeConfig.VEHICLES_MINIMAL,
page: 1,
limit: 25,
});Supported parameters:
search(vehicle-level full-text search)page,limit(max 100)shape,flat,flatLists
const vehicle = await client.getVehicle("00000000-0000-0000-0000-000000000001", {
shape: ShapeConfig.VEHICLES_COMPREHENSIVE,
});Notes:
- On vehicle detail,
searchfilters expandedawardees(...)when included in yourshape(it does not filter the vehicle itself). - When using
flat: true, you can override the joiner withjoiner(default".").
const awardees = await client.listVehicleAwardees("00000000-0000-0000-0000-000000000001", {
shape: ShapeConfig.VEHICLE_AWARDEES_MINIMAL,
});IDVs (indefinite delivery vehicles) are the parent “vehicle award” records that can have child awards/orders under them.
const idvs = await client.listIdvs({
limit: 25,
cursor: null,
shape: ShapeConfig.IDVS_MINIMAL,
awarding_agency: "4700",
});Notes:
- This endpoint uses keyset pagination (
cursor+limit) rather thanpage.
const idv = await client.getIdv("SOME_IDV_KEY", {
shape: ShapeConfig.IDVS_COMPREHENSIVE,
});Lists child awards (contracts) under an IDV.
const awards = await client.listIdvAwards("SOME_IDV_KEY", { limit: 25 });const children = await client.listIdvChildIdvs({ key: "SOME_IDV_KEY", limit: 25 });const tx = await client.listIdvTransactions("SOME_IDV_KEY", { limit: 100 });const summary = await client.getIdvSummary("SOLICITATION_IDENTIFIER");
const awards = await client.listIdvSummaryAwards("SOLICITATION_IDENTIFIER", { limit: 25 });const resp = await client.listEntities({
search: "Acme",
shape: ShapeConfig.ENTITIES_MINIMAL,
});Filters:
search- any field names supported by the API
Fetch a single entity by UEI or CAGE.
Returns a shaped entity object with nested addresses/fields based on the shape.
Forecast search, with optional shaping.
Search SAM.gov opportunities with shaping.
Webhook APIs let Large / Enterprise users manage subscription filters for outbound Tango webhooks.
Discover supported event_type values and subject types.
const info = await client.listWebhookEventTypes();const subs = await client.listWebhookSubscriptions({ page: 1, pageSize: 25 });Notes:
- Uses
page+page_size(notlimit) for pagination on this endpoint.
const sub = await client.getWebhookSubscription("SUBSCRIPTION_UUID");await client.createWebhookSubscription({
subscriptionName: "Track specific vendors",
payload: {
records: [
{ event_type: "awards.new_award", subject_type: "entity", subject_ids: ["UEI123ABC"] },
{ event_type: "awards.new_transaction", subject_type: "entity", subject_ids: ["UEI123ABC"] },
],
},
});Notes:
- Prefer v2 fields:
subject_type+subject_ids. - Legacy compatibility:
resource_idsis accepted as an alias forsubject_ids(don’t send both). - Catch-all:
subject_ids: []means “all subjects” for that record and is Enterprise-only. Large tier users must list specific IDs.
await client.updateWebhookSubscription("SUBSCRIPTION_UUID", {
subscriptionName: "Updated name",
});await client.deleteWebhookSubscription("SUBSCRIPTION_UUID");In production, MakeGov provisions the initial endpoint for you. These methods are most useful for dev/self-service.
const endpoints = await client.listWebhookEndpoints({ page: 1, limit: 25 });
const endpoint = await client.getWebhookEndpoint("ENDPOINT_UUID");// Create (one endpoint per user)
const created = await client.createWebhookEndpoint({ callbackUrl: "https://example.com/tango/webhooks" });
// Update
await client.updateWebhookEndpoint(created.id, { isActive: false });
// Delete
await client.deleteWebhookEndpoint(created.id);Send an immediate test webhook to your configured endpoint.
const result = await client.testWebhookDelivery();Fetch Tango-shaped sample deliveries (and sample subscription request bodies).
const sample = await client.getWebhookSamplePayload({ eventType: "awards.new_award" });The API does not currently expose a public /api/webhooks/deliveries/ or redelivery endpoint. Use:
testWebhookDelivery()for connectivity checksgetWebhookSamplePayload()for building handlers + subscription payloads
Every delivery includes an HMAC signature header:
X-Tango-Signature: sha256=<hex digest>
Compute the digest over the raw request body bytes using your shared secret.
import crypto from "node:crypto";
export function verifyTangoWebhookSignature(secret: string, rawBody: Buffer, signatureHeader: string | null): boolean {
if (!signatureHeader) return false;
const sig = signatureHeader.startsWith("sha256=") ? signatureHeader.slice("sha256=".length) : signatureHeader;
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(sig, "hex"));
}All thrown by async methods:
TangoAPIErrorTangoAuthErrorTangoNotFoundErrorTangoRateLimitErrorTangoValidationErrorShapeErrorShapeParseErrorShapeValidationErrorTypeGenerationErrorModelInstantiationError
All list endpoints return:
interface PaginatedResponse<T> {
count: number;
next: string | null;
previous: string | null;
pageMetadata: Record<string, unknown> | null;
results: T[];
}You can follow next / previous manually or use your own wrapper.