Amazon SP-API 8 min read

How to Get Amazon Custom Personalisation Text from SP-API

A buyer typed an engraving on your Amazon Custom listing and your production team needs those exact characters. The text isn't in getOrders — it's behind a restricted endpoint, inside a ZIP, at the end of an expiring URL. Here's the full retrieval path, plus the payload trap that silently drops half the fields.

Updated Aug 2026
How to Get Amazon Custom Personalisation Text from SP-API

The Field You Need Is Not Where You Are Looking #

You sell personalised products on Amazon — engraved, monogrammed, printed to order. One field decides whether the order can actually be fulfilled: the exact text the buyer typed. Get it wrong and you ship a physical object with someone's name misspelled on it.

So you call getOrders, then getOrderItems, and there is no personalisation anywhere in the response. That is expected. Amazon treats customisation data the same way it treats buyer names and addresses: as protected data behind a separate, restricted path.

Where it actually lives

GET /orders/v0/orders/{orderId}/orderItems/buyerInfo → the field BuyerCustomizedInfo.CustomizedURL → a signed, expiring link → a ZIP containing the customisation JSON and a print-ready SVG. You need a Restricted Data Token to call it at all.

An engraved metal plate, representing personalised made-to-order products
The characters the buyer typed have to survive intact from the order API to the engraving machine.

Step 1: Get Past the Restricted Data Gate #

The buyer-info path is restricted, so a normal access token returns nothing useful. You need a Restricted Data Token minted specifically for the path you are about to call.

The mistake that costs people hours: the RDT path must match the exact endpoint you are hitting, not its parent. Minting a token for /orders/v0/orders/{id}/orderItems and then calling /orderItems/buyerInfo returns 401, and the error looks like a permissions problem rather than a path mismatch — so people go and request more roles, which changes nothing.

If you are getting nulls or 401s here, start with the Restricted Data Token walkthrough; the personalisation field is gated by exactly the same mechanism as buyer name and address.

Step 2: Download the ZIP Before It Expires #

When an item is personalised, BuyerCustomizedInfo.CustomizedURL holds a signed, expiring link. Treat it as single-use: download during the sync that discovered the order, and persist the contents. Storing the URL to fetch later is a bug that only shows up in production.

Inside the ZIP:

  1. The customisation JSON

    Named after the order item ID. This is the one that matters, and the next section is about why it is trickier than it looks.

  2. An XML copy

    The same data in another format. Usually ignorable.

  3. A preview JPEG

    A small rendering of the personalised product. Useful in your ops UI so a human can eyeball what was ordered.

  4. A print-ready SVG

    The buyer's text already laid out on the product surface, with fonts and positioning resolved. For a print or engraving workflow this is often more useful than the raw characters.

Before you conclude it is broken: in a catalogue that mixes personalised and plain SKUs, custom orders can be a small minority of volume — on the order of one in sixty. A 90-day pull that happens to contain no custom orders looks exactly like a broken integration. Check a known-personalised order specifically rather than sampling at random.

The Trap: version3.0 Silently Loses Text #

This one costs real money, because it fails by omission rather than by error.

The customisation JSON contains two representations of the same order. There is customizationData, a deeply nested tree carrying exact geometry, fonts and colours; and there is version3.0.customizationInfo.surfaces[], a much flatter and more inviting structure. Naturally, everyone parses the flat one.

The problem: within version3.0, each area is typed as either TextPrinting or ImagePrinting, and Amazon decides per field which one to emit. A TextPrinting area has a text value you can read. An ImagePrinting area has an SVG and no text value at all.

In one real order, three fields were personalised — a date, a name and a sentiment line. The date came through as TextPrinting with readable text. The name and the sentiment came through as ImagePrinting: rendered into vector art, with the literal characters nowhere in that branch of the payload. Nothing errors. You just get one field instead of three.

Within version3.0, TextPrinting areas expose the buyer text but ImagePrinting areas contain only an SVG, so parsing version3.0 alone loses fields version3.0.customizationInfo.surfaces[].areas[] TextPrinting has a readable "text" value you get the characters ImagePrinting svgImage only, no "text" key text lost if you stop here Fall back to the customizationData tree for any area without a text value

So the rule is: parse version3.0 for convenience, but treat a missing text value as "look elsewhere", not as "empty". Walk the customizationData tree down to its TextCustomization leaves for anything the flat view did not give you.

What to Store, and What to Alert On #

Four things worth building in from the start, because retrofitting any of them is painful:

  • Store the normalised text as an ordered list of label and value per line item — that is what your production team reads.
  • Store the raw payload too. When a print comes out wrong, the argument is settled in seconds instead of hours, and re-parsing history after a bug fix becomes possible.
  • Persist the artwork. The print-ready SVG is genuinely valuable output, and the URL it came from will not be valid later.
  • Flag "personalised but empty" loudly. A made-to-order item with no personalisation text must reach a human before production — not slide into the queue blank. Given the ImagePrinting trap above, this alert is what catches a parser regression before it becomes a pile of wrong engravings.

Selling personalised goods on more than one channel? Etsy delivers the same data in a completely different shape — see getting personalisation text out of Etsy. Or talk to me about the integration.

FAQ #

Where is Amazon Custom personalisation data in SP-API?

On the order item, via GET /orders/v0/orders/{orderId}/orderItems/buyerInfo, in the field BuyerCustomizedInfo.CustomizedURL. That is a signed, expiring link to a ZIP containing the customisation JSON, an XML copy, a preview image and a print-ready SVG. It requires a Restricted Data Token.

Why is the buyer's engraving text missing from the customisation JSON?

Because you are probably reading only version3.0.customizationInfo.surfaces[]. Amazon emits some fields as ImagePrinting, which contains an SVG but no text value. Fall back to the customizationData tree and read its TextCustomization leaves for any field the flat view did not provide.

How long does Amazon's CustomizedURL stay valid?

It is a signed URL that expires, so treat it as single-use: download and persist the ZIP contents during the sync that discovered the order rather than storing the link for later.

Do I need a Restricted Data Token for personalisation data?

Yes. The customisation field sits on the restricted buyer-info path, so it is gated by the same Restricted Data Token mechanism as buyer name and shipping address. The RDT must be minted for the exact endpoint path you call, not its parent.

Why do none of my orders have personalisation data?

Most likely your sample contains no Amazon Custom orders. In a mixed catalogue, personalised SKUs can be a small fraction of volume, so test against an order you know is personalised rather than a random window.

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.

Found this helpful? Share it:

WhatsApp