Developer reference

Apex MCP server reference

Apex runs a Model Context Protocol server so an AI assistant can read a seller’s own Apex data and, with a separate write link on the Pro plan, prepare drafts. This page is the reference for the endpoint, keys, permissions, tools, limits and errors. For setup in a specific assistant, see the Claude and ChatGPT guides.

Endpoint
https://app.apexapplications.io/api/mcp
Transport
Streamable HTTP, stateless
Auth
Per-seller connector key
Tools
16 read, 3 draft

Endpoint and transport

POST https://app.apexapplications.io/api/mcp with the key as a bearer token, or POST https://app.apexapplications.io/api/mcp/apx_YOUR_KEY for clients that only accept a URL.

  • Stateless Streamable HTTP: one JSON-RPC 2.0 message (or a batch array) per POST, plain JSON back. No sessions and no server-to-client stream.
  • GET answers 405. Notifications (requests without an id) answer 202 with no body.
  • Supported protocol versions: 2025-06-18, 2025-03-26, 2024-11-05. The server answers with the version the client asked for when it is one of these, otherwise the newest.
  • Methods: initialize, ping, tools/list, tools/call.
List the tools
curl -s https://app.apexapplications.io/api/mcp \
  -H "Authorization: Bearer apx_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Keys and authentication

A seller makes keys in Apex under Connect your AI in the account menu. A key belongs to one Apex account and the user who made it. Apex stores only a hash of it and shows the plain key once.

  • Read keys see the read tools only. This is the default.
  • Write keys also see the draft tools. Making one needs the Pro plan and edit permission for purchase orders, products and vendors.
  • Up to 10 live keys per account, of which up to 3 may be write keys.
  • Keys in a URL can end up in logs and browser history. Prefer the header form where the client supports it, and turn off any key you have exposed.

OAuth is not supported yet. It is planned.

Permission enforcement

Every tool runs the same plan and permission checks as the page it mirrors in the Apex app, using the permissions of the user who made the key, read again on every call. A key never sees more than that user does, and the account always comes from the key, never from the arguments.

  • Read tools: a paid Apex plan (the trial counts) plus the matching view permission.
  • Draft tools: a write key, the Pro plan checked on every call, and the matching edit permissions. A downgrade stops an existing write key from drafting.
  • A read key that calls a draft tool anyway is refused and the attempt is logged.

Reads and drafts

Read tools carry readOnlyHint: true. Draft tools carry readOnlyHint: false, destructiveHint: false and idempotentHint: true, which is what makes clients such as ChatGPT and Claude ask the user before each call.

Draft tools only create drafts: an open purchase order that is never submitted, products added as drafts that are never activated, or a new supplier. Each returns what it made and a link to review it in Apex. No tool can submit or send a purchase order, contact a supplier, spend money, create or send a shipment, change a live price or repricer setting or delete anything.

create_draft_purchase_order accepts a requestId. The same id within 24 hours returns the first order instead of creating a second.

Tools

Names, descriptions and arguments exactly as tools/list returns them.

Read tools

get_business_snapshot

Read, any link

High-level counts for the seller's Apex account: ASINs in their product database, how many are profitable, how many profitable ones they already sell versus not yet, supplier count and plan. Call this first for general questions about how the business is doing.

No arguments.

get_profitable_opportunities

Read, any link

Profitable ASINs in the seller's database that they are NOT currently selling, best profit first. Use for 'what should I source next' or 'what am I missing'.

Arguments for get_profitable_opportunities
ArgumentTypeRequiredDescription
limitintegerNoHow many to return (1-25, default 10)1 to 25

get_restock_recommendations

Read, any link

Profitable products the seller already sells that are lowest on stock. Use for 'what should I reorder' or 'what is running out'.

Arguments for get_restock_recommendations
ArgumentTypeRequiredDescription
limitintegerNoHow many to return (1-25, default 10)1 to 25

get_growth_gaps

Read, any link

Structural gaps holding the seller back: empty database, no or few suppliers, untapped profitable ASINs, lower plan. Use before suggesting what to work on next.

No arguments.

get_profit_and_loss

Read, any link

Monthly profit and loss from Amazon sales for the last N months: sales, units, refunds, fees, cost of goods and gross profit per month. Use for 'how did I do in August' or 'is profit trending up'.

Arguments for get_profit_and_loss
ArgumentTypeRequiredDescription
monthsintegerNoMonths to include (1-24, default 12)1 to 24

get_profit_and_loss_statement

Read, any link

Profit and loss statement over a date range, bucketed by day, week or month (Sellerboard-style). Dates are YYYY-MM-DD. Defaults to the last 12 months by month. A range by day may cover at most about three months, by week about two years.

Arguments for get_profit_and_loss_statement
ArgumentTypeRequiredDescription
bystringNoBucket sizeday | week | month
fromstringNoStart date, YYYY-MM-DD
tostringNoEnd date, YYYY-MM-DD (default today)

search_products

Read, any link

Search the seller's product database (Apex Blue Databases): every ASIN they have sourced with cost, Buy Box price, profit, ROI, margin, stock and rank. Search matches ASIN, UPC, supplier SKU and title. Leave search empty to page through everything. Sort with orderBy like 'grossBuyBox:DESC' or 'roi:DESC'.

Arguments for search_products
ArgumentTypeRequiredDescription
searchstringNoASIN, UPC, supplier SKU or words from the title
orderBystringNoColumn and direction, e.g. grossBuyBox:DESC, margin:DESC, salesRank:ASC
pageintegerNoPage number (default 1)1 to any
limitintegerNoRows per page (1-50, default 20)1 to 50

list_catalog_scans

Read, any link

Catalog scans the seller has run through the UPC Scanner (Apex Green): one row per uploaded supplier catalog with its name, supplier, when it ran, line count and how many products it found, newest first. Pass vendorId (the supplier's id from get_purchase_orders' vendor.id or the Apex suppliers list) to see only that supplier's scans. Use the scan id with get_catalog_scan_results. For 'which profitable products does this supplier have that I do not have yet': call this with the supplier, take the latest scan id, then call get_catalog_scan_results with onlyNew=true and orderBy='profit:DESC'.

Arguments for list_catalog_scans
ArgumentTypeRequiredDescription
vendorIdstringNoOnly this supplier's scans (default: all suppliers)
limitintegerNoMost recent N scans (1-50, default 20)1 to 50

get_catalog_scan_results

Read, any link

Products found in one catalog scan with cost, Amazon price, profit, ROI, margin, rank and seller counts. Search matches title, brand, ASIN or UPC. Sort with orderBy like 'profit:DESC' or 'roi:DESC'. Every row has inDatabase: true when the seller already holds that ASIN as an active product in their database. Set onlyNew=true to return only products NOT yet in their database (total then counts just those). That, with orderBy='profit:DESC', answers 'which profitable products does this supplier have that I do not have yet': find the scan with list_catalog_scans, then call this.

Arguments for get_catalog_scan_results
ArgumentTypeRequiredDescription
scanIdstringYesScan id from list_catalog_scans
searchstringNoTitle, brand, ASIN or UPC
orderBystringNoColumn and direction, e.g. profit:DESC, roi:DESC, salesRank:ASC
onlyNewbooleanNoOnly products the seller does not already have in their database (default false)
pageintegerNoPage number (default 1)1 to any
limitintegerNoRows per page (1-50, default 20)1 to 50

get_purchase_orders

Read, any link

The seller's purchase orders (Apex Blue Purchase Orders page): vendor, order date, status, number of lines, units, total landed cost, projected revenue, profit, ROI and margin, destination warehouse, expected arrival. status='open' (default) is the page's Open tab: orders still being built, not yet submitted (status 'draft'). status='all' adds the Closed tab: submitted orders, each 'submitted' (sent, no shipment yet), 'in_transit' (inbound shipment created, not arrived) or 'received' (arrived). Projections use the Buy Box price, or the line's target price where one is set, minus fees and landed cost. Search matches vendor name, ASIN or product title. Newest first.

Arguments for get_purchase_orders
ArgumentTypeRequiredDescription
statusstringNo'open' (default): draft orders not yet submitted. 'all': also submitted, in transit and receivedopen | all
searchstringNoVendor name, ASIN or words from a product title
limitintegerNoOrders to return (1-50, default 20)1 to 50

get_repricer_listings

Read, any link

The seller's live Amazon listings as the repricer (Apex Gold) sees them: your price, Buy Box price, lowest offer, stock, 7 and 30 day units, fees, break-even and the strategy applied. Search matches SKU, ASIN or title.

Arguments for get_repricer_listings
ArgumentTypeRequiredDescription
searchstringNoSKU, ASIN or words from the title
limitintegerNoRows to return (1-100, default 25)1 to 100

get_repricer_impact

Read, any link

What the repricer has been worth: units and revenue within seven days of a price it changed and Amazon accepted, with margin before and after.

No arguments.

get_map_compliance

Read, any link

Minimum advertised price (MAP) status by brand. Without a brand: one row per brand with how many active listings it has and how many have MAP enforcement on. With a brand: that brand's listings with MAP price, whether enforcement is on, and the current listing price.

Arguments for get_map_compliance
ArgumentTypeRequiredDescription
brandstringNoBrand name as returned in the summary (case-insensitive)
onlyEnforcedbooleanNoOnly brands or listings with MAP enforcement on
limitintegerNoRows to return (1-200, default 100)1 to 200

get_inventory

Read, any link

FBA inventory per SKU with available, reserved and inbound units, sales velocity, days of inventory, stock status (Out of Stock, Restock, Enough Stock, Overstock), recommended restock and aged units. view='aging' narrows to SKUs with units past the aging line. Sort by any column, e.g. sortKey='daysOfInventory'.

Arguments for get_inventory
ArgumentTypeRequiredDescription
searchstringNoSKU, ASIN or words from the title
viewstringNo'all' (default) or 'aging'all | aging
sortKeystringNoColumn to sort by (default availableInventory)
sortOrderstringNoasc or desc (default desc)asc | desc
pageintegerNoPage number (default 1)1 to any
limitintegerNoRows per page (1-50, default 20)1 to 50

search_brands

Read, any link

Find brands to source from (Apex Green Brands): one row per brand with how many products Amazon lists for it, average price, average sellers per listing, share sold by Amazon, rating and average sales rank. search matches the brand name; category narrows to a department such as 'Health & Household'. Leave search empty to browse (free). Naming a brand counts toward the plan's monthly brand-search allowance exactly as typing it in the app does (a brand already looked at this month costs nothing again), and an empty search costs nothing. The sourcing loop: search_brands to pick a brand, research_products with that brand and inMyDatabase='hide' to find what is not yet in the seller's database, then add_products_to_database or create_draft_purchase_order (write links only).

Arguments for search_brands
ArgumentTypeRequiredDescription
searchstringNoBrand name, or part of it
categorystringNoDepartment, e.g. 'Grocery & Gourmet Food' (optional)
limitintegerNoBrands to return (1-25, default 10)1 to 25

research_products

Read, any link

Search Amazon products the way the Apex Products page does (Apex Green): ASIN, title, brand, price, sales rank, estimated monthly sales, number of sellers, whether Amazon sells it, estimated net proceeds after fees, and inDatabase (true when the seller already holds it as an active product). Give a brand (from search_brands) for the best results; browsing everything is slow and arbitrary. Set inMyDatabase='hide' to see only products the seller does not already have, which is the right setting before adding anything. soldByAmazon='no' leaves out products Amazon sells itself. orderBy is a column and direction such as 'salesRank:ASC', 'price:DESC', 'sellersCount:ASC' or 'estimatedMonthlySales:DESC'. Next steps for a good product: add_products_to_database or create_draft_purchase_order (write links only; they need the seller's cost from the supplier).

Arguments for research_products
ArgumentTypeRequiredDescription
brandstringNoBrand name (a partial name is matched)
searchstringNoASIN or words from the title; comma separate several ASINs
salesRankMinintegerNoBest (lowest) sales rank to include1 to any
salesRankMaxintegerNoWorst (highest) sales rank to include1 to any
sellersMinintegerNoFewest sellers on the listing0 to any
sellersMaxintegerNoMost sellers on the listing0 to any
priceMinnumberNoLowest price in USD0 to any
priceMaxnumberNoHighest price in USD0 to any
soldByAmazonstringNo'yes' only Amazon-sold, 'no' leaves those out, 'all' (default) bothyes | no | all
inMyDatabasestringNo'all' (default), 'hide' what the seller already has, 'only' what they already haveall | hide | only
orderBystringNoColumn:DIRECTION, e.g. salesRank:ASC or estimatedMonthlySales:DESC
limitintegerNoProducts to return (1-50, default 20)1 to 50
pageintegerNoPage number (default 1)1 to any

Draft tools (write keys, Pro)

create_draft_purchase_order

Draft, write link, Pro

Create a DRAFT purchase order for one supplier in the seller's Apex Blue Purchase Orders page (it appears on the Open tab). It is never submitted: the seller reviews and submits it in Apex. Give the supplier (id or name) and lines of {asin, quantity, unitCost?}. An ASIN already in the database under that supplier uses its cost unless you give unitCost (then only this order's line cost is set, the database is untouched); an ASIN that is not there needs unitCost and is added to the database as a draft product. Destination and notes are chosen in Apex when the order is submitted, not here. Pass a requestId so a retry cannot make a second order. Ask the seller for costs and quantities; never invent them.

Arguments for create_draft_purchase_order
ArgumentTypeRequiredDescription
vendorstringYesSupplier id, or the supplier's name (a close match is accepted)
linesarrayYesUp to 50 products to ordermax 50 items
lines[].asinstringYes10-character ASIN
lines[].quantityintegerYesUnits to order (1-100,000)1 to 100000
lines[].unitCostnumberNoCost per unit in USD. Optional when the ASIN is already in the database under this supplier (its cost is used); required otherwise0 to any
requestIdstringNoAny unique text for this order. Sending the same requestId again within 24 hours returns the first order instead of making another, so a retry is safe

add_products_to_database

Draft, write link, Pro

Add products to the seller's Apex Blue database as DRAFTS (the Drafts tab of the Databases page), exactly like uploading the bulk-upload template. Each item is {asin, unitCost, vendor?, casePack?, vendorSku?}: unitCost is the seller's cost per unit from the supplier, never a guess; every product needs a supplier, given per item or once as the top-level vendor (a name or id; it must already exist, see add_vendor); casePack defaults to 1. A product already in the database is skipped and reported, never duplicated. Nothing is made active: the seller reviews the drafts in Apex.

Arguments for add_products_to_database
ArgumentTypeRequiredDescription
vendorstringNoSupplier for every item that does not name its own (name or id)
itemsarrayYesUp to 100 productsmax 100 items
items[].asinstringYes10-character ASIN
items[].unitCostnumberYesCost per unit in USD0 to any
items[].vendorstringNoSupplier name or id (overrides the top-level vendor)
items[].casePackintegerNoUnits per case (default 1)1 to any
items[].vendorSkustringNoThe supplier's own SKU (optional)

add_vendor

Draft, write link, Pro

Add a supplier to the seller's Apex Blue Vendors page, the way its Add vendor form does (it starts as a lead on the pipeline board). Name is required; website and email are optional. If a supplier with that name already exists nothing is created and the existing one is returned. Apex suppliers have no notes field, so put anything else in the conversation, not here.

Arguments for add_vendor
ArgumentTypeRequiredDescription
namestringYesSupplier name
websitestringNoWebsite (optional)
emailstringNoContact email (optional)

Results and paging

A successful tools/call returns the result twice: as text in content for the model, and as the same object in structuredContent for clients that read JSON.

Example result, illustrative values
{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [{ "type": "text", "text": "{ \"items\": [ ... ] }" }],
    "structuredContent": {
      "items": [
        { "title": "Example product A", "daysOfInventory": 6, "recommendedQty": 120 }
      ]
    }
  }
}

Lists are capped so results fit a model’s context: most tools take a limit (typically up to 25 or 50) and a page, and return a total so the caller can ask for more. Money is rounded to two places.

Rate limits and quotas

  • 60 calls a minute per key, and 4 calls in flight per account.
  • Write keys: 10 draft calls a minute per key, and 100 draft-creating calls per account per UTC day.
  • Purchase orders: 1 to 50 lines, quantities 1 to 100,000. Products: up to 100 per call.
  • search_brands and research_products spend the plan’s monthly brand searches exactly as the app does.
  • The minute limits are enforced per server instance, as a guard against runaway loops rather than an exact quota.

Errors

HTTP 401
No key, an unknown key, or a key that has been turned off.
HTTP 405
A GET request. The server takes POST only.
JSON-RPC -32600
The body is not a JSON-RPC 2.0 request.
JSON-RPC -32601
An unknown method.
A tool result with isError: true
The call reached the tool but was refused or failed: an unknown tool, a missing plan or permission, a read key calling a draft tool, a rate or daily limit, or invalid arguments. The text explains it in plain words so the assistant can pass it on, for example “This link is read-only. Make a write link in Connect your AI.”

Audit log

Every call made through a write key, successful or refused, is recorded with the key’s name, the client, the tool, a summary of the arguments and the result. Arguments are summarised, never stored whole, and no secret is recorded. The seller sees recent entries under Connect your AI. Turning a key off keeps its history.

Revoking a key

In Apex, open Connect your AI, find the key under Your links and choose Turn off. The next call with that key answers 401. A key also stops working when its user loses access to the account.

Versioning and changes

The server identifies itself as apex-applications version 1.0.0 in initialize. Tools are added over time, and this page is regenerated from the server’s own definitions when they change.

Clients cache the tool list. After a change, refresh the connector in your client (ChatGPT has a Refresh button on the plugin) or start a new chat.

Planned, not available: choosing which areas a key can read, such as profit and loss only; signing in with oauth instead of pasting a link; proposing repricer changes that apply only after you approve them in apex.