| name | reddit-ads |
| description | Plan and create Reddit Ads campaigns end-to-end via the Hyper MCP — campaign, ad group, ad build order with subreddit / interest / geo targeting, promoted posts, custom and saved audiences, Reddit pixel conversion tracking, and reporting, with micro-currency budgets. Use when the user wants to launch Reddit ads, promote a Reddit post, target subreddits, set up a Reddit pixel, or pull Reddit ad reports. Also triggers on reddit campaign, reddit ppc, or reddit ads manager. |
| requires_toolkits | ["reddit_ads"] |
| icon | reddit_ads |
| short_description | Plan and create Reddit Ads with promoted posts, targeting, pixels, and reporting. |
Reddit Ads Campaigns
Strategic guide for managing Reddit advertising via the Reddit Ads API v3. The toolkit is a raw-HTTP client, so parameter types must be sent exactly as documented — strings as strings, integers as integers, and all money in micro-currency.
Requirements
If reddit_ads_get_me / reddit_ads_list_businesses is not in the tool list, stop and tell the user to enable Hyper MCP and connect Reddit Ads. Serving ads also requires an active funding instrument on the ad account — campaigns and ad groups can be created without one, but the account must be funded for ads to run.
Out of scope — defer to other skills
- Organic Reddit research (mining subreddit discussions, pain points, voice-of-customer) →
customer-research.
- Creative generation (ad copy, images) →
ad-creative-generation.
- Cross-platform campaign launches → use this skill for Reddit, then invoke
meta-ads / google-ads / tiktok-ads separately.
Critical Rules
CRITICAL: All budgets and bids are in micro-currency. $1.00 = 1,000,000 micros. A $50/day budget is goal_value=50000000; a $0.50 CPC is bid_value=500000. Never pass dollar amounts directly.
CRITICAL: Create campaigns, ad groups, and ads with configured_status="PAUSED" (the toolkit default). Never launch live without explicit user review. Because everything defaults to PAUSED, you can build a full campaign and archive it without spending — ideal for demos.
CRITICAL: Discovery flows through businesses, not a flat account list: reddit_ads_get_me → reddit_ads_list_businesses → reddit_ads_list_ad_accounts(business_id=...). There is no top-level "list all ad accounts" call.
CRITICAL: An ad promotes a post — it needs a post_id (or a profile_id + creation), not raw creative fields. Before creating an ad, find an existing post (reddit_ads_list_posts) or create one (reddit_ads_create_post). Only community posts can be promoted via the API.
CRITICAL: The ad group targeting.communities array takes subreddit NAMES, not the t5_ IDs that search_targeting returns. Use the name field from the search results: "communities": ["marketing", "SaaS", "Entrepreneur"] — passing t5_... IDs fails with "You cannot set invalid communities". (interests does use the IDs; geolocations uses country codes like "US".)
CRITICAL: Resolve targeting with reddit_ads_search_targeting before building — never guess values. targeting is a named parameter on create_ad_group; pass any other variant-heavy fields (audiences, schedule) via input_data.
CRITICAL: start_time is required when creating an ad group (ISO 8601). On a campaign, start_time is only valid with CBO enabled — for non-CBO campaigns, omit it at the campaign level and set it on the ad group, or you get "Cannot set start_time for a campaign without having campaign budget optimization enabled."
CRITICAL: bid_value is always required for bid_type CPC/CPM/CPV/CPV6 — even with bid_strategy="MAXIMIZE_VOLUME". Set a cap (e.g. bid_value=600000 = $0.60) or get one from reddit_ads_generate_bid_suggestion.
CRITICAL: There is no instant hard delete. Reddit requires an entity to be ARCHIVED for 3+ hours before it can be permanently DELETED. reddit_ads_delete_* tries the real delete and falls back to archiving (which stops delivery) when it isn't deletable yet. Check the returned configured_status (ARCHIVED vs DELETED) and tell the user a hard delete is possible ~3h after archiving.
CRITICAL: Reporting (reddit_ads_get_report) requires fields, starts_at, and ends_at. Spend metrics come back in micro-currency.
IMPORTANT: Campaigns require name, objective, and (to serve) a funding_instrument_id — list them with reddit_ads_list_funding_instruments. Conversion-optimized ad groups need a conversion_pixel_id (reddit_ads_list_pixels). From 2026-07-13, ad groups and CBO campaigns require conversion_pixel_id.
IMPORTANT: Lead generation works as a campaign objective (LEAD_GENERATION), but lead-gen form management is not available via this toolkit (it needs a feature-gated scope) — build lead-gen forms in Reddit Ads Manager.
CRITICAL (CONVERSIONS campaigns): the ad group optimization_goal is required and, for standard (non-CBO) CONVERSIONS campaigns, the only accepted value is CLICKS. SIGN_UP, PAGE_VISIT, PURCHASE, etc. are valid enum values but are rejected for this campaign type ("Conversion goal ... is not valid for Conversions Campaigns"). Reddit validates in two layers — enum membership, then campaign-type allowance. Use optimization_goal="CLICKS"; the CONVERSIONS objective still governs delivery.
CRITICAL (post types): valid post type values are IMAGE, VIDEO, CAROUSEL, TEXT — not LINK. TEXT posts are "free-form ads": they cannot carry a click_url and CANNOT be used in CONVERSIONS-campaign ads. For any ad with a destination (especially CONVERSIONS), promote an IMAGE / VIDEO / CAROUSEL post.
CRITICAL (creating posts with new media): prefer reddit_ads_create_structured_post — it takes media as a URL that Reddit downloads and re-hosts, so it needs no pre-uploaded asset. Creation is an async job: the tool polls up to wait_seconds (default 45) and returns the job; on status="SUCCESS" use job.post_id as the ad's post_id, else poll reddit_ads_get_structured_post_job. IMAGE needs media_url + destination_url; VIDEO also needs thumbnail_url; CAROUSEL takes 1–6 {image_url, destination_url, ...} cards; PROMOTED_POST promotes an existing SFW community post by id. call_to_action is a display label ("Sign Up", "Learn More"), never "SIGN_UP". The legacy reddit_ads_create_post cannot fetch media by URL — its content[].media_url must reference an already-uploaded Reddit asset (reddit_ads_list_creative_assets), CTA lives inside content[], and TEXT posts must have an empty content[]. Use the legacy tool only to reuse an existing asset.
IMPORTANT: Posts are immutable after creation except comments — to change headline/media/destination, create a new structured post. reddit_ads_update_post(post_id=..., allow_comments=...) only toggles comments (set is_structured_post=True for structured posts).
Tool surface
| Group | Tools |
|---|
| Identity & discovery | reddit_ads_get_me, reddit_ads_list_businesses, reddit_ads_list_ad_accounts, reddit_ads_get_ad_account, reddit_ads_list_funding_instruments |
| Campaigns | reddit_ads_list_campaigns, reddit_ads_get_campaign, reddit_ads_create_campaign, reddit_ads_update_campaign, reddit_ads_delete_campaign |
| Ad groups | reddit_ads_list_ad_groups, reddit_ads_get_ad_group, reddit_ads_create_ad_group, reddit_ads_update_ad_group, reddit_ads_delete_ad_group |
| Ads | reddit_ads_list_ads, reddit_ads_get_ad, reddit_ads_create_ad, reddit_ads_update_ad, reddit_ads_delete_ad |
| Posts & creative | reddit_ads_list_profiles, reddit_ads_get_profile, reddit_ads_list_posts, reddit_ads_create_post, reddit_ads_get_post, reddit_ads_update_post, reddit_ads_list_creative_assets, reddit_ads_get_creative_asset |
| Structured posts (media by URL) | reddit_ads_create_structured_post, reddit_ads_get_structured_post_job, reddit_ads_list_structured_posts, reddit_ads_get_structured_post |
| Targeting | reddit_ads_search_targeting, reddit_ads_suggest_keywords, reddit_ads_validate_keywords, reddit_ads_validate_geolocations |
| Audiences | reddit_ads_list_custom_audiences, reddit_ads_create_custom_audience, reddit_ads_get_custom_audience, reddit_ads_delete_custom_audience, reddit_ads_update_custom_audience_users, reddit_ads_list_saved_audiences, reddit_ads_create_saved_audience, reddit_ads_get_saved_audience, reddit_ads_update_saved_audience |
| Pixels & Conversions API | reddit_ads_list_pixels, reddit_ads_list_pixels_by_business, reddit_ads_post_conversion_events, reddit_ads_get_pixel_last_fired_at |
| Forecasting & access | reddit_ads_generate_bid_suggestion, reddit_ads_get_reach_forecast, reddit_ads_get_feature_access |
| Apps / SKAdNetwork | reddit_ads_list_apps, reddit_ads_get_skan_availability, reddit_ads_get_app_last_fired_at_report |
| Reporting & history | reddit_ads_get_report, reddit_ads_get_account_history |
All reference files live in references/. Read them at references/<file> (e.g. references/discovery.md).
Routing table
Campaign Workflow
Discover business/account → audit account → research (objective, targeting, budget, post) → resolve targeting IDs → confirm strategy → create campaign (PAUSED) → create ad group → find/create post → create ad → review with user → activate (update_* to ACTIVE).
Known Limitations
| Issue | Workaround |
|---|
| No instant hard delete; "A campaign must be archived before it can be deleted" / "cannot be deleted until three hours after it was archived" | Expected — delete_* auto-archives (stops delivery); hard delete is possible ~3h after archiving. Re-run delete later to remove permanently. |
Ad creation needs a post_id | Promote an existing community post (list_posts) or create one (create_post); only community posts can be promoted via the API. |
| Conversion ad groups rejected without a pixel | Set conversion_pixel_id (from list_pixels). Required for ad groups / CBO from 2026-07-13. |
| Campaign won't serve | Attach a funding_instrument_id (from list_funding_instruments); the account must be funded. |
| Lead-gen forms can't be created via API | Build the form in Reddit Ads Manager; the API only sets the LEAD_GENERATION objective. |
| Variant create fields (targeting, schedule, creative) aren't named params | Pass them through input_data (a dict), which is merged into the request body. |
| No flat ad-account list | Discover via get_me → list_businesses → list_ad_accounts(business_id). |
"You cannot set invalid communities: {t5_...}" | The targeting.communities array wants subreddit names, not the t5_ IDs from search_targeting. Use the name field. |
"Cannot set start_time ... without ... campaign budget optimization" | Campaign-level start_time is CBO-only. Omit it on non-CBO campaigns; set start_time on the ad group. |
Ad group create: "Input should be a valid datetime" on start_time | start_time is required on ad groups — always pass it. |
bid_value demanded despite MAXIMIZE_VOLUME | bid_value is always required for CPC/CPM/CPV/CPV6. Provide a cap or use generate_bid_suggestion. |
generate_bid_suggestion: "Additional fields not permitted" / "'start_time' is a required property" | duration is an ISO start/end range ({"start_time": ..., "end_time": ...}), not {"days": N}. |
| Varnish 503 on create | Transient Reddit backend error. Verify no duplicate was created (list_campaigns) before retrying. |
effective_status shows PENDING_APPROVAL right after create | Normal even for PAUSED entities (ad review) — it clears automatically; not a failure. |
CONVERSIONS ad group: "Conversion goal (optimization goal) is required" / "... is not valid for Conversions Campaigns" | optimization_goal is required and, for non-CBO CONVERSIONS, must be CLICKS (SIGN_UP/PAGE_VISIT/PURCHASE are rejected for this campaign type). |
"'LINK' is not one of [CAROUSEL, IMAGE, TEXT, VIDEO]" | Post type must be IMAGE/VIDEO/CAROUSEL/TEXT — there is no LINK type. |
Ad create: "Posts used for ads in Conversion campaigns cannot be free-form ad" / "Free form ads cannot have a click url" | TEXT posts are free-form — use IMAGE/VIDEO/CAROUSEL for CONVERSIONS ads. |
IMAGE post: "Image is required" | With legacy create_post, put the asset in content[].media_url (an already-uploaded Reddit asset from list_creative_assets); a post_url alone is not enough. To create from a fresh media URL, use reddit_ads_create_structured_post instead. |
Structured post job not done yet (status QUEUED/PROCESSING) | Creation is async; the create tool polls to wait_seconds (default 45). If still pending, poll reddit_ads_get_structured_post_job(post_creation_job_id=...) until SUCCESS (then use post_id) or CLIENT_ERROR/SERVER_ERROR (read error_message). |
| Need to change a post's headline/media/destination | Not possible — posts are immutable. Create a new structured post. reddit_ads_update_post only toggles allow_comments. |
Post: call_to_action "Additional fields not permitted" | call_to_action belongs inside content[], not top-level, and uses display labels ("Sign Up"), not enum constants ("SIGN_UP"). |
TEXT post: "Post content must be empty for this post type" | TEXT posts can't carry a content[] block — only IMAGE/VIDEO/CAROUSEL do. |
| Dollar amounts | Always micro-currency (×1,000,000). |
Safety Rules
Never:
- Assume business, ad account, campaign, post, pixel, or targeting IDs — look them up or ask.
- Skip the account audit phase.
- Create campaigns, ad groups, or ads without explicit user approval.
- Set anything to
ACTIVE without user consent.
- Pass dollar amounts instead of micro-currency.
- Create an ad without a valid
post_id.
- Promise an instant permanent delete — Reddit requires ARCHIVED for 3+ hours first.
- Guess targeting IDs — resolve them with
reddit_ads_search_targeting.