A comprehensive Node.js client library for the Apple Search Ads API, supporting campaigns, ad groups, keywords, reporting, and more.
- âś… Full support for Apple Search Ads API v3, v4, and v5
- âś… OAuth authentication with automatic token management
- âś… Certificate-based authentication (v3)
- âś… Comprehensive endpoint coverage:
- Campaigns management
- Ad Groups with targeting dimensions
- Keywords (targeting and negative)
- Ads management
- Reporting (campaigns, ad groups, keywords, search terms)
- Geo search
- Product pages
- Budget orders
- âś… Automatic pagination support
- âś… CLI tool for testing and automation
- âś… TypeScript-friendly (JSDoc annotations)
- âś… Verbose logging option for debugging
npm install applesearchads-api-nodeCreate a .env file in your project root:
# Your organization ID (required)
ORG_ID=your_org_id
# API Credentials for OAuth (required for v4/v5)
CLIENT_ID=SEARCHADS.your-client-id
TEAM_ID=SEARCHADS.your-team-id
KEY_ID=your-key-id
# Certificate files
PEM_FILE=private-key.p8
KEY_FILE=private-key.p8
# Certificate directory path (optional, defaults to current directory)
CERTIFICATES_DIR_PATH=./
# API Version (v3, v4, or v5 - default: v5)
API_VERSION=v5
# Verbose logging (true/false)
VERBOSE=false- Log in to App Store Connect
- Navigate to Users and Access > Keys
- Create a new API key with Apple Search Ads access
- Download the private key (.p8 file)
- Note your Key ID, Team ID, and Client ID
- Generate a certificate and private key
- Upload the certificate to App Store Connect
- Configure the PEM and KEY file paths in
.env
const SearchAdsAPI = require('applesearchads-api-node');
const api = new SearchAdsAPI();
// Get all campaigns
const campaigns = await api.getCampaigns();
console.log(campaigns);
// Get a specific campaign
const campaign = await api.getCampaign(campaignId);
// Get campaign report
const report = await api.getCampaignsReportByDate(
'2024-01-01',
'2024-01-31'
);const api = new SearchAdsAPI({
orgId: 'your_org_id',
clientId: 'your_client_id',
teamId: 'your_team_id',
keyId: 'your_key_id',
keyFile: 'path/to/private-key.p8',
certificatesDir: './certs/',
apiVersion: 'v5',
verbose: true
});// Create a campaign
await api.createCampaign(adamId, countries, name, budget, dailyBudget, currency);
// Find campaigns with conditions
await api.findCampaigns(sortField, sortOrder, conditions, limit, offset);
// Get all campaigns (with auto-pagination)
await api.getCampaigns(limit, offset);
// Get a specific campaign
await api.getCampaign(campaignId);
// Update a campaign
await api.updateCampaign(campaignId, countries, name, budget, dailyBudget, currency, status, adamId);
// Delete a campaign
await api.deleteCampaign(campaignId);// Create an ad group
await api.createAdgroup(
campaignId,
name,
currency,
cpcBid,
startTime,
endTime,
cpaGoal,
automatedKeywordsOptIn,
age,
gender,
deviceClass,
dayPart,
adminArea,
locality,
appDownloaders
);
// Get all ad groups for a campaign
await api.getAdgroups(campaignId, limit, offset);
// Get a specific ad group
await api.getAdgroup(campaignId, adgroupId);
// Update an ad group
await api.updateAdgroup(campaignId, adgroupId, ...options);
// Delete an ad group
await api.deleteAdgroup(campaignId, adgroupId);// Add targeting keywords
const keywords = [
{
text: 'keyword',
matchType: 'BROAD',
bidAmount: { amount: '1.50', currency: 'USD' }
}
];
await api.addTargetingKeywords(campaignId, adgroupId, keywords);
// Get targeting keywords
await api.getTargetingKeywords(campaignId, adgroupId, limit, offset);
// Update targeting keywords
await api.updateTargetingKeywords(campaignId, adgroupId, keywords);
// Delete a targeting keyword
await api.deleteTargetingKeyword(campaignId, adgroupId, keywordId);// Campaign-level negative keywords
await api.addCampaignNegativeKeywords(campaignId, keywords);
await api.getCampaignNegativeKeywords(campaignId);
await api.updateCampaignNegativeKeywords(campaignId, keywords);
await api.deleteCampaignNegativeKeywords(campaignId, keywordIds);
// Ad group-level negative keywords
await api.addAdgroupNegativeKeywords(campaignId, adgroupId, keywords);
await api.getAdgroupNegativeKeywords(campaignId, adgroupId);
await api.updateAdgroupNegativeKeywords(campaignId, adgroupId, keywords);
await api.deleteAdgroupNegativeKeywords(campaignId, adgroupId, keywordIds);// Campaign reports
await api.getCampaignsReportByDate(
startDate,
endDate,
sortField,
sortOrder,
conditions,
groupBy,
returnRecordsWithNoMetrics,
returnRowTotals,
returnGrandTotals,
granularity,
offset,
limit
);
// Ad group reports
await api.getAdgroupsReportByDate(campaignId, startDate, endDate, ...options);
// Keyword reports
await api.getKeywordsReportByDate(campaignId, startDate, endDate, ...options);
// Search terms reports
await api.getSearchtermsReportByDate(campaignId, startDate, endDate, ...options);
// Ad-level reports
await api.getAdLevelReportByDate(campaignId, startDate, endDate, ...options);// Search for geographic locations
await api.geoSearch(word, entity, countryCode, limit, offset);
// Get admin areas for a country
await api.getAdminAreas(countryCode);
// Get localities for a country
await api.getLocalities(countryCode);The package includes a command-line interface for testing and automation.
npm install -g applesearchads-api-nodeOr use locally:
npm run start -- <command># List campaigns
searchads campaigns list
# Get a specific campaign
searchads campaigns get --id 123456
# Create a campaign
searchads campaigns create \
--app-id 123456 \
--countries US,GB \
--name "My Campaign" \
--budget 1000 \
--daily-budget 100 \
--currency USD
# List ad groups
searchads adgroups list --campaign-id 123456
# List keywords
searchads keywords list --campaign-id 123456 --adgroup-id 789012
# Get campaign reports
searchads reports campaigns \
--start-date 2024-01-01 \
--end-date 2024-01-31
# Get campaign reports with daily granularity
searchads reports campaigns \
-g DAILY \
--start-date 2024-01-01 \
--end-date 2024-01-31
# Get ad group reports
searchads reports adgroups \
--campaign-id 123456 \
--start-date 2024-01-01 \
--end-date 2024-01-31
# Get ad group reports with hourly granularity
searchads reports adgroups \
--campaign-id 123456 \
-g HOURLY \
--start-date 2024-01-01 \
--end-date 2024-01-01
# Geo search
searchads geo search --word "California" --country US --entity AdminArea
# Enable verbose logging
searchads -v campaigns listtry {
const campaigns = await api.getCampaigns();
} catch (error) {
console.error('API Error:', error.message);
}The library throws descriptive errors for:
- Authentication failures
- Invalid parameters
- API rate limiting
- Network issues
- Invalid responses
Many methods support automatic pagination when limit=0:
// Get ALL campaigns (auto-pagination)
const allCampaigns = await api.getCampaigns(0);
// Get first 100 campaigns only
const someCampaigns = await api.getCampaigns(100);Enable verbose logging to see all API requests and responses:
const api = new SearchAdsAPI({ verbose: true });Or via environment variable:
VERBOSE=trueOr via CLI:
searchads -v campaigns list- v5 (recommended): Latest version with all features
- v4: OAuth authentication
- v3: Certificate-based authentication (legacy)
MIT
Contributions are welcome! Please open an issue or submit a pull request.
For questions or issues:
- Check the Apple Search Ads API documentation
- Open an issue on GitHub
- Review existing issues and discussions
Based on the Python implementation: https://github.com/phiture/searchads_api