@adkit/cli 1.13.26 → 1.13.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +450 -45
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -44,7 +44,7 @@ adkit projects current
44
44
  Browse competitor ads and advertisers tracked by AdKit.
45
45
 
46
46
  ```bash
47
- adkit library advertisers list --search "notion" --platform meta
47
+ adkit library advertisers search "notion" --platform meta
48
48
  adkit library advertisers <id>
49
49
  adkit library advertisers similar --industry saas
50
50
  adkit library ads list --advertiser <id>
package/dist/cli.js CHANGED
@@ -3519,10 +3519,25 @@ var AD_GROUP_UPDATE_FLAGS2 = ["name", "status", "budget-daily", "budget-lifetime
3519
3519
  var AD_UPDATE_FLAGS2 = ["name", "status"];
3520
3520
  var TARGETING_SEARCH_FLAGS = ["account", "facet", "query", "limit"];
3521
3521
  var RESULTS_FLAGS2 = ["level", "period", "fields", "breakdowns", "from", "to", "sort", "limit", "offset"];
3522
+ async function listLinkedInAccounts(client, _args, flags) {
3523
+ validateFlags(flags, [], "manage linkedin accounts list");
3524
+ return client.get("/manage/linkedin/accounts");
3525
+ }
3522
3526
  async function listLinkedInAvailableAccounts(client, _args, flags) {
3523
3527
  validateFlags(flags, [], "manage linkedin accounts available");
3524
3528
  return client.get("/manage/linkedin/accounts/available");
3525
3529
  }
3530
+ async function connectLinkedInAccount(client, args, flags) {
3531
+ validateFlags(flags, ["integration"], "manage linkedin accounts connect");
3532
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage linkedin accounts connect <account-id>");
3533
+ const integrationId = typeof flags.integration === "string" ? flags.integration : void 0;
3534
+ return client.post("/manage/linkedin/accounts/connect", { accountId, ...integrationId ? { integrationId } : {} });
3535
+ }
3536
+ async function disconnectLinkedInAccount(client, args, flags) {
3537
+ validateFlags(flags, [], "manage linkedin accounts disconnect");
3538
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage linkedin accounts disconnect <account-id>");
3539
+ return client.delete(`/manage/linkedin/accounts/${accountId}`);
3540
+ }
3526
3541
  async function uploadLinkedInMedia(client, _args, flags) {
3527
3542
  validateFlags(flags, MEDIA_UPLOAD_FLAGS3, "manage linkedin media upload");
3528
3543
  if (typeof flags.data === "string") {
@@ -3811,13 +3826,170 @@ function buildLinkedInMediaUploadSource(flags) {
3811
3826
  return source;
3812
3827
  }
3813
3828
 
3829
+ // src/commands/x.ts
3830
+ var CAMPAIGN_LIST_FLAGS4 = ["campaign-ids", "status", "limit", "offset"];
3831
+ var AD_GROUP_LIST_FLAGS4 = ["campaign-ids", "ad-group-ids", "status", "limit", "offset"];
3832
+ var AD_LIST_FLAGS4 = ["campaign-ids", "ad-group-ids", "ad-ids", "status", "limit", "offset"];
3833
+ var RESULTS_FLAGS3 = ["level", "from", "to", "fields", "breakdowns", "campaign-ids", "ad-group-ids", "ad-ids", "sort", "sort-direction", "limit", "offset", "raw"];
3834
+ async function listXAccounts(client, _args, flags) {
3835
+ validateFlags(flags, [], "manage x accounts list");
3836
+ return client.get("/manage/x/accounts");
3837
+ }
3838
+ async function listXAvailableAccounts(client, _args, flags) {
3839
+ validateFlags(flags, [], "manage x accounts available");
3840
+ return client.get("/manage/x/accounts/available");
3841
+ }
3842
+ async function connectXAccount(client, args, flags) {
3843
+ validateFlags(flags, ["integration"], "manage x accounts connect");
3844
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage x accounts connect <account-id>");
3845
+ const integrationId = typeof flags.integration === "string" ? flags.integration : void 0;
3846
+ return client.post("/manage/x/accounts/connect", { accountId, ...integrationId ? { integrationId } : {} });
3847
+ }
3848
+ async function disconnectXAccount(client, args, flags) {
3849
+ validateFlags(flags, [], "manage x accounts disconnect");
3850
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage x accounts disconnect <account-id>");
3851
+ return client.delete(`/manage/x/accounts/${accountId}`);
3852
+ }
3853
+ async function listXProfiles(client, args, flags) {
3854
+ validateFlags(flags, [], "manage x accounts <account-id> profiles");
3855
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage x accounts <account-id> profiles");
3856
+ return client.get(`/manage/x/accounts/${accountId}/profiles`);
3857
+ }
3858
+ async function listXPixels(client, args, flags) {
3859
+ validateFlags(flags, [], "manage x accounts <account-id> pixels");
3860
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage x accounts <account-id> pixels");
3861
+ return client.get(`/manage/x/accounts/${accountId}/pixels`);
3862
+ }
3863
+ async function updateXAccount(client, args, flags) {
3864
+ validateFlags(flags, ["default-profile", "default-pixel"], "manage x accounts <account-id> update");
3865
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage x accounts <account-id> update --default-profile <profile-id>");
3866
+ if (typeof flags.data === "string") {
3867
+ const body = parseDataFlag(flags, 'Use { "defaultProfileId": "...", "defaultPixelId": "..." }');
3868
+ return client.patch(`/manage/x/accounts/${accountId}`, body);
3869
+ }
3870
+ const defaultProfileId = typeof flags["default-profile"] === "string" ? flags["default-profile"] : void 0;
3871
+ const defaultPixelId = typeof flags["default-pixel"] === "string" ? flags["default-pixel"] : void 0;
3872
+ if (!defaultProfileId && !defaultPixelId) throw new CliError("MISSING_FLAG", "Nothing to update", "Pass --default-profile, --default-pixel, or --data");
3873
+ return client.patch(`/manage/x/accounts/${accountId}`, {
3874
+ ...defaultProfileId ? { defaultProfileId } : {},
3875
+ ...defaultPixelId ? { defaultPixelId } : {}
3876
+ });
3877
+ }
3878
+ async function listXCampaigns(client, _args, flags) {
3879
+ validateXReadFlags(flags, CAMPAIGN_LIST_FLAGS4, "manage x campaigns list");
3880
+ const query = buildXListQuery(flags, ["campaign-ids"]);
3881
+ return client.get(`/manage/x/campaigns${query}`);
3882
+ }
3883
+ async function getXCampaign(client, args, flags) {
3884
+ validateXReadFlags(flags, [], "manage x campaigns get");
3885
+ const campaignId = requireArg(args, 0, "campaign-id", "Run: adkit manage x campaigns get <campaign-id>");
3886
+ const query = queryString({ accountId: typeof flags.account === "string" ? flags.account : void 0 });
3887
+ return client.get(`/manage/x/campaigns/${campaignId}${query}`);
3888
+ }
3889
+ async function listXAdGroups(client, _args, flags) {
3890
+ validateXReadFlags(flags, AD_GROUP_LIST_FLAGS4, "manage x ad-groups list");
3891
+ const query = buildXListQuery(flags, ["campaign-ids", "ad-group-ids"]);
3892
+ return client.get(`/manage/x/ad-groups${query}`);
3893
+ }
3894
+ async function getXAdGroup(client, args, flags) {
3895
+ validateXReadFlags(flags, [], "manage x ad-groups get");
3896
+ const adGroupId = requireArg(args, 0, "ad-group-id", "Run: adkit manage x ad-groups get <ad-group-id>");
3897
+ const query = queryString({ accountId: typeof flags.account === "string" ? flags.account : void 0 });
3898
+ return client.get(`/manage/x/ad-groups/${adGroupId}${query}`);
3899
+ }
3900
+ async function listXAds(client, _args, flags) {
3901
+ validateXReadFlags(flags, AD_LIST_FLAGS4, "manage x ads list");
3902
+ const query = buildXListQuery(flags, ["campaign-ids", "ad-group-ids", "ad-ids"]);
3903
+ return client.get(`/manage/x/ads${query}`);
3904
+ }
3905
+ async function getXAd(client, args, flags) {
3906
+ validateXReadFlags(flags, [], "manage x ads get");
3907
+ const adId = requireArg(args, 0, "ad-id", "Run: adkit manage x ads get <ad-id>");
3908
+ const query = queryString({ accountId: typeof flags.account === "string" ? flags.account : void 0 });
3909
+ return client.get(`/manage/x/ads/${adId}${query}`);
3910
+ }
3911
+ async function listXResults(client, _args, flags) {
3912
+ validateXReadFlags(flags, RESULTS_FLAGS3, "manage x results");
3913
+ const level = requireFlag(flags, "level", "Use --level campaigns, ad-groups, or ads");
3914
+ const from = requireFlag(flags, "from", "Use --from YYYY-MM-DD with --to");
3915
+ const to = requireFlag(flags, "to", "Use --to YYYY-MM-DD with --from");
3916
+ const raw = flags.raw === true ? "true" : typeof flags.raw === "string" ? flags.raw : void 0;
3917
+ const query = queryString({
3918
+ accountId: typeof flags.account === "string" ? flags.account : void 0,
3919
+ level,
3920
+ from,
3921
+ to,
3922
+ fields: typeof flags.fields === "string" ? flags.fields : void 0,
3923
+ breakdowns: typeof flags.breakdowns === "string" ? flags.breakdowns : void 0,
3924
+ campaignIds: typeof flags["campaign-ids"] === "string" ? flags["campaign-ids"] : void 0,
3925
+ adGroupIds: typeof flags["ad-group-ids"] === "string" ? flags["ad-group-ids"] : void 0,
3926
+ adIds: typeof flags["ad-ids"] === "string" ? flags["ad-ids"] : void 0,
3927
+ sort: typeof flags.sort === "string" ? flags.sort : void 0,
3928
+ sortDirection: typeof flags["sort-direction"] === "string" ? flags["sort-direction"] : void 0,
3929
+ limit: typeof flags.limit === "string" ? flags.limit : void 0,
3930
+ offset: typeof flags.offset === "string" ? flags.offset : void 0,
3931
+ raw
3932
+ });
3933
+ return client.get(`/manage/x/results${query}`);
3934
+ }
3935
+ function buildXListQuery(flags, filterKeys) {
3936
+ return queryString({
3937
+ accountId: typeof flags.account === "string" ? flags.account : void 0,
3938
+ campaignIds: filterKeys.includes("campaign-ids") && typeof flags["campaign-ids"] === "string" ? flags["campaign-ids"] : void 0,
3939
+ adGroupIds: filterKeys.includes("ad-group-ids") && typeof flags["ad-group-ids"] === "string" ? flags["ad-group-ids"] : void 0,
3940
+ adIds: filterKeys.includes("ad-ids") && typeof flags["ad-ids"] === "string" ? flags["ad-ids"] : void 0,
3941
+ status: typeof flags.status === "string" ? flags.status : void 0,
3942
+ limit: typeof flags.limit === "string" ? flags.limit : void 0,
3943
+ offset: typeof flags.offset === "string" ? flags.offset : void 0
3944
+ });
3945
+ }
3946
+ function validateXReadFlags(flags, allowed, command) {
3947
+ const permitted = /* @__PURE__ */ new Set(["account", "json", "project", ...allowed]);
3948
+ const unsupported = Object.keys(flags).filter((flag) => !permitted.has(flag));
3949
+ if (!unsupported.length) return;
3950
+ const renderedFlags = unsupported.map((flag) => `--${flag}`).join(", ");
3951
+ throw new CliError("UNKNOWN_FLAG", `Unknown flag${unsupported.length > 1 ? "s" : ""}: ${renderedFlags}`, `Run: adkit ${command} --help`);
3952
+ }
3953
+
3814
3954
  // src/commands/microsoft.ts
3955
+ async function listMicrosoftAccounts(client, _args, flags) {
3956
+ validateFlags(flags, [], "manage microsoft accounts list");
3957
+ return client.get("/manage/microsoft/accounts");
3958
+ }
3815
3959
  async function listMicrosoftAvailableAccounts(client, _args, flags) {
3816
3960
  validateFlags(flags, [], "manage microsoft accounts available");
3817
3961
  return client.get("/manage/microsoft/accounts/available");
3818
3962
  }
3963
+ async function connectMicrosoftAccount(client, args, flags) {
3964
+ validateFlags(flags, ["integration"], "manage microsoft accounts connect");
3965
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage microsoft accounts connect <account-id>");
3966
+ const integrationId = typeof flags.integration === "string" ? flags.integration : void 0;
3967
+ return client.post("/manage/microsoft/accounts/connect", { accountId, ...integrationId ? { integrationId } : {} });
3968
+ }
3969
+ async function disconnectMicrosoftAccount(client, args, flags) {
3970
+ validateFlags(flags, [], "manage microsoft accounts disconnect");
3971
+ const accountId = requireArg(args, 0, "account-id", "Run: adkit manage microsoft accounts disconnect <account-id>");
3972
+ return client.delete(`/manage/microsoft/accounts/${accountId}`);
3973
+ }
3819
3974
 
3820
3975
  // src/commands/status.ts
3976
+ var STATUS_PLATFORMS = [
3977
+ ["meta", "Meta"],
3978
+ ["google", "Google"],
3979
+ ["tiktok", "TikTok"],
3980
+ ["reddit", "Reddit"],
3981
+ ["x", "X"],
3982
+ ["linkedin", "LinkedIn"],
3983
+ ["microsoft", "Microsoft"]
3984
+ ];
3985
+ var DEFAULT_LABELS = {
3986
+ identityId: "Identity",
3987
+ identityType: "Identity type",
3988
+ instagramUserId: "Instagram user",
3989
+ pageId: "Page",
3990
+ pixelId: "Pixel",
3991
+ profileId: "Profile"
3992
+ };
3821
3993
  function isStatusResponse(value) {
3822
3994
  if (!value || typeof value !== "object") return false;
3823
3995
  if (!("connected" in value) || typeof value.connected !== "boolean") return false;
@@ -3831,28 +4003,32 @@ async function status(client, json) {
3831
4003
  if (!isStatusResponse(response)) throw new Error("Unexpected response from AdKit status");
3832
4004
  const data = response;
3833
4005
  if (json) {
3834
- console.log(JSON.stringify(data));
4006
+ const serializedStatus = JSON.stringify(data);
4007
+ console.log(serializedStatus);
3835
4008
  return;
3836
4009
  }
3837
4010
  const { project, platforms } = data;
3838
4011
  const lines = [];
3839
4012
  lines.push(`Project: ${project.name || "unnamed"} (${project.id})`);
3840
4013
  lines.push("");
3841
- if (platforms.meta.connected) {
3842
- lines.push("Meta: connected");
3843
- for (const a of platforms.meta.accounts) {
3844
- lines.push(` ${a.id} \u2014 ${a.name} (${a.currency}, ${a.status})`);
3845
- if (a.defaults.pageId) lines.push(` Page: ${a.defaults.pageId}`);
3846
- if (a.defaults.pixelId) lines.push(` Pixel: ${a.defaults.pixelId}`);
4014
+ for (const [platformKey, label] of STATUS_PLATFORMS) {
4015
+ const platform2 = platforms[platformKey];
4016
+ if (!platform2.connected) {
4017
+ lines.push(`${label}: not connected`);
4018
+ continue;
4019
+ }
4020
+ lines.push(`${label}: connected`);
4021
+ for (const account of platform2.accounts) {
4022
+ const details = [account.currency, account.status].filter(Boolean).join(", ");
4023
+ lines.push(` ${account.id}${account.name ? ` \u2014 ${account.name}` : ""}${details ? ` (${details})` : ""}`);
4024
+ const defaults = Object.entries(account.defaults ?? {});
4025
+ for (const [key, value] of defaults) if (value) lines.push(` ${DEFAULT_LABELS[key] ?? key}: ${value}`);
3847
4026
  }
3848
- } else lines.push("Meta: not connected");
3849
- if (platforms.google.connected) {
3850
- lines.push("Google: connected");
3851
- for (const a of platforms.google.accounts) lines.push(` ${a.id} \u2014 ${a.name} (${a.currency})`);
3852
- } else lines.push("Google: not connected");
4027
+ }
3853
4028
  lines.push("");
3854
4029
  lines.push(data.instructions);
3855
- console.log(lines.join("\n"));
4030
+ const output = lines.join("\n");
4031
+ console.log(output);
3856
4032
  }
3857
4033
 
3858
4034
  // src/commands/drafts.ts
@@ -3935,15 +4111,17 @@ function readStringFlag(flags, key) {
3935
4111
  const value = flags[key];
3936
4112
  return typeof value === "string" ? value : void 0;
3937
4113
  }
4114
+ var ADVERTISER_FILTER_FLAGS = ["industry", "category", "platform", "sort", "limit", "page"];
3938
4115
  async function listAdvertisers(client, _args, flags) {
3939
- const industry = typeof flags.industry === "string" ? flags.industry : void 0;
3940
- const category = typeof flags.category === "string" ? flags.category : void 0;
3941
- const platform2 = typeof flags.platform === "string" ? flags.platform : void 0;
3942
- const search = typeof flags.search === "string" ? flags.search : void 0;
3943
- const sort = typeof flags.sort === "string" ? flags.sort : "name";
3944
- const limit = typeof flags.limit === "string" ? flags.limit : void 0;
3945
- const page = typeof flags.page === "string" ? flags.page : void 0;
3946
- const qs = queryString3({ industry, category, platform: platform2, search, sort, limit, page });
4116
+ validateFlags(flags, ADVERTISER_FILTER_FLAGS, "library advertisers list");
4117
+ const qs = buildAdvertiserQueryString(flags);
4118
+ return client.get(`/library/advertisers${qs}`);
4119
+ }
4120
+ async function searchAdvertisers(client, args, flags) {
4121
+ validateFlags(flags, ADVERTISER_FILTER_FLAGS, "library advertisers search");
4122
+ const query = args.join(" ").trim();
4123
+ if (!query) throw new CliError("MISSING_ARGUMENT", "Missing advertiser search query", "Run: adkit library advertisers search <query>");
4124
+ const qs = buildAdvertiserQueryString(flags, query);
3947
4125
  return client.get(`/library/advertisers${qs}`);
3948
4126
  }
3949
4127
  async function getAdvertiser(client, args, _flags) {
@@ -3975,6 +4153,15 @@ async function addAdvertiser(client, _args, flags) {
3975
4153
  linkedInLibraryUrl: linkedinLibrary
3976
4154
  });
3977
4155
  }
4156
+ function buildAdvertiserQueryString(flags, query) {
4157
+ const industry = typeof flags.industry === "string" ? flags.industry : void 0;
4158
+ const category = typeof flags.category === "string" ? flags.category : void 0;
4159
+ const platform2 = typeof flags.platform === "string" ? flags.platform : void 0;
4160
+ const sort = typeof flags.sort === "string" ? flags.sort : "name";
4161
+ const limit = typeof flags.limit === "string" ? flags.limit : void 0;
4162
+ const page = typeof flags.page === "string" ? flags.page : void 0;
4163
+ return queryString3({ industry, category, platform: platform2, query, sort, limit, page });
4164
+ }
3978
4165
  async function listLibraryAds(client, _args, flags) {
3979
4166
  const platform2 = readStringFlag(flags, "platform");
3980
4167
  const status2 = readStringFlag(flags, "status");
@@ -4860,7 +5047,9 @@ Manage platforms:
4860
5047
  google Google Ads
4861
5048
  tiktok TikTok Ads
4862
5049
  reddit Reddit Ads
5050
+ x X Ads
4863
5051
  linkedin LinkedIn Ads
5052
+ microsoft Microsoft Ads
4864
5053
  drafts Drafts across platforms
4865
5054
 
4866
5055
  Run \`adkit <command> --help\` for details.
@@ -6748,9 +6937,9 @@ Platforms:
6748
6937
  google Google Ads
6749
6938
  tiktok TikTok Ads
6750
6939
  reddit Reddit Ads
6751
- x X Ads raw API access
6940
+ x X account setup plus read-only campaigns, ad groups, ads, and results
6752
6941
  linkedin LinkedIn Ads (campaigns, ad groups, ads, targeting, results)
6753
- microsoft Microsoft Ads raw API access + account discovery
6942
+ microsoft Microsoft Ads raw API access + account setup
6754
6943
  drafts Manage drafts across platforms
6755
6944
  platform-api-requests Send raw API requests (escape hatch)
6756
6945
 
@@ -6836,18 +7025,122 @@ General flags:
6836
7025
  ${FLAG.account}
6837
7026
 
6838
7027
  Run adkit manage reddit accounts --help for account setup.`.trim(),
6839
- x: `adkit manage x \u2014 X Ads raw API access
7028
+ x: `adkit manage x \u2014 X Ads management
6840
7029
 
6841
- X is currently exposed through Advanced Platform Access only.
6842
- Use platform-api-requests with official X Ads API endpoint paths.
7030
+ Entity groups:
7031
+ accounts Connect accounts and configure profile/pixel defaults
7032
+ campaigns List/get campaigns
7033
+ ad-groups List/get line items as ad groups
7034
+ ads List/get promoted-Post associations
7035
+ results Campaign, ad-group, and ad performance
6843
7036
 
6844
7037
  ${rawPlatformCommandLine("x")}
6845
7038
 
6846
7039
  Examples:
6847
- adkit manage platform-api-requests --platform x --endpoint "accounts/18ce54d4x5t/campaigns" --method GET --request-description "List X campaigns" --account 18ce54d4x5t`.trim(),
6848
- microsoft: `adkit manage microsoft \u2014 Microsoft Ads raw API access + account discovery
7040
+ adkit manage x accounts available
7041
+ adkit manage x campaigns list --account 18ce54d4x5t
7042
+ adkit manage x results --level ads --from 2026-08-01 --to 2026-08-07 --account 18ce54d4x5t`.trim(),
7043
+ "x accounts": `adkit manage x accounts \u2014 X Ads accounts
7044
+
7045
+ list List connected X ad accounts
7046
+ available List discoverable X ad accounts
7047
+ connect <id> Connect an X ad account
7048
+ disconnect <id> Disconnect an X ad account
7049
+ <id> profiles List X identities available to an account
7050
+ <id> pixels List X conversion pixels available to an account
7051
+ <id> update Save default identity and pixel IDs
6849
7052
 
6850
- Microsoft (Bing) is currently exposed through Advanced Platform Access, plus account discovery.
7053
+ Flags:
7054
+ --integration <id> Connect using a specific workspace login returned by available
7055
+ --default-profile <id> Default X identity for ad creation
7056
+ --default-pixel <id> Default X conversion pixel
7057
+ --data <json> Full update body; also supports null to clear a default
7058
+
7059
+ Examples:
7060
+ adkit manage x accounts list
7061
+ adkit manage x accounts available
7062
+ adkit manage x accounts connect 18ce54d4x5t
7063
+ adkit manage x accounts 18ce54d4x5t profiles
7064
+ adkit manage x accounts 18ce54d4x5t pixels
7065
+ adkit manage x accounts 18ce54d4x5t update --default-profile 12abc --default-pixel p123
7066
+ adkit manage x accounts disconnect 18ce54d4x5t`.trim(),
7067
+ "x campaigns": `adkit manage x campaigns \u2014 X Ads campaigns (read-only)
7068
+
7069
+ list List campaigns
7070
+ get <id> Get one campaign
7071
+
7072
+ Flags:
7073
+ ${FLAG.account}
7074
+ --campaign-ids <ids> Comma-separated campaign platform IDs
7075
+ --status <s> active, paused, or removed
7076
+ --limit <n> Max rows
7077
+ --offset <n> Row offset
7078
+
7079
+ Example:
7080
+ adkit manage x campaigns list --status active
7081
+ adkit manage x campaigns get 8v7jo`.trim(),
7082
+ "x ad-groups": `adkit manage x ad-groups \u2014 X line items as AdKit ad groups (read-only)
7083
+
7084
+ list List ad groups
7085
+ get <id> Get one ad group
7086
+
7087
+ Flags:
7088
+ ${FLAG.account}
7089
+ --campaign-ids <ids> Comma-separated parent campaign IDs
7090
+ --ad-group-ids <ids> Comma-separated line-item IDs
7091
+ --status <s> active, paused, or removed
7092
+ --limit <n> Max rows
7093
+ --offset <n> Row offset
7094
+
7095
+ Example:
7096
+ adkit manage x ad-groups list --campaign-ids 8v7jo`.trim(),
7097
+ "x ads": `adkit manage x ads \u2014 X promoted-Post ads (read-only)
7098
+
7099
+ list List promoted-Post ads
7100
+ get <id> Get one ad by promoted association ID
7101
+
7102
+ Identity:
7103
+ platformId is the promoted association ID used by X Ads and analytics. postId is the underlying Post ID.
7104
+
7105
+ Flags:
7106
+ ${FLAG.account}
7107
+ --campaign-ids <ids> Comma-separated parent campaign IDs
7108
+ --ad-group-ids <ids> Comma-separated parent line-item IDs
7109
+ --ad-ids <ids> Comma-separated promoted association IDs
7110
+ --status <s> active, paused, or removed
7111
+ --limit <n> Max rows
7112
+ --offset <n> Row offset
7113
+
7114
+ Example:
7115
+ adkit manage x ads get 1efwlo`.trim(),
7116
+ "x results": `adkit manage x results \u2014 X Ads performance reporting (read-only)
7117
+
7118
+ list List reporting rows (list is optional)
7119
+
7120
+ Flags:
7121
+ ${FLAG.account}
7122
+ --level <level> Required: campaigns, ad-groups, or ads
7123
+ --from <date> Required YYYY-MM-DD start
7124
+ --to <date> Required YYYY-MM-DD end
7125
+ --fields <csv> spend, impressions, clicks, ctr, cpc, cpm, outboundClicks, outboundCtr, costPerOutboundClick, videoViews
7126
+ --breakdowns <csv> day only
7127
+ --campaign-ids <ids> Campaign filters
7128
+ --ad-group-ids <ids> Ad-group filters
7129
+ --ad-ids <ids> Promoted association filters for level ads
7130
+ --sort <field> Metric to sort by (default: spend)
7131
+ --sort-direction <d> asc or desc
7132
+ --limit <n> Max rows
7133
+ --offset <n> Row offset
7134
+ --raw Include queried placements in platformDetails
7135
+
7136
+ Note:
7137
+ X does not name one primary Results metric, so rows omit metrics.results and return conversionEvents: {}.
7138
+
7139
+ Example:
7140
+ adkit manage x results --level ads --from 2026-08-01 --to 2026-08-07 --fields spend,impressions,clicks`.trim(),
7141
+ microsoft: `adkit manage microsoft \u2014 Microsoft Ads raw API access + account setup
7142
+
7143
+ Microsoft (Bing) is currently exposed through Advanced Platform Access, plus account assignment.
6851
7144
  Endpoints are FULL https URLs to Bing Ads v13 hosts (campaign/reporting/bulk .api.bingads.microsoft.com) \u2014 not relative paths.
6852
7145
  Bing REST puts the operation in the HTTP verb; query reads are POST to .../Query* paths.
6853
7146
  Because query reads are POST, add --publish on read-only Query* calls \u2014 otherwise you get a draft instead of data.
@@ -6855,15 +7148,30 @@ Because query reads are POST, add --publish on read-only Query* calls \u2014 oth
6855
7148
  ${rawPlatformCommandLine("microsoft")}
6856
7149
 
6857
7150
  Commands:
6858
- accounts available List Microsoft ad accounts discoverable from the connected workspace login
7151
+ accounts List, discover, connect, and disconnect Microsoft ad accounts
6859
7152
 
6860
7153
  Examples:
6861
7154
  adkit manage microsoft accounts available
6862
7155
  adkit manage platform-api-requests --platform microsoft --endpoint "https://campaign.api.bingads.microsoft.com/CampaignManagement/v13/Campaigns/QueryByAccountId" --payload '{"AccountId":187276743,"CampaignType":"Search"}' --request-description "List Microsoft campaigns" --account 187276743 --publish`.trim(),
7156
+ "microsoft accounts": `adkit manage microsoft accounts \u2014 Microsoft Ads accounts
7157
+
7158
+ list List connected Microsoft ad accounts
7159
+ available List discoverable Microsoft ad accounts
7160
+ connect <id> Connect a Microsoft ad account
7161
+ disconnect <id> Disconnect a Microsoft ad account
7162
+
7163
+ Flags:
7164
+ --integration <id> Connect using a specific workspace login returned by available
7165
+
7166
+ Examples:
7167
+ adkit manage microsoft accounts list
7168
+ adkit manage microsoft accounts available
7169
+ adkit manage microsoft accounts connect 187276743
7170
+ adkit manage microsoft accounts disconnect 187276743`.trim(),
6863
7171
  linkedin: `adkit manage linkedin \u2014 LinkedIn Ads management
6864
7172
 
6865
7173
  Entity groups:
6866
- accounts Discover LinkedIn ad accounts (available)
7174
+ accounts List, discover, connect, and disconnect LinkedIn ad accounts
6867
7175
  media Upload creative and fetch media by URN
6868
7176
  campaigns Manage campaigns (LinkedIn "Campaign Groups")
6869
7177
  ad-groups Manage ad groups (LinkedIn "Campaigns"/"Ad sets" \u2014 objective, budget, targeting)
@@ -6883,6 +7191,21 @@ ${FLAG.data}
6883
7191
 
6884
7192
  ${rawPlatformCommandLine("linkedin")}
6885
7193
  Run adkit manage linkedin <group> --help for details.`.trim(),
7194
+ "linkedin accounts": `adkit manage linkedin accounts \u2014 LinkedIn Ads accounts
7195
+
7196
+ list List connected LinkedIn ad accounts
7197
+ available List discoverable LinkedIn ad accounts
7198
+ connect <id> Connect a LinkedIn ad account
7199
+ disconnect <id> Disconnect a LinkedIn ad account
7200
+
7201
+ Flags:
7202
+ --integration <id> Connect using a specific workspace login returned by available
7203
+
7204
+ Examples:
7205
+ adkit manage linkedin accounts list
7206
+ adkit manage linkedin accounts available
7207
+ adkit manage linkedin accounts connect 512345678
7208
+ adkit manage linkedin accounts disconnect 512345678`.trim(),
6886
7209
  drafts: `adkit manage drafts \u2014 Manage drafts
6887
7210
 
6888
7211
  list List all drafts
@@ -8721,16 +9044,28 @@ async function main() {
8721
9044
  }
8722
9045
  } else if (platform2 === "linkedin") {
8723
9046
  switch (entity) {
8724
- case "accounts":
9047
+ case "accounts": {
8725
9048
  switch (action) {
9049
+ case "list":
9050
+ case void 0:
9051
+ data = await listLinkedInAccounts(client, restArgs, flags);
9052
+ emptyHint = "No LinkedIn ad accounts connected. Connect a workspace login first if no accounts are available.";
9053
+ break;
8726
9054
  case "available":
8727
9055
  data = await listLinkedInAvailableAccounts(client, restArgs, flags);
8728
9056
  emptyHint = "No LinkedIn ad accounts available from the connected workspace login.";
8729
9057
  break;
9058
+ case "connect":
9059
+ data = await connectLinkedInAccount(client, restArgs, flags);
9060
+ break;
9061
+ case "disconnect":
9062
+ data = await disconnectLinkedInAccount(client, restArgs, flags);
9063
+ break;
8730
9064
  default:
8731
- throw new CliError("UNKNOWN_COMMAND", `Unknown action: linkedin accounts ${action}`, "Available: available.");
9065
+ throw new CliError("UNKNOWN_COMMAND", `Unknown action: linkedin accounts ${action}`, "Run: adkit manage linkedin accounts --help");
8732
9066
  }
8733
9067
  break;
9068
+ }
8734
9069
  case "media": {
8735
9070
  if (!action) {
8736
9071
  showHelp("linkedin media", flags.help === "full");
@@ -8832,21 +9167,98 @@ async function main() {
8832
9167
  }
8833
9168
  } else if (platform2 === "microsoft") {
8834
9169
  switch (entity) {
8835
- case "accounts":
9170
+ case "accounts": {
8836
9171
  switch (action) {
9172
+ case "list":
9173
+ case void 0:
9174
+ data = await listMicrosoftAccounts(client, restArgs, flags);
9175
+ emptyHint = "No Microsoft ad accounts connected. Connect a workspace login first if no accounts are available.";
9176
+ break;
8837
9177
  case "available":
8838
9178
  data = await listMicrosoftAvailableAccounts(client, restArgs, flags);
8839
9179
  emptyHint = "No Microsoft ad accounts available from the connected workspace login.";
8840
9180
  break;
9181
+ case "connect":
9182
+ data = await connectMicrosoftAccount(client, restArgs, flags);
9183
+ break;
9184
+ case "disconnect":
9185
+ data = await disconnectMicrosoftAccount(client, restArgs, flags);
9186
+ break;
8841
9187
  default:
8842
- throw new CliError("UNKNOWN_COMMAND", `Unknown action: microsoft accounts ${action}`, "Available: available.");
9188
+ throw new CliError("UNKNOWN_COMMAND", `Unknown action: microsoft accounts ${action}`, "Run: adkit manage microsoft accounts --help");
8843
9189
  }
8844
9190
  break;
9191
+ }
8845
9192
  default:
8846
9193
  throw new CliError("UNKNOWN_COMMAND", `Unknown entity: microsoft ${entity}`, "Available: accounts, platform-api-requests");
8847
9194
  }
8848
- } else if (platform2 === "x") throw new CliError("UNKNOWN_COMMAND", `Unknown entity: x ${entity}`, "Available: platform-api-requests");
8849
- else throw new CliError("UNKNOWN_COMMAND", "Unknown platform", "Available: meta, google, tiktok, reddit, x, linkedin, microsoft, drafts, platform-api-requests");
9195
+ } else if (platform2 === "x") {
9196
+ switch (entity) {
9197
+ case "accounts": {
9198
+ if (action && action !== "list" && action !== "available" && action !== "connect" && action !== "disconnect") {
9199
+ const accountId = action;
9200
+ const subcommand = args[4];
9201
+ if (subcommand === "profiles") {
9202
+ data = await listXProfiles(client, [accountId], flags);
9203
+ emptyHint = "No X identities found for this account.";
9204
+ } else if (subcommand === "pixels") {
9205
+ data = await listXPixels(client, [accountId], flags);
9206
+ emptyHint = "No X conversion pixels found for this account.";
9207
+ } else if (subcommand === "update") data = await updateXAccount(client, [accountId], flags);
9208
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown subcommand: x accounts ${accountId} ${subcommand ?? ""}`, "Expected: profiles, pixels, or update");
9209
+ break;
9210
+ }
9211
+ switch (action) {
9212
+ case "list":
9213
+ case void 0:
9214
+ data = await listXAccounts(client, restArgs, flags);
9215
+ emptyHint = "No X ad accounts connected. Connect a workspace login first if no accounts are available.";
9216
+ break;
9217
+ case "available":
9218
+ data = await listXAvailableAccounts(client, restArgs, flags);
9219
+ emptyHint = "No X ad accounts available from the connected workspace login.";
9220
+ break;
9221
+ case "connect":
9222
+ data = await connectXAccount(client, restArgs, flags);
9223
+ break;
9224
+ case "disconnect":
9225
+ data = await disconnectXAccount(client, restArgs, flags);
9226
+ break;
9227
+ default:
9228
+ throw new CliError("UNKNOWN_COMMAND", `Unknown action: x accounts ${action}`, "Run: adkit manage x accounts --help");
9229
+ }
9230
+ break;
9231
+ }
9232
+ case "campaigns":
9233
+ if (action === "list") {
9234
+ data = await listXCampaigns(client, restArgs, flags);
9235
+ emptyHint = "No X campaigns matched the selected filters.";
9236
+ } else if (action === "get") data = await getXCampaign(client, restArgs, flags);
9237
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown action: x campaigns ${action}`, "Available: list, get");
9238
+ break;
9239
+ case "ad-groups":
9240
+ if (action === "list") {
9241
+ data = await listXAdGroups(client, restArgs, flags);
9242
+ emptyHint = "No X ad groups matched the selected filters.";
9243
+ } else if (action === "get") data = await getXAdGroup(client, restArgs, flags);
9244
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown action: x ad-groups ${action}`, "Available: list, get");
9245
+ break;
9246
+ case "ads":
9247
+ if (action === "list") {
9248
+ data = await listXAds(client, restArgs, flags);
9249
+ emptyHint = "No X promoted-Post ads matched the selected filters.";
9250
+ } else if (action === "get") data = await getXAd(client, restArgs, flags);
9251
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown action: x ads ${action}`, "Available: list, get");
9252
+ break;
9253
+ case "results":
9254
+ if (action && action !== "list") throw new CliError("UNKNOWN_COMMAND", `Unknown action: x results ${action}`, "Available: list");
9255
+ data = await listXResults(client, restArgs, flags);
9256
+ emptyHint = "No X result rows matched the selected range and filters.";
9257
+ break;
9258
+ default:
9259
+ throw new CliError("UNKNOWN_COMMAND", `Unknown entity: x ${entity}`, "Available: accounts, campaigns, ad-groups, ads, results, platform-api-requests");
9260
+ }
9261
+ } else throw new CliError("UNKNOWN_COMMAND", "Unknown platform", "Available: meta, google, tiktok, reddit, x, linkedin, microsoft, drafts, platform-api-requests");
8850
9262
  printResult(data, flags, emptyHint, detailEntity);
8851
9263
  return;
8852
9264
  }
@@ -8882,14 +9294,7 @@ async function main() {
8882
9294
  console.log(output || "No similar advertisers found. Try adjusting --industry, --category, or --tags filters.");
8883
9295
  }
8884
9296
  } else if (action === "search") {
8885
- const query = args.slice(3).join(" ");
8886
- if (!query) {
8887
- console.error("Usage: adkit library advertisers search <query>");
8888
- process.exitCode = 1;
8889
- return;
8890
- }
8891
- flags.search = query;
8892
- const data = await listAdvertisers(client, [], flags);
9297
+ const data = await searchAdvertisers(client, args.slice(3), flags);
8893
9298
  if (wantsJson(flags)) printResult(data, flags, "No advertisers found matching your search.");
8894
9299
  else {
8895
9300
  const rows = unwrapList(data).map(formatLibraryAdvertiserRow);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adkit/cli",
3
- "version": "1.13.26",
3
+ "version": "1.13.27",
4
4
  "description": "The Ads CLI for AI agents — manage Meta & Google ad campaigns, browse the ad library, and generate creatives from your terminal.",
5
5
  "keywords": [
6
6
  "ads cli",