Tactical recommendations
Recommendations the service publishes for an account, and the routes to apply or edit one.
- class ad_api.api.Recommendations(account: str = 'default', marketplace: Marketplaces = Marketplaces.EU, credentials: Dict[str, str] | None = None, proxies: Dict[str, str] | None = None, verify: bool = True, timeout: int | None = None, debug: bool = False, access_token: str | None = None, verify_additional_credentials: bool = True)
Note
Amazon lists these under
Recommendations & insightsin its API index, alongsideOverlapping audiences, without a beta marker. Seven other pages there do carry(beta); this one does not, so the label is gone from this page and from the readme.### Endpoint map
:header-rows: 1 Path
Method
Kind
Answer
POST /recommendations/listlist_recommendationsread
200POST /recommendations/applyapply_recommendationswrite
200PUT /recommendations/{recommendationId}update_recommendationwrite
200All three answer at version 1, which is the default. Unlike the Insights routes, where version 1 was retired and answered
415, these work without passing a version.### The STATUS filter
The filter field
STATUSdoes not take campaign states. It takes the stages a recommendation passes through, and the service lists them when you get it wrong:Filter for recommendation status must only contain values [PUBLISHED, APPLY_IN_PROGRESS, APPLY_SUCCESS, APPLY_FAILED, REJECTED]
ENABLEDandACTIVEare refused. That enum is not in the contract and only comes from the rejection message.### About filters
filtersbehaves oddly, and the contract does not explain it::header-rows: 1 Body
Result
{"maxResults": 10}200, the account’s recommendations{"filters": []}400 Member must have length greater than or equal to 1{"filters": [{...}]}200, the filtered setRequired when present, optional in practice. Each filter takes
field,values,includeandoperator::header-rows: 1 Member
Type
Meaning
fieldstring
RECOMMENDATION_ID,AD_PRODUCT,RECOMMENDATION_TYPE,STATUS,GROUPING_TYPEorCAMPAIGN_ID.valuesarray
Between 1 and 500 strings.
includeboolean
Include the match or exclude it. Defaults to true.
operatorstring
EXACTis the only value.### A body is required
Every method takes one. Calling without it fails before the request is sent:
KeyError: 'body'
That comes from the package, not the service, so it costs nothing but says nothing helpful either.
### The writes were not exercised
apply_recommendationsedits real bidding and budgets on the account, andupdate_recommendationedits the recommendation before it is applied. Neither was called: the account held no recommendation to apply.Read one first with
list_recommendations. The fieldsupdate_recommendationexpects change withrecommendationType, and the contract describes a bidding rule and a budget rule but not every type.### Example: read the recommendations
from ad_api.api import Recommendations client = Recommendations(account='my_account', debug=False) res = client.list_recommendations(body={"maxResults": 50}) payload = res.payload print(payload["totalResults"]) for rec in payload["recommendations"]: print(rec.get("recommendationId"), rec.get("recommendationType"))
An empty list with
totalResultsat 0 means the account has none. That is a fact about the account, not a failed call, and a small account with a few campaigns often has none.### Example: filter by status
from ad_api.api import Recommendations client = Recommendations(account='my_account', debug=False) res = client.list_recommendations(body={ "maxResults": 50, "filters": [{ "field": "STATUS", "values": ["PUBLISHED"], "include": True, "operator": "EXACT", }], })
### Example: apply one
This changes the account. Read the list first.
from ad_api.api import Recommendations client = Recommendations(account='my_account', debug=False) res = client.apply_recommendations( body={"recommendationIds": ["your-recommendation-id"]}) print(res.payload)
- list_recommendations(version: int = 1, **kwargs) ApiResponse
Retrieves a list of recommendations.
- Request Body (required)
- ListRecommendationsRequest {maxResults (integer) default: 500 minimum: 1 maximum: 500nextToken (string) Token to retrieve the next page of results.filters (array) minItems: 1 maxItems: 10 [ListRecommendationsFilter {include (boolean): Flag to specify if the filter should be included or excluded. default: truefield* FilterField (string): Field to filter by. Enum: [‘RECOMMENDATION_ID’, ‘AD_PRODUCT’, ‘RECOMMENDATION_TYPE’, ‘STATUS’, ‘GROUPING_TYPE’, ‘CAMPAIGN_ID’]values* (array) minItems: 1 maxItems: 500 [string]operator FilterOperator (string): Operator to filter field by. Enum: [‘EXACT’]}]}
The values
STATUSaccepts are not the states of a campaign. They are the stages a recommendation passes through, and the service names them in its rejection message:PUBLISHED,APPLY_IN_PROGRESS,APPLY_SUCCESS,APPLY_FAILEDandREJECTED.ENABLEDandACTIVEare refused.filtersbehaves oddly. An empty list answers400 Member must have length greater than or equal to 1, yet leaving the member out altogether answers200with the account’s recommendations. So it is required when present, and optional in practice.A body is required: without one the call fails before reaching the service, with
KeyError: 'body'.- Returns
ApiResponse with
recommendations,totalResultsandnextToken. The list is empty for an account that has none, which is a fact about the account rather than a failed call.
- apply_recommendations(version: int = 1, **kwargs) ApiResponse
Applies one or more recommendations.
- Request Body (required)
- ApplyRecommendationsRequest {recommendationIds* (array) minItems: 1 maxItems: 100 [(string) Recommendation identifier.]}
Warning
This changes campaigns. Applying a recommendation edits real bidding and budgets on the account, and there is no undo richer than changing them back by hand.
Not exercised: no recommendation existed on the account to apply.
- Returns
ApiResponse
- update_recommendation(recommendationId, version: int = 1, **kwargs) ApiResponse
Updates a recommendation.
path recommendationId:string | Required. The identifier of the recommendation.
- Request Body (required)
- UpdateRecommendationRequest {ruleBasedBidding UpdateRuleBasedBidding {Can only be updated for recommendations with recommendationType NEW_CAMPAIGN_BIDDING_RULE or CAMPAIGN_BIDDING_RULE.recommendedRuleRoas* (number)}recommendedValue (string) Recommended value of the recommendation. Type of data expected for each recommendation type:budgetRule UpdateBudgetRule {ruleDetails* UpdateBudgetRuleDetails {duration UpdateBudgetRuleDuration {dateRangeTypeDuration UpdateBudgetRuleDurationDateRange {endDate (string): End date of the budget rule in YYYY-MM-DD format. The end date is inclusive.}budgetIncreaseBy BudgetRuleIncreaseBy {value*(number): Budget of the rule.}ruleName* (string): Name of the budget rule. Required to be unique within a campaign. minLength: 1 maxLength: 355performanceMeasureCondition BudgetRulePerformanceMeasureCondition {threshold*(number): Threshold of the performance metric.}}}}
Warning
This edits a recommendation before it is applied. Read one first with
list_recommendationsfor the shape it expects, since the fields change withrecommendationType.Not exercised, for the same reason as
apply_recommendations.- Returns
ApiResponse