A fully-typed TypeScript SDK for the Vantage API. Types and client methods are auto-generated from the official OpenAPI specification.
npm install @vantage-sh/vantage-clientThis SDK provides two distinct modes of operation: a high-level resource API for convenience, and a low-level typed request method for full control with complete type safety.
The APIV2Client organizes endpoints by resource with intuitive CRUD methods:
import { APIV2Client } from "@vantage-sh/vantage-client";
const client = new APIV2Client("your-api-token");
// List resources with query parameters
const reports = await client.costReports.list({ page: 1 });
// Get a specific resource by token
const report = await client.costReports.get("rprt_abc123");
// Create a new resource
const folder = await client.folders.create({
title: "Production Costs",
workspace_token: "wrkspc_123",
});
// Update a resource
await client.folders.update("fldr_abc123", {
title: "Updated Title",
});
// Delete a resource
await client.folders.delete("fldr_abc123");Resources with nested or specialized endpoints expose additional methods:
// Access sub-resources
const costs = await client.costs.getForCostReport("rprt_abc123", {
start_date: "2024-01-01",
end_date: "2024-01-31",
});For full control, use the request method directly with path strings. The SDK provides complete type safety — TypeScript validates that your path exists, your method is supported, and your request/response bodies match the schema:
import { APIV2Client } from "@vantage-sh/vantage-client";
const client = new APIV2Client("your-api-token");
// Path and method are type-checked against the OpenAPI schema
const report = await client.request(
"/cost_reports/rprt_abc123",
"GET",
undefined
);
// TypeScript enforces correct body shape for POST/PUT/PATCH
const newFolder = await client.request("/folders", "POST", {
title: "My Folder",
workspace_token: "wrkspc_123",
});
// Query parameters are passed as the body for GET requests
const reports = await client.request("/cost_reports", "GET", {
page: 1,
});The Path type is a union of all valid API paths. TypeScript will error on invalid paths:
// ✓ Valid path
await client.request("/cost_reports", "GET", { page: 1 });
// ✗ TypeScript error: invalid path
await client.request("/not_a_real_endpoint", "GET", {});The SupportedMethods<P> type ensures only valid HTTP methods for each path:
// ✓ GET is supported on /cost_reports
await client.request("/cost_reports", "GET", { page: 1 });
// ✗ TypeScript error: DELETE not supported on /cost_reports
await client.request("/cost_reports", "DELETE", {});Import types for individual endpoints when needed:
import type {
GetCostReportResponse,
CreateFolderRequest,
CreateFolderResponse,
} from "@vantage-sh/vantage-client";
function displayReport(report: GetCostReportResponse) {
console.log(report.title);
}By default, API errors are thrown as VantageAPIError with structured error information:
import { VantageAPIError } from "@vantage-sh/vantage-client";
try {
await client.costReports.get("invalid_token");
} catch (error) {
if (error instanceof VantageAPIError) {
console.log(error.status); // 404
console.log(error.statusText); // "Not Found"
console.log(error.errors); // ["Resource not found"] or null
}
}For Go-style error handling without try/catch, enable never throw mode by passing true as the second argument to the client constructor:
import { APIV2Client, VantageAPIError } from "@vantage-sh/vantage-client";
const client = new APIV2Client("your-api-token", true);
// All methods return [result, null] on success or [null, error] on failure
const [report, error] = await client.costReports.get("rprt_abc123");
if (error) {
console.log(error.status); // 404
console.log(error.errors); // ["Resource not found"]
return;
}
// TypeScript knows report is defined here
console.log(report.title);This pattern works with all client methods, including the low-level request method:
const client = new APIV2Client("your-api-token", true);
const [folders, error] = await client.request("/folders", "GET", { page: 1 });
if (error) {
// Handle error
return;
}
// Use folders safelyUse pathEncode to safely encode dynamic path segments:
import { pathEncode } from "@vantage-sh/vantage-client";
const token = pathEncode(userProvidedToken);
const report = await client.request(
`/cost_reports/${token}`,
"GET",
undefined
);To create the checked in generated files, run the following command.
npm run generatenpm run buildThis fetches the latest OpenAPI schema from the Vantage API, generates TypeScript types, and compiles the client.
npm run type-checkThe client automatically detects multipart/form-data routes and handles them appropriately. However, this detection requires a manually-maintained mapping in BaseClient.ts:
const multipartEdgeCases: MultipartEdgeCases = {
"/exchange_rates/csv": {
POST: true,
},
"/business_metrics/{}/values.csv": {
PUT: true,
},
// ...
};The MultipartEdgeCases type is derived from the OpenAPI schema. If a new multipart route is added to the API, TypeScript will produce an error until you add the route to this object. Path parameters are represented as {} in the keys.
The SDK exports several utility types for advanced use:
| Type | Description |
|---|---|
Path |
Union of all valid API paths |
SupportedMethods<P> |
Valid HTTP methods for a given path |
RequestBodyForPathAndMethod<P, M> |
Request body type for a path/method |
ResponseBodyForPathAndMethod<P, M> |
Response body type for a path/method |
NoSlashString |
Branded type for safely encoded path segments |
To run the tests, create an .env.local file copying the values from .env.example. You will need
VANTAGE_API_TOKEN- API Token with Read / Write accessVANTAGE_WORKSPACE_TOKEN- Workspace token for a location to create objectsVANTAGE_API_BASE_URL- Optionally, override the API URL. Default isapi.vantage.sh
After building locally and confirming the changes in the Vantage API are reflected in the types in this
repository, bump the version in package.json, run npm i, and open a PR. CI will take care of publishing
the new version with the updates.
Semantic Considerations:
patch- Bug fixesminor- New APIs or additions to existing APIsmajor- Breaking changes