# ads_sp_bulk_create (https://sellersheetai.com/docs/mcp-api/tools/ads_sp_bulk_create)

> Create complete Sponsored Products campaign structures in one call (Amazon Ads API v1) — campaign → ad groups → product ads → targets, with the created ids chained server-side.

Access: **WRITE** · toolset amazon_ads · family ads.v1

The whole request is validated and preflighted first, so a malformed spec, a duplicate campaign name or an ASIN you do not own creates nothing. Amazon Ads API · QueryCampaign · POST /adsApi/v1/query/campaigns Amazon Ads API · ProductMetadata · POST /product/metadata Amazon Ads API · CreateCampaign · POST /adsApi/v1/create/campaigns Amazon Ads API · CreateAdGroup · POST /adsApi/v1/create/adGroups Amazon Ads API · CreateAd · POST /adsApi/v1/create/ads Amazon Ads API · CreateTarget · POST /adsApi/v1/create/targets Docs: https://advertising.amazon.com/API/docs/en-us/api-spec-v1-campaigns#tag/Campaigns/operation/QueryCampaign Docs: https://advertising.amazon.com/API/docs/en-us/product-metadata#tag/Product-Selector/operation/ProductMetadata Docs: https://advertising.amazon.com/API/docs/en-us/api-spec-v1-campaigns#tag/Campaigns/operation/CreateCampaign Docs: https://advertising.amazon.com/API/docs/en-us/api-spec-v1-adgroups#tag/AdGroups/operation/CreateAdGroup Docs: https://advertising.amazon.com/API/docs/en-us/api-spec-v1-ads#tag/Ads/operation/CreateAd Docs: https://advertising.amazon.com/API/docs/en-us/api-spec-v1-targets#tag/Targets/operation/CreateTarget Gate: approve — interactive: show the change (Amazon's preview first where one exists), wait for an explicit approve; autopilot: only when the seller's own words asked for this change; otherwise ask.

## Call it

MCP tool call:

```json
{
  "name": "ads_sp_bulk_create",
  "arguments": {
    "store": "myStore-US",
    "countryCode": "<countryCode>",
    "campaign_spec": []
  }
}
```

Tool API (early access — contact us):

```bash
curl -X POST https://api.sellersheetai.com/api/v1/tools/ads_sp_bulk_create \
  -H "Authorization: Bearer $SELLERSHEET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"store":"myStore-US","countryCode":"<countryCode>","campaign_spec":[]}'
```

## Arguments

| Name | Type | Required | Description |
|---|---|---|---|
| `store` | string | yes | the store ref `<store>-<CC>` (name-country, e.g. 'myStore-US') — one of get_user_context's store_refs, verbatim. |
| `countryCode` | string | yes | the Ads profile's 2-letter country code (e.g. 'US'). |
| `campaign_spec` | object[] | yes | [{campaign, negativeTargets, adGroups}] — campaign: {name*, state PAUSED (default — a bulk never launches spend by accident) \| ENABLED, dailyBudget*, startDate* 'YYYYMMDD', endDate, targetingType MANUAL (default) \| AUTO, bidStrategy SALES_DOWN_ONLY (default) \| SALES_UP_AND_DOWN \| MANUAL, portfolioId, campaignId (resume only)}; negativeTargets: campaign-level blocks [{targetType KEYWORD \| PRODUCT, targetDetails, state}]; adGroups: [{adGroup: {name*, defaultBid*, state, adGroupId (resume only)}, productAds: [{sku OR asin, state}], targets: [{targetType*, targetDetails*, bid, state}], negativeTargets: [{targetType* KEYWORD \| PRODUCT, targetDetails*, state}]}]. A biddable target's targetType is KEYWORD \| PRODUCT \| PRODUCT_CATEGORY \| THEME, with targetDetails exactly as ads_create_target takes them (the amazon-ads skill lists the catalog); one ad group is single-targeting-type — keyword targets and product/category/theme targets need separate ad groups. At most 10 campaigns per call, 20 ad groups per campaign and 100 productAds / targets / negativeTargets per ad group — split larger launches. |

## Result

- the orchestrated result described below.
- `data.results` — per campaign {campaignName, status SUCCESS | PARTIAL | ERROR, campaignId, adGroupIds {name: id}, steps: [{action, status, id | error}], message} — inspect every step; PARTIAL means some children failed.

## Gotchas

- A rejected request names the field path of each problem. After the preflight only Amazon-side state (an ineligible product) fails, per step: that campaign becomes PARTIAL and every other step proceeds.
- A seller account advertises by SKU (one SKU = one ASIN, so it names the offer). An asin is resolved to your SKU, but when it maps to several SKUs the whole request is rejected with the SKUs listed — prefer sku when you list a product more than once. A Vendor Central account has no SKUs and passes asin.
- To resume a PARTIAL campaign re-call with the row's campaignId and each created adGroupId (with its defaultBid), OMITTING every child (product ad, target, negative) whose step shows SUCCESS — only the campaign and ad groups are skipped by id; children are re-sent verbatim and an existing one returns a per-index duplicate error.
- Idea sources: ads_get_ranked_keyword_recommendation, ads_sp_get_product_recommendations, ads_get_category_recommendations_for_asins, ads_get_budget_recommendation, ads_get_theme_based_bid_recommendation_for_ad_group_v1.

## Example

- one manual campaign with a product-targeting ad group — [{"campaign": {"name": "AE_Widget_SP_PT", "state": "PAUSED", "dailyBudget": 10, "startDate": "20261201"}, "adGroups": [{"adGroup": {"name": "AE_Widget_SP_PT_Main", "defaultBid": 0.4}, "productAds": [{"sku": "MY-SKU-001"}], "targets": [{"targetType": "PRODUCT", "bid": 0.4, "targetDetails": {"productTarget": {"matchType": "PRODUCT_EXACT", "product": {"productId": "B0XXXXXXXX"}, "productIdType": "ASIN"}}}], "negativeTargets": [{"targetType": "KEYWORD", "targetDetails": {"keywordTarget": {"keyword": "cheap", "matchType": "EXACT"}}}]}]}]