Node.js SDK
Build JavaScript and TypeScript integrations without writing HTTP requests by hand.
Install and authenticate
Install @chadwin/sdk with npm:
npm install @chadwin/sdkThe SDK requires Node.js 22 or newer. Create a client with your Chadwin API key, then make your first request:
import { Chadwin } from "@chadwin/sdk";
const apiKey = process.env.CHADWIN_API_KEY;
if (!apiKey) throw new Error("CHADWIN_API_KEY is not set");
const client = new Chadwin({ apiKey });
const { company } = await client.companies.get({ ticker: "AAPL" });
console.log(company.name);Choose a resource
Company search includes stored historical ticker associations and companies without listings. Its listings array may be empty and makes no claim about current listing status. Ticker detail resolves one CIK from the accepted SEC ticker snapshot; its is_current field means snapshot membership, not verified trading or business status.
The client groups methods by the kind of data you want:
| What you want to do | SDK resource |
|---|---|
| Search stored companies or retrieve a company by its SEC ticker association | client.companies |
| Retrieve annual or quarterly company-report data and complete cleaned HTML | client.companyReports |
| Retrieve reviewed normalized annual financial statements and metrics | client.financialStatements |
| List insider transactions from Forms 3, 4, and 5 | client.insiderTransactions |
| Retrieve a complete Form 3, 4, or 5 filing | client.insiderFilings |
| List or retrieve Form 144 proposed sales | client.proposedSales |
| Retrieve a Form 13F filing and its reported holdings | client.institutionalFilings |
| Find Form 13F managers and retrieve their periods, holdings, or positions | client.institutionalManagers |
| Poll for newly published data | client.feeds |
Method inputs and results are typed and work with TypeScript inference. JSON results keep the field names shown in the API reference.
Common workflows
Retrieve company reports and their HTML
Use companyReports.get for a company and fiscal period, and companyReports.getByAccession for one exact filing. Version 0.10 replaces getForPeriod and moves the former accession-only get to getByAccession.
A fiscal-year lookup returns the original report and any amendments listed together. Use each filing's accession number to retrieve its complete cleaned HTML.
const report = await client.companyReports.get({
ticker: "AAPL",
fiscalYear: 2025,
fiscalPeriod: "FY",
});
for (const filing of report.filings) {
const html = await client.companyReports.getHtml({
accessionNumber: filing.accession_number,
});
console.log(filing.form, html.length);
}For a 10-Q, use the filer-reported Q1, Q2, or Q3 fiscal period. These values do not assume calendar quarters, and there is no Q4 because the annual filing covers the fourth quarter.
const report = await client.companyReports.get({
ticker: "AAPL",
fiscalYear: 2025,
fiscalPeriod: "Q3",
});
for (const filing of report.filings) {
console.log(filing.form, filing.accession_number);
}Retrieve normalized annual financial statements
Company detail and statement methods accept exactly one ticker or cik, for example client.companies.get({ cik: "320193" }). CIKs are strings and do not require a current listing. Statement issuer name and ticker may be null.
Use financialStatements.get to retrieve available reviewed values for one fiscal year or the newest available years. The financial statements beta guide explains current coverage and missing results.
const result = await client.financialStatements.get({
ticker: "AAPL",
fiscalYear: 2024,
});
console.log(result.periods[0]?.income_statement.revenue);Find insider purchases and sales
Filter a company's insider transactions by SEC acceptance date and transaction code. P identifies an open-market or private purchase, and S identifies an open-market or private sale.
for await (const transaction of client.insiderTransactions.iterate({
tickers: ["AAPL"],
from: "2026-08-01",
transactionCodes: ["P", "S"],
})) {
console.log(transaction);
}Retrieve an institutional manager's positions
Use a manager's Form 13F file number to retrieve its latest consolidated positions.
const { positions } = await client.institutionalManagers.listPositions({
form13fFileNumber: "028-04545",
period: "latest",
});
for (const position of positions) {
console.log(position);
}Retrieve large result sets
Insider transactions and proposed sales use the same list and iterate methods for one company or a watchlist. Supply tickers: ["AAPL"] or ciks: ["0000320193"], never both. Omit both to query the current listed-company universe. Each result row includes its issuer. The former listForCompany and iterateForCompany methods are removed.
Version 0.10 restarts history pagination. Old cursors return invalid_cursor; start again without a cursor. Keep the same identifiers, dates, codes, and page size on later pages. A changed ticker-to-CIK mapping also requires a restart.
Historical insider transactions, proposed sales, institutional managers, reported holdings, and consolidated positions can contain thousands of records. Their SDK methods return one page at a time so your application does not have to load the full result set in one response.
Each page includes a next_cursor. When it has a value, pass it to the same method with the original identifiers and filters to retrieve the next page.
The API binds each cursor to the operation, identifiers, filters, and page size that produced it. Filing-holdings and manager-period cursors also bind to the source row-set revision. If that data changes during traversal, the API returns a 409 restart error instead of mixing pages; restart without a cursor.
Choose how to retrieve results
Use the page method when you need a “Load more” interface or want to save next_cursor and resume later. Use the async iterator when you want the SDK to retrieve every page for you.
| Results | One page | Every page |
|---|---|---|
| Insider transactions | insiderTransactions.list() | insiderTransactions.iterate() |
| Proposed sales | proposedSales.list() | proposedSales.iterate() |
| Institutional managers | institutionalManagers.list() | institutionalManagers.iterateManagers() |
| Holdings in one filing | institutionalFilings.listHoldings() | institutionalFilings.iterateHoldings() |
| Manager holdings | institutionalManagers.listHoldings() | institutionalManagers.iterateHoldings() |
| Manager positions | institutionalManagers.listPositions() | institutionalManagers.iteratePositions() |
for await (const position of client.institutionalManagers.iteratePositions({
form13fFileNumber: "028-04545",
period: "latest",
})) {
await savePosition(position);
}Feed resources do not provide iterators because your application must save its progress between polling runs. Use the filing and transaction feed guide to build that consumer.
Handle errors
Failed requests throw APIError. Use its status and code fields to decide what your application should do:
import { APIError } from "@chadwin/sdk";
try {
await client.companies.get({ ticker: "AAPL" });
} catch (error) {
if (error instanceof APIError) {
console.error(error.status, error.code);
} else {
throw error;
}
}The SDK retries safe requests after temporary network, rate-limit, and server failures. It does not retry permanent input, access, or billing-period quota errors.
Read response headers
A normal SDK request returns the parsed, typed result. Most integrations only need this data.
If you also need HTTP details—for example, to check how many requests remain in your billing-period quota—call .withResponse() on the request. It returns data, the same typed result, and response, the native Response with its status and headers. It does not make a second API request.
const { data, response } = await client.companies
.get({ ticker: "AAPL" })
.withResponse();
console.log(data.company.name);
console.log(response.headers.get("x-billing-period-quota-remaining"));Quota and rate-limit headers
| Header | Meaning | When it appears |
|---|---|---|
X-Billing-Period-Quota-Limit | Total requests available in the current billing period | Successful billed requests and billing-period quota errors |
X-Billing-Period-Quota-Remaining | Requests remaining after the current request | Successful billed requests and billing-period quota errors |
X-Billing-Period-Quota-Reset | Time when the billing-period quota resets | Successful billed requests and billing-period quota errors |
Retry-After | Seconds to wait before retrying | Rate-limit and billing-period quota errors |
RateLimit-Limit | Requests allowed in the short rate-limit window | Short-window rate-limit errors |
RateLimit-Reset | Seconds until the short rate-limit window resets | Short-window rate-limit errors |
The API reference shows any additional headers returned by a specific endpoint.
