@adkit/cli 1.13.26 → 1.13.28

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 +2 -2
  2. package/dist/cli.js +454 -50
  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>
@@ -60,7 +60,7 @@ adkit studio ads list
60
60
  adkit studio ads generate --ref media:<id> --mode clone
61
61
  adkit studio ads <id>
62
62
  adkit studio media upload ./banner.png
63
- adkit studio media list
63
+ adkit studio media list <ad-id>
64
64
  ```
65
65
 
66
66
  ### Meta (Facebook / Instagram)
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");
@@ -4772,7 +4959,6 @@ var CLI_HELP_OVERRIDES = {
4772
4959
  "manage google keywords add-negative": { path: "manage google keywords negatives add", description: "" },
4773
4960
  "manage google keywords remove-negative": { path: "manage google keywords negatives remove", description: "" },
4774
4961
  "studio ads generate": { path: "studio generate", description: "" },
4775
- "studio ads media_list": { path: "studio media list", description: "" },
4776
4962
  "studio ads share": { path: "studio share", description: "" },
4777
4963
  "studio media request_upload_url": {
4778
4964
  path: "studio media upload",
@@ -4860,7 +5046,9 @@ Manage platforms:
4860
5046
  google Google Ads
4861
5047
  tiktok TikTok Ads
4862
5048
  reddit Reddit Ads
5049
+ x X Ads
4863
5050
  linkedin LinkedIn Ads
5051
+ microsoft Microsoft Ads
4864
5052
  drafts Drafts across platforms
4865
5053
 
4866
5054
  Run \`adkit <command> --help\` for details.
@@ -6714,7 +6902,7 @@ Examples:
6714
6902
  "platform-api-requests": `adkit manage platform-api-requests \u2014 Send raw API requests to ad platforms
6715
6903
 
6716
6904
  Bypasses normalized AdKit entity validation, but still runs account and safety checks.
6717
- GET requests execute immediately. POST/PUT/PATCH/DELETE create drafts by default; add --publish to execute mutating requests immediately.
6905
+ Recognized read-only requests execute immediately. Other POST/PUT/PATCH/DELETE requests create drafts by default; add --publish to execute mutations immediately.
6718
6906
  Must be enabled in Agent Permissions first.
6719
6907
  Use this for unsupported native platform resources/workflows. Use platformOverrides instead when you only need raw fields on a supported normalized resource.
6720
6908
  Use the selected platform's official endpoint paths, field names, enum values, and resource shapes. Do not translate normalized AdKit field names into raw API payloads by guessing.
@@ -6740,7 +6928,7 @@ Examples:
6740
6928
  adkit manage platform-api-requests --platform reddit --endpoint "ad_accounts/a2_example/campaigns" --payload '{"name":"Test","objective":"TRAFFIC","configured_status":"PAUSED"}' --request-description "Create paused Reddit campaign" --account a2_example
6741
6929
  adkit manage platform-api-requests --platform x --endpoint "accounts/18ce54d4x5t/campaigns" --method GET --request-description "List X campaigns" --account 18ce54d4x5t
6742
6930
  adkit manage platform-api-requests --platform linkedin --endpoint "adCampaignGroups/(account:urn:li:sponsoredAccount:512345678)" --method GET --request-description "List LinkedIn campaign groups" --account 512345678
6743
- 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(),
6931
+ 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`.trim(),
6744
6932
  manage: `adkit manage \u2014 Ad platform management
6745
6933
 
6746
6934
  Platforms:
@@ -6748,9 +6936,9 @@ Platforms:
6748
6936
  google Google Ads
6749
6937
  tiktok TikTok Ads
6750
6938
  reddit Reddit Ads
6751
- x X Ads raw API access
6939
+ x X account setup plus read-only campaigns, ad groups, ads, and results
6752
6940
  linkedin LinkedIn Ads (campaigns, ad groups, ads, targeting, results)
6753
- microsoft Microsoft Ads raw API access + account discovery
6941
+ microsoft Microsoft Ads raw API access + account setup
6754
6942
  drafts Manage drafts across platforms
6755
6943
  platform-api-requests Send raw API requests (escape hatch)
6756
6944
 
@@ -6836,34 +7024,153 @@ General flags:
6836
7024
  ${FLAG.account}
6837
7025
 
6838
7026
  Run adkit manage reddit accounts --help for account setup.`.trim(),
6839
- x: `adkit manage x \u2014 X Ads raw API access
7027
+ x: `adkit manage x \u2014 X Ads management
6840
7028
 
6841
- X is currently exposed through Advanced Platform Access only.
6842
- Use platform-api-requests with official X Ads API endpoint paths.
7029
+ Entity groups:
7030
+ accounts Connect accounts and configure profile/pixel defaults
7031
+ campaigns List/get campaigns
7032
+ ad-groups List/get line items as ad groups
7033
+ ads List/get promoted-Post associations
7034
+ results Campaign, ad-group, and ad performance
6843
7035
 
6844
7036
  ${rawPlatformCommandLine("x")}
6845
7037
 
6846
7038
  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
7039
+ adkit manage x accounts available
7040
+ adkit manage x campaigns list --account 18ce54d4x5t
7041
+ adkit manage x results --level ads --from 2026-08-01 --to 2026-08-07 --account 18ce54d4x5t`.trim(),
7042
+ "x accounts": `adkit manage x accounts \u2014 X Ads accounts
7043
+
7044
+ list List connected X ad accounts
7045
+ available List discoverable X ad accounts
7046
+ connect <id> Connect an X ad account
7047
+ disconnect <id> Disconnect an X ad account
7048
+ <id> profiles List X identities available to an account
7049
+ <id> pixels List X conversion pixels available to an account
7050
+ <id> update Save default identity and pixel IDs
6849
7051
 
6850
- Microsoft (Bing) is currently exposed through Advanced Platform Access, plus account discovery.
7052
+ Flags:
7053
+ --integration <id> Connect using a specific workspace login returned by available
7054
+ --default-profile <id> Default X identity for ad creation
7055
+ --default-pixel <id> Default X conversion pixel
7056
+ --data <json> Full update body; also supports null to clear a default
7057
+
7058
+ Examples:
7059
+ adkit manage x accounts list
7060
+ adkit manage x accounts available
7061
+ adkit manage x accounts connect 18ce54d4x5t
7062
+ adkit manage x accounts 18ce54d4x5t profiles
7063
+ adkit manage x accounts 18ce54d4x5t pixels
7064
+ adkit manage x accounts 18ce54d4x5t update --default-profile 12abc --default-pixel p123
7065
+ adkit manage x accounts disconnect 18ce54d4x5t`.trim(),
7066
+ "x campaigns": `adkit manage x campaigns \u2014 X Ads campaigns (read-only)
7067
+
7068
+ list List campaigns
7069
+ get <id> Get one campaign
7070
+
7071
+ Flags:
7072
+ ${FLAG.account}
7073
+ --campaign-ids <ids> Comma-separated campaign platform IDs
7074
+ --status <s> active, paused, or removed
7075
+ --limit <n> Max rows
7076
+ --offset <n> Row offset
7077
+
7078
+ Example:
7079
+ adkit manage x campaigns list --status active
7080
+ adkit manage x campaigns get 8v7jo`.trim(),
7081
+ "x ad-groups": `adkit manage x ad-groups \u2014 X line items as AdKit ad groups (read-only)
7082
+
7083
+ list List ad groups
7084
+ get <id> Get one ad group
7085
+
7086
+ Flags:
7087
+ ${FLAG.account}
7088
+ --campaign-ids <ids> Comma-separated parent campaign IDs
7089
+ --ad-group-ids <ids> Comma-separated line-item IDs
7090
+ --status <s> active, paused, or removed
7091
+ --limit <n> Max rows
7092
+ --offset <n> Row offset
7093
+
7094
+ Example:
7095
+ adkit manage x ad-groups list --campaign-ids 8v7jo`.trim(),
7096
+ "x ads": `adkit manage x ads \u2014 X promoted-Post ads (read-only)
7097
+
7098
+ list List promoted-Post ads
7099
+ get <id> Get one ad by promoted association ID
7100
+
7101
+ Identity:
7102
+ platformId is the promoted association ID used by X Ads and analytics. postId is the underlying Post ID.
7103
+
7104
+ Flags:
7105
+ ${FLAG.account}
7106
+ --campaign-ids <ids> Comma-separated parent campaign IDs
7107
+ --ad-group-ids <ids> Comma-separated parent line-item IDs
7108
+ --ad-ids <ids> Comma-separated promoted association IDs
7109
+ --status <s> active, paused, or removed
7110
+ --limit <n> Max rows
7111
+ --offset <n> Row offset
7112
+
7113
+ Example:
7114
+ adkit manage x ads get 1efwlo`.trim(),
7115
+ "x results": `adkit manage x results \u2014 X Ads performance reporting (read-only)
7116
+
7117
+ list List reporting rows (list is optional)
7118
+
7119
+ Flags:
7120
+ ${FLAG.account}
7121
+ --level <level> Required: campaigns, ad-groups, or ads
7122
+ --from <date> Required YYYY-MM-DD start
7123
+ --to <date> Required YYYY-MM-DD end
7124
+ --fields <csv> spend, impressions, clicks, ctr, cpc, cpm, outboundClicks, outboundCtr, costPerOutboundClick, videoViews
7125
+ --breakdowns <csv> day only
7126
+ --campaign-ids <ids> Campaign filters
7127
+ --ad-group-ids <ids> Ad-group filters
7128
+ --ad-ids <ids> Promoted association filters for level ads
7129
+ --sort <field> Metric to sort by (default: spend)
7130
+ --sort-direction <d> asc or desc
7131
+ --limit <n> Max rows
7132
+ --offset <n> Row offset
7133
+ --raw Include queried placements in platformDetails
7134
+
7135
+ Note:
7136
+ X does not name one primary Results metric, so rows omit metrics.results and return conversionEvents: {}.
7137
+
7138
+ Example:
7139
+ adkit manage x results --level ads --from 2026-08-01 --to 2026-08-07 --fields spend,impressions,clicks`.trim(),
7140
+ microsoft: `adkit manage microsoft \u2014 Microsoft Ads raw API access + account setup
7141
+
7142
+ Microsoft (Bing) is currently exposed through Advanced Platform Access, plus account assignment.
6851
7143
  Endpoints are FULL https URLs to Bing Ads v13 hosts (campaign/reporting/bulk .api.bingads.microsoft.com) \u2014 not relative paths.
6852
7144
  Bing REST puts the operation in the HTTP verb; query reads are POST to .../Query* paths.
6853
- Because query reads are POST, add --publish on read-only Query* calls \u2014 otherwise you get a draft instead of data.
7145
+ Recognized Query* reads execute immediately even though Bing uses POST. Other POST requests remain draft-first.
6854
7146
 
6855
7147
  ${rawPlatformCommandLine("microsoft")}
6856
7148
 
6857
7149
  Commands:
6858
- accounts available List Microsoft ad accounts discoverable from the connected workspace login
7150
+ accounts List, discover, connect, and disconnect Microsoft ad accounts
6859
7151
 
6860
7152
  Examples:
6861
7153
  adkit manage microsoft accounts available
6862
- 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(),
7154
+ 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`.trim(),
7155
+ "microsoft accounts": `adkit manage microsoft accounts \u2014 Microsoft Ads accounts
7156
+
7157
+ list List connected Microsoft ad accounts
7158
+ available List discoverable Microsoft ad accounts
7159
+ connect <id> Connect a Microsoft ad account
7160
+ disconnect <id> Disconnect a Microsoft ad account
7161
+
7162
+ Flags:
7163
+ --integration <id> Connect using a specific workspace login returned by available
7164
+
7165
+ Examples:
7166
+ adkit manage microsoft accounts list
7167
+ adkit manage microsoft accounts available
7168
+ adkit manage microsoft accounts connect 187276743
7169
+ adkit manage microsoft accounts disconnect 187276743`.trim(),
6863
7170
  linkedin: `adkit manage linkedin \u2014 LinkedIn Ads management
6864
7171
 
6865
7172
  Entity groups:
6866
- accounts Discover LinkedIn ad accounts (available)
7173
+ accounts List, discover, connect, and disconnect LinkedIn ad accounts
6867
7174
  media Upload creative and fetch media by URN
6868
7175
  campaigns Manage campaigns (LinkedIn "Campaign Groups")
6869
7176
  ad-groups Manage ad groups (LinkedIn "Campaigns"/"Ad sets" \u2014 objective, budget, targeting)
@@ -6883,6 +7190,21 @@ ${FLAG.data}
6883
7190
 
6884
7191
  ${rawPlatformCommandLine("linkedin")}
6885
7192
  Run adkit manage linkedin <group> --help for details.`.trim(),
7193
+ "linkedin accounts": `adkit manage linkedin accounts \u2014 LinkedIn Ads accounts
7194
+
7195
+ list List connected LinkedIn ad accounts
7196
+ available List discoverable LinkedIn ad accounts
7197
+ connect <id> Connect a LinkedIn ad account
7198
+ disconnect <id> Disconnect a LinkedIn ad account
7199
+
7200
+ Flags:
7201
+ --integration <id> Connect using a specific workspace login returned by available
7202
+
7203
+ Examples:
7204
+ adkit manage linkedin accounts list
7205
+ adkit manage linkedin accounts available
7206
+ adkit manage linkedin accounts connect 512345678
7207
+ adkit manage linkedin accounts disconnect 512345678`.trim(),
6886
7208
  drafts: `adkit manage drafts \u2014 Manage drafts
6887
7209
 
6888
7210
  list List all drafts
@@ -8721,16 +9043,28 @@ async function main() {
8721
9043
  }
8722
9044
  } else if (platform2 === "linkedin") {
8723
9045
  switch (entity) {
8724
- case "accounts":
9046
+ case "accounts": {
8725
9047
  switch (action) {
9048
+ case "list":
9049
+ case void 0:
9050
+ data = await listLinkedInAccounts(client, restArgs, flags);
9051
+ emptyHint = "No LinkedIn ad accounts connected. Connect a workspace login first if no accounts are available.";
9052
+ break;
8726
9053
  case "available":
8727
9054
  data = await listLinkedInAvailableAccounts(client, restArgs, flags);
8728
9055
  emptyHint = "No LinkedIn ad accounts available from the connected workspace login.";
8729
9056
  break;
9057
+ case "connect":
9058
+ data = await connectLinkedInAccount(client, restArgs, flags);
9059
+ break;
9060
+ case "disconnect":
9061
+ data = await disconnectLinkedInAccount(client, restArgs, flags);
9062
+ break;
8730
9063
  default:
8731
- throw new CliError("UNKNOWN_COMMAND", `Unknown action: linkedin accounts ${action}`, "Available: available.");
9064
+ throw new CliError("UNKNOWN_COMMAND", `Unknown action: linkedin accounts ${action}`, "Run: adkit manage linkedin accounts --help");
8732
9065
  }
8733
9066
  break;
9067
+ }
8734
9068
  case "media": {
8735
9069
  if (!action) {
8736
9070
  showHelp("linkedin media", flags.help === "full");
@@ -8832,21 +9166,98 @@ async function main() {
8832
9166
  }
8833
9167
  } else if (platform2 === "microsoft") {
8834
9168
  switch (entity) {
8835
- case "accounts":
9169
+ case "accounts": {
8836
9170
  switch (action) {
9171
+ case "list":
9172
+ case void 0:
9173
+ data = await listMicrosoftAccounts(client, restArgs, flags);
9174
+ emptyHint = "No Microsoft ad accounts connected. Connect a workspace login first if no accounts are available.";
9175
+ break;
8837
9176
  case "available":
8838
9177
  data = await listMicrosoftAvailableAccounts(client, restArgs, flags);
8839
9178
  emptyHint = "No Microsoft ad accounts available from the connected workspace login.";
8840
9179
  break;
9180
+ case "connect":
9181
+ data = await connectMicrosoftAccount(client, restArgs, flags);
9182
+ break;
9183
+ case "disconnect":
9184
+ data = await disconnectMicrosoftAccount(client, restArgs, flags);
9185
+ break;
8841
9186
  default:
8842
- throw new CliError("UNKNOWN_COMMAND", `Unknown action: microsoft accounts ${action}`, "Available: available.");
9187
+ throw new CliError("UNKNOWN_COMMAND", `Unknown action: microsoft accounts ${action}`, "Run: adkit manage microsoft accounts --help");
8843
9188
  }
8844
9189
  break;
9190
+ }
8845
9191
  default:
8846
9192
  throw new CliError("UNKNOWN_COMMAND", `Unknown entity: microsoft ${entity}`, "Available: accounts, platform-api-requests");
8847
9193
  }
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");
9194
+ } else if (platform2 === "x") {
9195
+ switch (entity) {
9196
+ case "accounts": {
9197
+ if (action && action !== "list" && action !== "available" && action !== "connect" && action !== "disconnect") {
9198
+ const accountId = action;
9199
+ const subcommand = args[4];
9200
+ if (subcommand === "profiles") {
9201
+ data = await listXProfiles(client, [accountId], flags);
9202
+ emptyHint = "No X identities found for this account.";
9203
+ } else if (subcommand === "pixels") {
9204
+ data = await listXPixels(client, [accountId], flags);
9205
+ emptyHint = "No X conversion pixels found for this account.";
9206
+ } else if (subcommand === "update") data = await updateXAccount(client, [accountId], flags);
9207
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown subcommand: x accounts ${accountId} ${subcommand ?? ""}`, "Expected: profiles, pixels, or update");
9208
+ break;
9209
+ }
9210
+ switch (action) {
9211
+ case "list":
9212
+ case void 0:
9213
+ data = await listXAccounts(client, restArgs, flags);
9214
+ emptyHint = "No X ad accounts connected. Connect a workspace login first if no accounts are available.";
9215
+ break;
9216
+ case "available":
9217
+ data = await listXAvailableAccounts(client, restArgs, flags);
9218
+ emptyHint = "No X ad accounts available from the connected workspace login.";
9219
+ break;
9220
+ case "connect":
9221
+ data = await connectXAccount(client, restArgs, flags);
9222
+ break;
9223
+ case "disconnect":
9224
+ data = await disconnectXAccount(client, restArgs, flags);
9225
+ break;
9226
+ default:
9227
+ throw new CliError("UNKNOWN_COMMAND", `Unknown action: x accounts ${action}`, "Run: adkit manage x accounts --help");
9228
+ }
9229
+ break;
9230
+ }
9231
+ case "campaigns":
9232
+ if (action === "list") {
9233
+ data = await listXCampaigns(client, restArgs, flags);
9234
+ emptyHint = "No X campaigns matched the selected filters.";
9235
+ } else if (action === "get") data = await getXCampaign(client, restArgs, flags);
9236
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown action: x campaigns ${action}`, "Available: list, get");
9237
+ break;
9238
+ case "ad-groups":
9239
+ if (action === "list") {
9240
+ data = await listXAdGroups(client, restArgs, flags);
9241
+ emptyHint = "No X ad groups matched the selected filters.";
9242
+ } else if (action === "get") data = await getXAdGroup(client, restArgs, flags);
9243
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown action: x ad-groups ${action}`, "Available: list, get");
9244
+ break;
9245
+ case "ads":
9246
+ if (action === "list") {
9247
+ data = await listXAds(client, restArgs, flags);
9248
+ emptyHint = "No X promoted-Post ads matched the selected filters.";
9249
+ } else if (action === "get") data = await getXAd(client, restArgs, flags);
9250
+ else throw new CliError("UNKNOWN_COMMAND", `Unknown action: x ads ${action}`, "Available: list, get");
9251
+ break;
9252
+ case "results":
9253
+ if (action && action !== "list") throw new CliError("UNKNOWN_COMMAND", `Unknown action: x results ${action}`, "Available: list");
9254
+ data = await listXResults(client, restArgs, flags);
9255
+ emptyHint = "No X result rows matched the selected range and filters.";
9256
+ break;
9257
+ default:
9258
+ throw new CliError("UNKNOWN_COMMAND", `Unknown entity: x ${entity}`, "Available: accounts, campaigns, ad-groups, ads, results, platform-api-requests");
9259
+ }
9260
+ } else throw new CliError("UNKNOWN_COMMAND", "Unknown platform", "Available: meta, google, tiktok, reddit, x, linkedin, microsoft, drafts, platform-api-requests");
8850
9261
  printResult(data, flags, emptyHint, detailEntity);
8851
9262
  return;
8852
9263
  }
@@ -8882,14 +9293,7 @@ async function main() {
8882
9293
  console.log(output || "No similar advertisers found. Try adjusting --industry, --category, or --tags filters.");
8883
9294
  }
8884
9295
  } 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);
9296
+ const data = await searchAdvertisers(client, args.slice(3), flags);
8893
9297
  if (wantsJson(flags)) printResult(data, flags, "No advertisers found matching your search.");
8894
9298
  else {
8895
9299
  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.28",
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",