There's No Endpoint to Read Amazon Buyer-Seller Messages #
You're building support tooling on top of a marketplace. A buyer messages the seller — "can you change the engraving before it ships?", "please cancel", "where's my order?" — and you want that message in your own app, attached to the order, so your team sees it without living in Seller Central.
So you open the Selling Partner API docs, look for a getMessages on the Messaging API, and it isn't there. You assume you've missed a scope or an expansion flag and start hunting.
Stop hunting. As of August 2026 there is no Selling Partner API endpoint that returns the messages buyers send you. Amazon's Messaging API only sends. There is no conversations resource, no inbox resource, no "get messages" call under any role you can apply for.
This is deliberate rather than an oversight. Buyer contact is personal data, and Amazon would rather intermediate it inside Seller Central than hand you an inbox you could export.
| Where people look | Returns buyer messages? | What the API actually offers |
|---|---|---|
| Messaging API v1 | No | Send-only — templated seller-to-buyer messages, no read operation |
| Notifications API | No | Event types cover orders, offers and reports — none carry message content |
| Reports API | No | No report type contains buyer correspondence |
The one path that exists on every platform is the same one the helpdesk vendors use, and it isn't an API. It's the notification email the marketplace already sends you. This post is how to turn that into a clean, deduplicated feed of buyer messages inside your own app.
The Wrong Turns: Messaging API, Notifications, and Scraping #
Three things look like the answer and aren't. Rule them out first so you don't lose a day.
The Messaging API is send-only. Every operation on Amazon's Messaging API v1 either sends a templated message (confirm delivery details, request a review, send an invoice) or tells you which message types you're allowed to send for an order. getMessagingActionsForOrder sounds promising and returns permissions, not content. There is no operation that returns what the buyer wrote.
The Notifications API has no event for it. You'd expect a "buyer sent you a message" notification type to subscribe to. Check the SP-API Notifications use-case guide — the event types are operational (orders, offers, inventory, account health). None of them fire on an incoming buyer message, so you can't even get a webhook that one arrived, let alone its text. Amazon staff have confirmed the read gap directly on the official SP-API discussions, and it remains true today.
Scraping the Seller Central inbox is a trap. It's a terms-of-service violation, it breaks every time the DOM changes, and it needs a logged-in session per account. Don't build on it.
Gotcha: "there's no notification type for incoming messages" is the part people miss. You cannot subscribe your way to buyer messages. If you want them event-driven, the event has to be an email arriving, not an SP-API notification.
How the Message Actually Reaches You: the Notification Email #
Here's the surface that does exist. When a buyer messages the seller, the marketplace emails a copy to the seller's notification address — the same email you already get today. That email is the only programmatic handle on the message content.
On Amazon the sender is a per-message relay alias: something shaped like redacted-alias@marketplace.amazon.com. That single fact is the key to the whole pipeline — it's what separates a real buyer message from the flood of "Sold, ship now" and "your item shipped" notifications, which come from other Amazon addresses. Filter on the relay domain and you have your signal.
This is exactly how third-party support tools integrate marketplace messages: they parse the notification emails and use the API only to enrich with order data. There's no secret endpoint they have and you don't — everyone is working from the same email.
The Email-Relay Ingestion Pipeline #
The pattern is four moves: aggregate the notification emails into one mailbox you control, poll it, parse each message, and attach it to the order. Each account keeps forwarding to a single mailbox, so 1 account or 20 accounts is the same pipeline.
Polling every couple of minutes is cheap and appropriate. IMAP isn't a metered API — it's included with any mailbox — and an empty poll is a few kilobytes. Buyer messages are time-sensitive (a change request has to beat production), so near-real-time matters more than shaving 700 polls a day that cost nothing. The one paid step, if you classify message intent with an LLM, runs once per message, not once per poll.
At the mailbox, either point each account's notification address straight at the aggregation mailbox, or full-forward and let the server decide what's a buyer message. For many accounts, full-forward plus server-side filtering is less setup and easier to change: if a sender pattern shifts, you fix it in one place instead of re-editing a rule on every account.
Matching a Message to Its Order — and Its Account #
The order id does all the work. On Amazon it has the fixed shape NNN-NNNNNNN-NNNNNNN (three digits, seven, seven), and it's globally unique — the same id never belongs to two orders, across every marketplace and every seller account. So one lookup resolves not just the order but the account, the marketplace, the buyer and the workflow stage, because they all hang off the order row.
The id appears in the email — sometimes in the subject, sometimes only in the body — so scan both:
import re
ORDER_ID = re.compile(r"\b\d{3}-\d{7}-\d{7}\b") # same shape on every Amazon marketplace
def match_to_order(db, subject, body):
m = ORDER_ID.search(subject) or ORDER_ID.search(body)
if not m:
return None # no id -> park in an "unassigned" queue
# one indexed lookup resolves the order, and with it the account,
# marketplace and buyer, because they all reference this row
return db.query(Order).filter_by(marketplace_order_id=m.group(0)).one_or_none()
You never tag emails by account. Twenty accounts can forward into one mailbox and every message still lands on the right order under the right account, because the order id is the key and it's already linked to its account in your database. That's the property that makes this scale without per-account plumbing.
Two things fall out of this design cleanly:
- Multiple marketplaces are free. A US, Canada or UK order id has the identical format and comes through the same relay domain. Only the message language differs — and matching doesn't read the language. If you classify intent with a model, that step is multilingual anyway.
- The order might not be in your database yet. A very recent order, or one from a marketplace you haven't synced, won't match. Store the message with the extracted id and let it auto-link on the next order sync. Nothing is lost; it just resolves late.
Related: the buyer's email and phone in that message are relay values, not real contact details — see why no marketplace gives you a real buyer phone number, and where personalization actually lives in the order payload.
Never Processing the Same Email Twice #
A poller that re-reads the whole inbox every two minutes will create the same message — and fire the same alert — over and over. Two mechanisms, belt and suspenders, stop that.
A high-water mark so you only fetch what's new. Every message has a stable IMAP UID; remember the last one you processed and ask the server only for higher UIDs. Old mail is never even downloaded:
typ, data = imap.uid("SEARCH", None, f"UID {last_seen_uid + 1}:*")
A uniqueness guard so a re-read can't duplicate. Store each email's own Message-ID with a unique constraint; a second insert of the same message is rejected, not duplicated:
class BuyerMessage(Base):
__tablename__ = "buyer_messages"
id = Column(Integer, primary_key=True)
rfc822_message_id = Column(String, unique=True) # idempotency key
order_id = Column(Integer, ForeignKey("orders.id"), nullable=True)
sender_relay = Column(String) # reply handle (see below)
body = Column(Text)
received_at = Column(DateTime)
Gotcha: don't dedupe with the IMAP \Seen flag. The moment anyone opens the aggregation mailbox in a webmail client, messages get marked read and your "unseen only" logic silently skips them. The UID watermark plus the Message-ID constraint are immune to a human glancing at the inbox.
Replying — and Where You Can't #
Reading is only half of it. Since the inbound message carries a relay reply-to address, you can often reply straight back into the marketplace thread — but the rules differ, and one platform blocks it outright.
| Marketplace | Reply from your app? | How |
|---|---|---|
| Reply to the relay address | Yes | From an address registered on that seller account — it lands back in the buyer's thread |
| Reply from an unregistered address | No | Amazon drops it — the sending address must be registered on that seller account |
| Start a new thread | No | Only buyer-initiated threads may be replied to; unsolicited contact breaches the communication policy |
A safe first version is: read every message automatically, but reply with a one-click deep link into the Seller Central thread. Full in-app replies (sending on the account's behalf) are a later step — they need a sending credential per mailbox, which is more secret management than the read path. Whatever you build, only ever reply to a buyer-initiated thread; unsolicited outreach is against Amazon's messaging policy.
Building this across many seller accounts? The message read is the easy half; matching, dedupe, and per-account isolation are where it gets real — related reading on how buyer PII access actually works, or talk to me about the ingestion pipeline.
FAQ #
Is there an Amazon API to read buyer-seller messages?
No. As of August 2026 the Selling Partner Messaging API is send-only — it posts templated seller-to-buyer messages and lists which message types are allowed for an order. There is no operation that returns the content a buyer sent, and no Notifications event fires on an incoming message.
How do support tools get Amazon buyer messages then?
They parse the notification emails. Amazon emails a copy of each buyer message to the seller's notification address from a per-message relay alias at marketplace.amazon.com; tools ingest that email and use the API only to enrich it with order data. There is no private endpoint they have that you don't.
Do other marketplaces have a message-read API?
This guide is about Amazon specifically, but the pattern is not unique to it — the major marketplaces all keep the buyer inbox off the API and intermediate contact themselves. If you are integrating another platform, check its API reference for a conversations or messages resource before assuming one exists.
How do I match a forwarded message to the right order and seller account?
Extract the Amazon order id (the fixed NNN-NNNNNNN-NNNNNNN shape) from the email subject or body and look it up in your orders table. The id is globally unique, so one indexed lookup resolves the order and, through it, the account, marketplace and buyer — you never need to tag emails by account.
Can I reply to a buyer from my own app?
Yes. Reply to the relay address from an address registered on that Amazon account and it lands back in the buyer's thread. Only ever reply to a thread the buyer started — unsolicited contact is against Amazon's communication policy regardless of how you send it.
Related guides
Marketplace APIs
Amazon vs Etsy vs Walmart vs eBay: Four Marketplace APIs, Four Auth Models
If you're integrating more than one marketplace, the authentication layer is where your abstraction breaks first. All four use OAuth 2.0 on paper, and no two behave the same way in practice. Here's what actually differs — token lifetimes, rotation, credential ownership — and how those differences should shape your database schema.
Read guide →Marketplace APIs
No Marketplace Gives You a Real Buyer Phone Number (What to Do Instead)
Your carrier API rejects the shipment because the consignee phone is missing, and the order payload simply doesn't contain one. That's not a bug in your integration — Etsy and Walmart don't return a buyer phone at all, and Amazon's is a relay number. Here's what each marketplace actually gives you and how to satisfy the carrier without inventing data.
Read guide →Marketplace APIs
Etsy's Rotating OAuth Refresh Token (and the Sync Race It Creates)
Your Etsy integration works for weeks, then a shop quietly stops syncing and only a human re-login fixes it. That is the rotating refresh token: Etsy issues a new one on every refresh and kills the old, so a crashed write or two concurrent syncs orphan the shop. Here is the mechanism, the scheduled-vs-manual sync race, and the cache-plus-lock fix.
Read guide →Don't want to build this yourself?
I set this up for sellers and agencies every week. Book a free 30-minute audit of your Amazon data & PPC setup — you'll leave with a plan either way, whether we work together or not.