Developer API

SellerMate Public API

Beta

Programmatic, key-authenticated access to SellerMate’s tools — campaign analytics, targeting, reports, and (with the right scope) budget/bid changes and campaign creation. The public API is a thin, stable surface over the same engine that powers SellerMate’s MCP / AI agent, so every tool is permission-checked, policy-guarded, and audit-logged.

Production base URL

https://api.sellermate.ai

Version prefix

/public/v1

Beta: the Public API is stable enough to build on, but endpoints and response shapes may still change. Treat GET /public/v1/tools as the source of truth.

In the examples below, {BASE} means your SellerMate API host (the production base URL above).

1.

Authentication

Every request to /public/v1/* must carry an API key. Send it either way:

1X-API-Key: sm_live_xxxxxxxxxxxxxxxxxxxx

or

1Authorization: Bearer sm_live_xxxxxxxxxxxxxxxxxxxx
  • Keys look like sm_live_….
  • A key is created by a workspace admin in the SellerMate web app (Profile → API Keys) and is shown once, at creation — store it securely; it cannot be retrieved later.
  • A key is scoped to a single workspace.
  • Repeated failed auth attempts from an IP are locked out (see §3).
2.

Authorization model

Three independent layers apply to every call — all must pass:

LayerWhat it controls
Key scopestools:read (analytics/reports) and/or tools:write (mutations). A read-only key cannot call write tools.
Account bindingA key is bound to its workspace. It may optionally be restricted to a subset of Amazon accounts; if so, it can only act on those accounts.
Workspace policiesWrite actions still pass through the workspace’s policies (bid/budget min-max, neverPause, ACOS guards) and approval rules. A blocked action returns 422; an action requiring approval returns a pending status.

workspace_id and amazon_account_id are bound to the key and injected by the server — you normally don’t send them (see §4 → “How arguments work”).

3.

Rate limiting & abuse protection

Two independent throttles apply:

Per-key request limit. Each valid key has a per-minute request limit (default 120/min). Exceeding it returns:

1HTTP 429 Too Many Requests
2Retry-After: 37
3{ "status": 429, "message": "Rate limit exceeded. Slow down and retry." }

Per-IP failed-auth lockout (brute-force protection). After 10 failed auth attempts from one IP within a minute, that IP is locked out for ~15 minutes (429 + Retry-After). Honor Retry-After, and don’t retry-storm on a 401 — a bad key won’t start working, and repeated failures lock your IP.

Shared egress IPs (offices / CI / fixed servers): if several legitimate integrations leave from one IP, ask an admin to add it to the server-side trusted-IP allowlist (exact IPs or CIDRs) so the failed-auth lockout never applies to it.
4.

Conventions

  • All requests/responses are JSON. Send Content-Type: application/json on POST.
  • Successful tool calls return the tool’s result object directly (no envelope).
  • Error shapes: auth / rate-limit / lockout failures are { "status": <code>, "message": "..." }; tool-level errors are { "error": "..." } (policy violations add rule, scope, message).

HTTP status codes

CodeMeaning
200Success — body is the tool result.
400Invalid arguments (missing/malformed parameters).
401Auth failed. Always a generic { "message": "Invalid API key" } — missing, unknown, expired, and revoked keys are indistinguishable by design (prevents key enumeration).
403Key scope doesn't permit this tool, or the account isn't allowed for this key.
404Unknown tool (also returned for tools your scope can't see).
422A workspace policy rejected a write (body includes rule/scope/message).
429Rate limit exceeded or too many failed auth attempts (IP lockout). See Retry-After.
500Internal error.

How arguments work (read this once)

Every tool is called as POST /public/v1/tools/{name} with a JSON object of arguments in the body. A few rules apply across all tools — once you know them, each tool below only lists what’s unique to it.

  • Auto-injected identity — you usually omit these:
    • workspace_id is always taken from your key; anything you send is ignored.
    • amazon_account_id is injected automatically if your key is limited to one account. If your key spans multiple/all accounts, pass amazon_account_id to choose one (get the IDs from get_user_context). The lone exception is get_marketplace_summary, which takes amazon_account_ids (a list) to span accounts.
  • Required vs optional: arguments marked Required must be present; everything under Optional has a sensible default (noted inline). Sending an unknown field is ignored.
  • Dates: start_date / end_date are strings in YYYY-MM-DD. (Exception: get_sqp_report uses integer month + year.)
  • Pagination:
    • Performance/list tools use page (0-indexed, default 0) and page_size (default 100, max 500).
    • list_product_catalog and get_inventory use limit (default 50, max 200) and offset (default 0).
    • get_sqp_report uses page + page_size (default 50, max 200).
  • Sorting (performance tools): sort_field (a metric name) + sort_direction (asc | desc, default desc).
  • Grouping (performance tools): group_by is an array of dimensions to roll metrics up by; each tool has its own allowed dimensions and default. Time dimensions (week, month, year) give trend breakdowns.
  • Common metric names: cost (spend), attributedSales14d (sales), impressions, clicks, purchases (orders), acos, roas, ctr, cpc, cvr.
  • Tags (ads-metric tools): tag_values filters to entities carrying those legacy tag labels; group_by_tag: true returns one row per tag. Tag inventory comes from get_tags.
  • Authoritative schema: GET /public/v1/tools/{name} returns the live JSON Schema for any tool — the source of truth if this doc and the API ever differ.
5.

Endpoints

GET /public/v1/tools

List the tools your key can use (filtered to its scope). Each entry includes the tool’s JSON Schema, so this doubles as machine-readable discovery.

1curl -s {BASE}/public/v1/tools -H "X-API-Key: sm_live_..."
2# { "tools": [ { "name": "...", "description": "...", "inputSchema": {...} }, ... ] }

GET /public/v1/tools/{name}

Return the JSON Schema for one tool. 404 if unknown or outside your scope.

POST /public/v1/tools/{name}

Invoke a tool. Body = the tool’s arguments (§4). Returns the raw tool result.

1curl -s -X POST {BASE}/public/v1/tools/get_campaign_performance \
2 -H "X-API-Key: sm_live_..." -H "Content-Type: application/json" \
3 -d '{"start_date":"2026-05-01","end_date":"2026-05-31"}'
6.

Tools reference

Scope is shown per tool (read = needs tools:read; write = needs tools:write). workspace_id / amazon_account_id are auto-injected per §4 and omitted below.

Discovery

get_user_contextread

Your accessible workspaces and Amazon accounts (scoped to the key). Call this first to get the amazon_account_id values the other tools need.

Arguments: none. Returns: user, and workspaces[] each with accounts[] (id, name, country, currency, marketplace, advertiser_id).

get_sellermate_capabilitiesread

What the SellerMate platform supports beyond these API tools (with deep links).

Optional: query (string — what you’re trying to do, e.g. "dayparting", to highlight relevant features).

Campaigns

list_campaignsread

Campaign inventory (no metrics) — names, state, budget, type, targeting type.

Optional:

  • status — string[] of ENABLED | PAUSED | ARCHIVED (default ["ENABLED"]).
  • sponsored_type — string[] of Product | Brand | Display.
  • name_search — string, case-insensitive partial match (returns any state).
get_campaign_performanceread

Ads-only performance per campaign for a date range (spend, sales, ACOS, ROAS, impressions, clicks, CTR, CPC, orders, CVR + summary).

Required: start_date, end_date.

Optional: campaign_ids (string[]), campaign_name (partial match), status (string[]; default ENABLED), tag_values (string[]), group_by_tag (bool — one row per tag).

get_marketplace_summaryread

Aggregated ads metrics per account across the workspace.

Required: start_date, end_date. Optional: amazon_account_ids — string[] (defaults to all accounts the key can reach). This tool spans accounts, so it takes a list rather than the single injected amazon_account_id.

update_campaign_budgetwrite

Set absolute daily budgets on one or more campaigns. Passes through workspace budget policy (may be blocked → 422, or queued for approval).

Required: updates — array (1–50) of { campaign_id, new_budget } where campaign_id is the Amazon campaignId from list_campaigns and new_budget is a number > 0. Optional: _reasoning — string, stored in the audit log (recommended).

create_campaignwrite

Create one Sponsored Products campaign. Asynchronous — returns status:"processing" and a session_id; poll get_campaign_creation_status (~30–60s later). Subject to the campaignCreate policy (budget cap, allowed targeting types, approval).

Required:

  • name — string, unique within the account.
  • sponsored_type"Product" (only type supported today).
  • targeting_type"AUTO" (Amazon picks targets; no keywords/product targets allowed) or "MANUAL" (requires at least one keyword or product target).
  • daily_budget — number > 0 (account currency; capped by maxStartingBudget).
  • ad_group — object: { name, default_bid (>0), products: [{ asin, sku?, state? }] (≥1) }. ASINs must come from list_product_catalog — do not invent them. For MANUAL, also include keywords ({ keyword_text, match_type (BROAD|EXACT|PHRASE), bid, state }) and/or product_targets; optional negative_keywords / negative_product_targets.

Optional: state (ENABLED default | PAUSED), dynamic_bidding ({ strategy, placementBidding }), _reasoning.

get_campaign_creation_statusread

Poll an async create_campaign job.

Required: session_id (from create_campaign). Returns: status (pending | in_progress | completed | failed), per-step outcomes, and the new campaignId under steps.campaign_creation.campaign_ids once assigned.

Targeting

list_targetsread

Individual targets (keywords / product targets / auto targets) — bid, state, match type, keyword text or product expression, parent campaign/ad group. No metrics.

Optional: state (string[] of ENABLED|PAUSED|ARCHIVED; default ENABLED+PAUSED), sponsored_type (Product|Brand|Display), campaign_id, ad_group_id, keyword_text (search), page, page_size, include_tags (bool).

get_targeting_performanceread

Aggregated metrics per target. Default grouping is targetingValue + campaignName.

Required: start_date, end_date. Optional:

  • group_by — string[] from targetingValue, targetingType, campaignName, campaignId, adGroupName, adGroupId, reportType, sponsoredType, tags, week, month, year, dayOfWeek.
  • targeting_type — string[] (keyword: EXACT/PHRASE/BROAD; product: ASIN_SAME_AS/ASIN_BRAND_SAME_AS/ASIN_CATEGORY_SAME_AS/…; auto: LOOSE_MATCH/CLOSE_MATCH/SUBSTITUTES/COMPLEMENTS).
  • targeting_value (single keyword/ASIN), campaign_ids, ad_group_ids, sponsored_type, sort_field, sort_direction, page, page_size.
get_search_term_performanceread

Customer search queries that triggered your ads + their metrics. Default grouping is searchTerm.

Required: start_date, end_date. Optional: group_by (incl. searchTerm, targetingValue, matchType, campaignName, week/month…), search_term (exact filter), campaign_ids, ad_group_ids, targeting_type (string[]), sort_field, sort_direction, page, page_size, tag_values, group_by_tag, include_tags.

update_target_bidwrite

Set absolute bids on keywords/product targets. Passes through workspace bid policy.

Required: updates — array (1–50) of { target_id, new_bid } where target_id is the id from list_targets (same for keywords and product targets) and new_bid is a number > 0. Optional: _reasoning.

Products & reports

get_advertised_product_performanceread

Ads-only metrics per advertised ASIN. (Only products that got ad impressions; for all products use list_product_catalog; for organic/TACoS use get_retail_product_performance.)

Required: start_date, end_date. Optional: ad_asin (single ASIN), ad_product_name, campaign_ids, ad_group_ids, report_type (string[] of spAdvertisedDaily/sbAdvertisedDaily/sdAdvertisedDaily), group_by (incl. adAsin, campaignName, week…), sort_field, sort_direction, page, page_size, tag_values, group_by_tag, include_tags.

get_retail_product_performanceread

Combined retail + ads metrics per ASIN — total revenue, sessions, page views, buy box %, organic-vs-ads, TACoS. Requires Seller Central (SP-API); returns a connect link if not connected.

Required: start_date, end_date. Optional: asin, item_name, listing_type (child_asin default | parent_asin rollup), sort_field (incl. totalSales, sessions, pageViews, unitsOrdered, buyBoxPercentage, tacos, acos, roas…), sort_direction, page, page_size.

get_placement_performanceread

Metrics per placement (Top of Search / Product Page / Rest of Search; SB also Home) per campaign, plus bid-adjustment % and bidding strategy.

Required: start_date, end_date. Optional: sponsored_type (string[] Product/Brand/Displayset this when you want SP-only or SB-only numbers, else totals mix ad types), placement_classification (string[] Top of Search/Product Page/Home/Rest of Search), campaign_ids, campaign_names, campaign_targeting_type (AUTO/MANUAL), state, group_by, metrics, sort_field, sort_direction, page, page_size.

get_sqp_reportread

Amazon Search Query Performance — one row per (ASIN, search query) for a month. Note: this tool uses month + year, not a date range.

Required: month — integer 1–12; year — four-digit integer. Optional: asin (exact), search_query (exact), sort_field (default searchQueryData.searchQueryScore), sort_direction, page, page_size (default 50, max 200 — keep small).

get_orders_reportread

Orders for a date range. Returns aggregate totals + a breakdown by state; raw per-order rows only on request (they can be large).

Required: start_date, end_date. Optional: include_orders (bool, default false — include raw rows), max_orders_per_state (int, default 5, max 50), top_states (int, default 25, max 100), state (case-insensitive contains filter), marketplace_ids (string[]).

get_tagsread

Legacy tag inventory for one entity type — labels, colors, assigned entities, and optionally per-tag metrics.

Required: data_typecampaign | product | targeting | search_term. Optional: include_entities (bool, default true), include_metrics (bool — requires start_date + end_date), tag_labels (string[]), start_date, end_date.

list_product_catalogread

Seller ASINs + SKUs. Requires Seller Central (SP-API). Two modes:

  • Mode 1 (catalog only): omit dates → ASIN, SKU, name, image, price, fulfillment, status, FBM qty.
  • Mode 2 (catalog + performance): pass start_date + end_date → adds retail (and optionally ads) metrics, isAdvertised.

Optional: asins (string[]), skus (string[]), name_search, fulfillment_channel (FBA|FBM|ALL), include_suppressed (bool), limit (default 50, max 200), offset; Mode 2 only: start_date/end_date, include_ads_metrics, include_retail_metrics, unadvertised_only (bool — only products with no ad spend, i.e. create_campaign candidates), max_acos, min_total_revenue, sort_by ({ field, direction }).

get_inventoryread

Per-ASIN stock — FBM quantity, FBA fulfillable/warehouse balance, snapshot date. Requires Seller Central (SP-API).

Optional: asins (string[]), view (merged default | fbm | fba), limit (default 50, max 200), offset.

The exact tool set is whatever GET /public/v1/tools returns for your key — new platform tools appear there automatically.
7.

Worked examples

Discover accounts — get_user_context

1curl -s -X POST {BASE}/public/v1/tools/get_user_context \
2 -H "X-API-Key: sm_live_..." -H "Content-Type: application/json" -d '{}'

Response

1{
2 "user": { "id": "...", "name": "API Key: Reporting", "role": 1 },
3 "workspaces": [
4 { "id": "<workspace_id>", "name": "Acme",
5 "accounts": [
6 { "id": "<amazon_account_id>", "name": "Acme US", "country": "US",
7 "currency": "USD", "marketplace": "ATVPDKIKX0DER", "advertiser_id": "..." }
8 ] }
9 ]
10}

Read metrics — get_campaign_performance

1curl -s -X POST {BASE}/public/v1/tools/get_campaign_performance \
2 -H "X-API-Key: sm_live_..." -H "Content-Type: application/json" \
3 -d '{"amazon_account_id":"<id>","start_date":"2026-05-01","end_date":"2026-05-31","status":["ENABLED","PAUSED"]}'

Returns { "data": [ {campaign metrics} ], "summary": {...}, "dateRange": {...}, "total": N }.

Write a budget — update_campaign_budget (needs tools:write)

1curl -s -X POST {BASE}/public/v1/tools/update_campaign_budget \
2 -H "X-API-Key: sm_live_..." -H "Content-Type: application/json" \
3 -d '{
4 "updates": [ { "campaign_id": "<campaignId from list_campaigns>", "new_budget": 25.0 } ],
5 "_reasoning": "Scaling a profitable campaign"
6 }'

Outcomes:

  • Applied: { "status": "success", "applied": true, "results": [...] }
  • Policy-blocked (422): { "error": "Policy violation [maxBudget] …", "rule": "maxBudget", ... }
  • Needs approval: { "status": "pending_approval", "applied": false, "rollback_token": "..." }

Create a campaign — create_campaign (async, needs tools:write)

1curl -s -X POST {BASE}/public/v1/tools/create_campaign \
2 -H "X-API-Key: sm_live_..." -H "Content-Type: application/json" \
3 -d '{
4 "name": "SP - Auto - Hero ASINs",
5 "sponsored_type": "Product",
6 "targeting_type": "AUTO",
7 "daily_budget": 20.0,
8 "ad_group": {
9 "name": "Auto AG",
10 "default_bid": 0.75,
11 "products": [ { "asin": "B0XXXXXXXX" } ]
12 },
13 "_reasoning": "Launch auto campaign for top unadvertised ASIN"
14 }'
15# -> { "status": "processing", "session_id": "..." } then poll:
16curl -s -X POST {BASE}/public/v1/tools/get_campaign_creation_status \
17 -H "X-API-Key: sm_live_..." -H "Content-Type: application/json" \
18 -d '{"session_id":"..."}'
8.

Python quickstart

1import requests
2
3BASE = "https://api.sellermate.ai"
4KEY = "sm_live_..."
5H = {"X-API-Key": KEY, "Content-Type": "application/json"}
6
7def call(tool, **args):
8 r = requests.post(f"{BASE}/public/v1/tools/{tool}", headers=H, json=args, timeout=120)
9 r.raise_for_status()
10 return r.json()
11
12ctx = call("get_user_context")
13account_id = ctx["workspaces"][0]["accounts"][0]["id"]
14
15perf = call("get_campaign_performance",
16 amazon_account_id=account_id,
17 start_date="2026-05-01", end_date="2026-05-31")
18print(perf["summary"])

A fuller demo/diagnostic client lives at scripts/sm_api_demo.py.

9.

Notes & limits

  • Per-call batch cap: write tools accept at most 50 items in updates per call.
  • One-time secret: a key’s plaintext is shown only at creation; lost keys must be revoked and recreated.
  • Revocation is immediate: a revoked key returns 401 on the next call.
  • Generic auth errors + IP lockout: all auth failures look identical (401 Invalid API key), and repeated failures from one IP are locked out (§3). Don’t loop on a 401.
  • CORS: the API is for server-to-server use with a secret key. Don’t embed keys in browser/client-side code.
  • Discovery is authoritative: GET /public/v1/tools (and /tools/{name}) is the source of truth for available tools and their parameters.
Ready to build? Create an API key in the app (Profile → API Keys) and start with get_user_context.
Book Demo