yandex-direct-api-sdk
v0.1.0
Published
TypeScript SDK for Yandex Direct API v5
Maintainers
Readme
Yandex Direct API SDK (TypeScript)
Typed SDK for Yandex Direct API v5.
It provides:
- strongly typed request/response models for supported services,
- a single
YandexDirectClientwith service-specific methods, - pagination and money helpers,
- consistent error handling with request id and units metadata.
Highlights
- Strict TypeScript models for API payloads (
add,update,get, lifecycle methods). - Service-oriented client API (
client.campaigns.get(...),client.ads.update(...), etc.). - Built-in transport for production and sandbox endpoints.
- Useful metadata on each response:
requestIdand parsedUnitsheader. - Typed API errors via
YandexDirectApiErrorwithisRetriablehelper.
Scope
- In scope: Yandex Direct JSON API v5 at
https://api.direct.yandex.com/json/v5(and the sandbox twin).- Most services use
POSTwith a JSON body{ method, params }as in the official reference. - The Reports (statistics) service is supported via
client.reports.getReport(...)and returns TSV/plain text.
- Most services use
- Out of scope (for now): the SOAP/XML Live API, and any endpoint that is not reachable via the standard
json/v5base path. Some docs mention alternate API versions for specific flows (for examplev501for product ads); those calls are not routed by this client unless you add a custom transport / rewrite. - Finance: use
paymentTokenin client config when the method requires thePayment-Tokenheader (see Yandex Direct headers documentation).
Installation
npm install yandex-direct-api-sdkExamples (from the repository)
Runnable samples live under examples/: campaigns-basic, reports-basic, agency-basic. Each has its own package.json and links the SDK with file:../.. — run bun run build at the repo root first, then bun install inside an example folder.
Quick Start
import { YandexDirectClient } from 'yandex-direct-api-sdk';
const client = new YandexDirectClient({
token: process.env.YANDEX_DIRECT_TOKEN!,
language: 'en', // optional, default: 'en'
// clientLogin: 'agency-client-login', // optional (for agency calls)
// useOperatorUnits: true, // optional
// apiVersion: 'v501', // optional for endpoints documented on v501
// sandbox: true, // optional
});
const response = await client.campaigns.get({
SelectionCriteria: { Ids: [123456789] },
FieldNames: ['Id', 'Name', 'State', 'Status'],
});
console.log(response.requestId);
console.log(response.units); // { spent, remaining, dailyLimit } | undefined
console.log(response.result.Campaigns);Configuration
YandexDirectClient accepts:
token(required): OAuth token.language(optional):'ru' | 'en'.clientLogin(optional): advertiser login for agency workflows.useOperatorUnits(optional): use operator units instead of advertiser units.paymentToken(optional): finance token for finance API methods (Payment-Tokenheader).acceptGzip(optional): setAccept-Encoding: gzipon requests.extraHeaders(optional): additional headers (cannot override auth, content type, language, agency headers, orPayment-Token).sandbox(optional): use sandbox endpoint.apiVersion(optional): JSON API version path ('v5'default,'v501'for endpoints documented on v501).fetch(optional): custom fetch implementation (useful for tests).maxRetries/retryDelayMs(optional): retry retriable API/HTTP/network failures.
Recipes
Campaigns only
const { result } = await client.campaigns.get({
SelectionCriteria: { Ids: [123456789] },
FieldNames: ['Id', 'Name', 'State', 'Status'],
});
console.log(result.Campaigns);Agency (client login + agency APIs)
Use the advertiser login in config, then call agency-scoped services as documented by Yandex.
const agencyClient = new YandexDirectClient({
token: process.env.YANDEX_DIRECT_TOKEN!,
clientLogin: 'advertiser-login', // sub-client under the agency token
});
const clients = await agencyClient.agencyclients.get({
SelectionCriteria: {},
FieldNames: ['Login', 'CountryId'] as const,
});
const report = await agencyClient.reports.getReport(
{
SelectionCriteria: {
Filter: [{ Field: 'CampaignId', Operator: 'IN', Values: ['10002'] }],
},
FieldNames: ['Date', 'CampaignId', 'Clicks', 'Cost'] as const,
ReportName: 'Agency stats',
ReportType: 'CAMPAIGN_PERFORMANCE_REPORT',
DateRangeType: 'LAST_7_DAYS',
Format: 'TSV',
IncludeVAT: 'YES',
},
{ processingMode: 'auto' },
);Reports only (statistics TSV)
If the rest of your stack talks to Direct elsewhere, you can still use this SDK only for reports — instantiate YandexDirectClient and call client.reports.requestReport / getReport with the same config (token, sandbox, clientLogin, apiVersion as needed).
Reports (statistics)
Use client.reports.getReport(...) to request Direct statistics reports. The SDK sends a JSON body to the reports service and parses the TSV response.
const report = await client.reports.getReport({
SelectionCriteria: {
Filter: [
{ Field: 'CampaignId', Operator: 'IN', Values: ['10002', '10007'] },
],
},
FieldNames: ['Date', 'CampaignId', 'Clicks', 'Cost'] as const,
ReportName: 'Actual Data',
ReportType: 'CAMPAIGN_PERFORMANCE_REPORT',
DateRangeType: 'AUTO',
Format: 'TSV',
IncludeVAT: 'YES',
// IncludeDiscount is optional (deprecated by Yandex docs)
// IncludeDiscount: 'YES',
});
console.log(report.rows[0].Clicks); // stringNotes:
IncludeDiscountis optional and deprecated by Yandex.returnMoneyInMicrosrequest option follows Yandex semantics:false-> sends headerreturnMoneyInMicros: falsetrue/undefined-> does not send this header (default API behavior, values in micros)
Offline / queue flow example:
const pendingOrReport = await client.reports.requestReport(
{
SelectionCriteria: {
Filter: [{ Field: 'CampaignId', Operator: 'IN', Values: ['10002'] }],
},
FieldNames: ['Date', 'CampaignId', 'Clicks'] as const,
ReportName: 'Queued report',
ReportType: 'CAMPAIGN_PERFORMANCE_REPORT',
DateRangeType: 'AUTO',
Format: 'TSV',
IncludeVAT: 'YES',
},
{ processingMode: 'offline' },
);
if ('status' in pendingOrReport) {
// 201/202: queued or still generating
// retryInSeconds is recommended polling interval from API (if provided)
console.log(pendingOrReport.status, pendingOrReport.retryInSeconds);
}The convenience helper client.reports.getReport(...) already polls automatically
for 201/202 responses and uses retryIn when available.
Validation note:
- The backend is the source of truth for Reports validation and incompatibilities.
- The SDK focuses on typing and transport behavior; server-side errors are surfaced as
YandexDirectApiError.
Typing note:
FieldNames,SelectionCriteria.Filter[].Field, andOrderBy[].Fieldare constrained byReportType(from Yandexfields-list). The mapping is generated intosrc/types/reports-field-mappings.generated.ts. After updatingapi-docs/.../fields-list.md, runbun run generate:report-fieldsand commit the regenerated file.
Error Handling
import { YandexDirectApiError } from 'yandex-direct-api-sdk';
try {
await client.ads.update({
Ads: [
{
Id: 111,
TextAd: { Title: 'New title' },
},
],
});
} catch (error) {
if (error instanceof YandexDirectApiError) {
console.error(error.code, error.detail, error.requestId);
if (error.isRetriable) {
// retry logic
}
}
throw error;
}Pagination Helper
Use paginate for get methods that support Page.
import { paginate } from 'yandex-direct-api-sdk';
for await (const page of paginate(
(params) => client.ads.get(params),
{
SelectionCriteria: { CampaignIds: [123456789] },
FieldNames: ['Id', 'AdGroupId', 'CampaignId'],
},
{ limit: 10_000 },
)) {
console.log(page.result.Ads.length);
}Money Helpers
Yandex Direct monetary fields are often represented in micros (x 1,000,000).
import { toMicros, fromMicros } from 'yandex-direct-api-sdk';
const apiValue = toMicros(12.34); // 12340000
const human = fromMicros(apiValue); // 12.34Client ↔ JSON service (cheat sheet)
Each property maps to POST https://api.direct.yandex.com/json/v5/{service} (or sandbox / v501 when configured):
| YandexDirectClient property | JSON service segment |
|-------------------------------|-------------------------|
| adGroups | adgroups |
| ads | ads |
| adImages | adimages |
| advideos | advideos |
| adExtensions | adextensions |
| agencyclients | agencyclients |
| audiencetargets | audiencetargets |
| bidmodifiers | bidmodifiers |
| bids | bids |
| businesses | businesses |
| campaigns | campaigns |
| changes | changes |
| clients | clients |
| creatives | creatives |
| dictionaries | dictionaries |
| feeds | feeds |
| keywords | keywords |
| keywordbids | keywordbids |
| keywordsresearch | keywordsresearch |
| leads | leads |
| negativeKeywordSharedSets | negativekeywordsharedsets |
| reports | reports |
| retargetingLists | retargetinglists |
| sitelinks | sitelinks |
| strategies | strategies |
| turbopages | turbopages |
Development
bun install
bun run typecheck
bun test
bun run build
# Regenerate Reports field unions from api-docs (optional; commit the output)
bun run generate:report-fields- CI: GitHub Actions runs
typecheck,test, andbuildon pushes and pull requests tomain/master. You can also run the workflow manually (Actions → CI → Run workflow). - Contributing / doc updates: see CONTRIBUTING.md.
