Claude Spotify Instacart API Integration: An APAC Commerce Blueprint

Key Takeaways
- Claude's Spotify and Instacart connectors both run on MCP — reuse that pattern.
- Expose narrow, typed tools; never a generic "call the API" endpoint.
- Sign Shopee requests with HMAC-SHA256 over the exact concatenated base string.
- Keep deterministic marketplace workflows in n8n; use Claude only for judgement.
- Ship read-only first, gate writes behind confirmation tokens.
Quick Answer: Claude's Spotify and Instacart connectors both use the Model Context Protocol: narrow typed tools, delegated OAuth, and Streamable HTTP transport. APAC commerce teams can reuse that exact architecture to wrap Shopee, Lazada and 3PL APIs as a custom Claude connector for order and fulfilment workflows.
Anthropic shipped consumer connectors for Spotify, Instacart, Booking.com and a dozen other lifestyle apps in late 2025, and Spotify's own newsroom confirmed users can now link accounts to Claude for taste-based recommendations. Engadget covered the same launch. What almost nobody covered is the part that matters if you sell things for a living: the Claude Spotify Instacart API integration pattern is a reusable architecture, and it maps almost one-to-one onto the order, inventory and fulfilment stack that an Asia-Pacific commerce brand already runs.
Related reading: Claude AI Production Integration Risks: An Engineering Playbook
I run a managed contracting business that builds these integrations for listed retail, catering and dealer-network clients across Greater China and Southeast Asia. The business problem clients bring us is never "we want an AI chatbot." It is "our CS team answers 400 WhatsApp messages a day about where the parcel is, and half of them require someone to log into three dashboards." Spotify and Instacart solved a version of that problem — expose a narrow, well-typed set of actions to a model, let the model handle the language. This tutorial shows you how to build the same thing against Shopee, Lazada and a regional 3PL, with code you can paste.
The honest constraint up front: this is not cheap to run, and it is not a weekend project if you want it in front of customers. Budget for a proper OAuth token store, per-tenant rate limiting, and a human escalation path. I'll flag costs where they bite.
Related reading: Ecommerce Platform Comparison Cost 2026: Shopify Plus vs Adobe vs SHOPLINE
Why the Spotify and Instacart connectors are the right reference architecture
Both connectors are built on the Model Context Protocol (MCP), the open standard Anthropic published in November 2024 and which now has SDKs in TypeScript, Python, Java, Kotlin, C# and Go per the modelcontextprotocol.io documentation. Instacart's own developer docs have a page titled "Connect your AI agent to Instacart with MCP" — they did not build a bespoke Claude plugin, they published an MCP server and let any client connect.
That is the design decision worth copying. Three properties make it work:
- Tools are narrow and typed. Instacart does not expose "query our database." It exposes recipe-to-cart and product-search actions with JSON schemas. The model cannot invent a parameter that does not exist.
- Auth is delegated. The connector performs OAuth 2.1 against the provider; Claude never sees a raw partner secret. Anthropic's support documentation describes how Claude decides which connected app to invoke without the user naming it.
- Transport is standard. Remote MCP over Streamable HTTP means one server serves Claude Desktop, Claude Code, and your own app.
Swap "Spotify playlist" for "Lazada order" and "Instacart cart" for "3PL shipment booking" and the architecture is unchanged.
The market context for APAC is why this is worth the engineering hours. Momentum Works' annual Ecommerce in Southeast Asia research put regional platform GMV above US$150 billion, with Shopee holding the largest single share and TikTok Shop growing fastest. That GMV sits behind marketplace APIs that are, to put it kindly, inconsistent. Shopee signs requests with HMAC-SHA256 over a concatenated string. Lazada uses its own signing scheme with sorted parameters. Your Australian 3PL probably wants an API key in a header. An MCP layer is where you absorb that inconsistency once.
Related reading: GPT-5.5 Enterprise Workflow Automation: An APAC CTO's Playbook
Related reading: Supply Chain Security for LLM Inference: An APAC Checklist
Related reading: Salesforce Agentforce AI Adoption 2026: The APAC Ops Playbook
Prerequisites
Before step one, have these in hand. Missing any of them is the most common reason a "Claude Spotify Instacart API integration not working" thread on Reddit ends with no answer — the failure is almost always auth or transport, not the model.
Accounts and credentials
- Claude Max, Team or Enterprise plan, or an Anthropic Console account with API access. Custom connectors are not available on the free tier — check current plan availability in Anthropic's docs before you scope.
- Shopee Open Platform partner account (
partner_id,partner_key) with a test shop authorised. Sandbox is at the Open Platform console. - Lazada Open Platform app (
app_key,app_secret) with seller authorisation for at least one venture (SG, MY, PH, TH, VN, ID). - Optional but realistic: credentials for one fulfilment provider. We use Janio, Ninja Van or an in-house WMS depending on the client.
Local environment
- Node.js 20 LTS or later.
node --versionshould printv20.xor higher. npm10+, orpnpmif you prefer.- A tunnelling tool for local testing of remote MCP:
cloudflaredorngrok. - Claude Desktop installed, or Claude Code (
npm i -g @anthropic-ai/claude-code).
Infrastructure decisions made
- Where tokens live. Not in environment variables. Marketplace access tokens expire — Shopee's in four hours — and refresh must be atomic across instances. Postgres with row-level encryption or AWS Secrets Manager both work.
- Region. If you serve Indonesian or Vietnamese sellers, host in
ap-southeast-1orap-southeast-3. Cross-Pacific round trips on every tool call turn a two-second answer into eight. - A read-only mode flag. You will want it in week two.
Scaffold the project:
1mkdir apac-commerce-mcp && cd apac-commerce-mcp2npm init -y3npm i @modelcontextprotocol/sdk zod express undici4npm i -D typescript @types/node @types/express tsx5npx tsc --init --target es2022 --module node16 --outDir dist
Expected output from the install:
1added 118 packages, and audited 119 packages in 6s
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
Step 1: Stand up a minimal MCP server and prove the handshake
Start with one tool that returns static data. Prove the transport before you touch a marketplace API — this single discipline saves hours.
Create src/server.ts:
1import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";2import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";3import { z } from "zod";45const server = new McpServer({6 name: "apac-commerce",7 version: "0.1.0",8});910server.tool(11 "health_check",12 "Returns server status and configured marketplace regions.",13 {},14 async () => ({15 content: [16 {17 type: "text",18 text: JSON.stringify({19 status: "ok",20 regions: ["SG", "MY", "HK", "TW"],21 mode: process.env.MCP_READ_ONLY === "true" ? "read-only" : "read-write",22 }),23 },24 ],25 })26);2728const transport = new StdioServerTransport();29await server.connect(transport);
Register it with Claude Desktop. On macOS the config file is ~/Library/Application Support/Claude/claude_desktop_config.json; on Windows, %APPDATA%\Claude\claude_desktop_config.json.
1{2 "mcpServers": {3 "apac-commerce": {4 "command": "npx",5 "args": ["-y", "tsx", "/absolute/path/to/apac-commerce-mcp/src/server.ts"],6 "env": { "MCP_READ_ONLY": "true" }7 }8 }9}
Restart Claude Desktop fully — quit, don't just close the window. Then verify from the CLI first, because the desktop app's error surface is thin:
1npx @modelcontextprotocol/inspector npx tsx src/server.ts
The Inspector opens a browser UI. Click Tools → List Tools and you should see:
1{2 "tools": [3 {4 "name": "health_check",5 "description": "Returns server status and configured marketplace regions.",6 "inputSchema": { "type": "object", "properties": {} }7 }8 ]9}
If the tool list is empty, your server crashed on startup and stdio swallowed the stack trace. Run npx tsx src/server.ts directly and read the error.
Step 2: Sign and call the Shopee Open Platform correctly
Shopee's signing is the step where most teams lose an afternoon. The base string is a concatenation, not a sorted query — order matters exactly.
Create src/shopee.ts:
1import crypto from "node:crypto";2import { request } from "undici";34const HOST = process.env.SHOPEE_HOST ?? "https://partner.shopeemobile.com";5const PARTNER_ID = Number(process.env.SHOPEE_PARTNER_ID);6const PARTNER_KEY = process.env.SHOPEE_PARTNER_KEY!;78function signShopApi(path: string, timestamp: number, accessToken: string, shopId: number) {9 const base = `${PARTNER_ID}${path}${timestamp}${accessToken}${shopId}`;10 return crypto.createHmac("sha256", PARTNER_KEY).update(base).digest("hex");11}1213export async function shopeeGet<T>(14 path: string,15 params: Record<string, string | number>,16 accessToken: string,17 shopId: number18): Promise<T> {19 const timestamp = Math.floor(Date.now() / 1000);20 const sign = signShopApi(path, timestamp, accessToken, shopId);2122 const query = new URLSearchParams({23 partner_id: String(PARTNER_ID),24 timestamp: String(timestamp),25 access_token: accessToken,26 shop_id: String(shopId),27 sign,28 ...Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])),29 });3031 const res = await request(`${HOST}${path}?${query}`, { method: "GET" });32 const body = (await res.body.json()) as any;3334 if (body.error) {35 throw new Error(`shopee:${body.error}:${body.message ?? ""}`);36 }37 return body as T;38}
Smoke-test it standalone before wiring it into a tool:
1SHOPEE_PARTNER_ID=1234567 \2SHOPEE_PARTNER_KEY=xxxx \3npx tsx -e "import('./src/shopee.ts').then(m => m.shopeeGet('/api/v2/order/get_order_list', { time_range_field: 'create_time', time_from: Math.floor(Date.now()/1000)-86400, time_to: Math.floor(Date.now()/1000), page_size: 5 }, process.env.TOKEN, Number(process.env.SHOP_ID)).then(r => console.log(JSON.stringify(r, null, 2))))"
A correct call returns:
1{2 "error": "",3 "message": "",4 "request_id": "a1b2c3d4e5f6",5 "response": {6 "more": false,7 "order_list": [8 { "order_sn": "240118ABCDEFGH", "order_status": "READY_TO_SHIP" }9 ]10 }11}
If you get error: "error_sign", your base string is wrong — print it and count the characters. If you get error_auth, the shop authorisation expired and you need the refresh flow.
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
Step 3: Expose commerce actions as narrow, typed tools
This is where the Instacart lesson earns its keep. Do not expose a generic call_shopee_api tool. The model will guess parameters and you will get support tickets you cannot reproduce.
Add to src/server.ts:
1import { shopeeGet } from "./shopee.js";2import { getTokenForShop } from "./tokens.js";34server.tool(5 "find_order_status",6 "Look up the fulfilment status of a single marketplace order by order number. Read-only.",7 {8 marketplace: z.enum(["shopee", "lazada"]),9 order_reference: z.string().min(6).max(32)10 .describe("Marketplace order number as shown to the buyer, e.g. 240118ABCDEFGH"),11 shop_id: z.number().int().describe("Internal shop identifier from list_connected_shops"),12 },13 async ({ marketplace, order_reference, shop_id }) => {14 if (marketplace !== "shopee") {15 return { content: [{ type: "text", text: "Lazada lookup not enabled on this server." }] };16 }1718 const token = await getTokenForShop(shop_id);19 const data = await shopeeGet<any>(20 "/api/v2/order/get_order_detail",21 { order_sn_list: order_reference, response_optional_fields: "recipient_address,package_list" },22 token.accessToken,23 token.shopId24 );2526 const order = data.response?.order_list?.[0];27 if (!order) {28 return { content: [{ type: "text", text: `No order found for ${order_reference}.` }] };29 }3031 return {32 content: [{33 type: "text",34 text: JSON.stringify({35 order_reference: order.order_sn,36 status: order.order_status,37 courier: order.package_list?.[0]?.shipping_carrier ?? null,38 tracking_number: order.package_list?.[0]?.tracking_number ?? null,39 destination_region: order.recipient_address?.region ?? null,40 }),41 }],42 };43 }44);
Three things in that snippet are deliberate:
.describe()on every field. The model reads these. Vague descriptions produce wrong tool calls more often than bad prompts do.- Redacted response shape. No customer name, no phone, no full address — only the region. If you pipe PII into a model context you have created a data-transfer question under Singapore's PDPA and, for HK operations, the PDPO. Decide that consciously, not by omission.
- Named error strings.
shopee:error_signin a log is diagnosable; a thrownTypeErroris not.
For write actions — booking a pickup, cancelling, issuing a refund — gate them behind a confirmation tool:
1server.tool(2 "request_fulfilment_hold",3 "Place an order on hold. Requires an explicit confirmation token from confirm_intent.",4 {5 order_reference: z.string(),6 confirmation_token: z.string().describe("Token returned by confirm_intent within the last 120 seconds"),7 reason_code: z.enum(["customer_request", "address_invalid", "stock_issue"]),8 },9 async (args) => { /* verify token TTL, then act */ }10);
Agents are good at reasoning and bad at restraint. The token pattern costs you one extra round trip and removes an entire class of incident.
Step 4: Go remote so Claude, Claude Code and your own app share one server
Stdio is fine for your laptop. Production needs Streamable HTTP so you can register the server as a custom connector and serve mobile and web clients. Create src/http.ts:
1import express from "express";2import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";3import { buildServer } from "./server-factory.js";45const app = express();6app.use(express.json({ limit: "512kb" }));78app.post("/mcp", async (req, res) => {9 const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });10 res.on("close", () => transport.close());1112 const server = buildServer({13 tenantId: req.header("x-tenant-id") ?? "unknown",14 readOnly: req.header("x-mode") === "read-only",15 });1617 await server.connect(transport);18 await transport.handleRequest(req, res, req.body);19});2021app.get("/healthz", (_req, res) => res.json({ ok: true }));22app.listen(3000, () => console.log("MCP listening on :3000"));
Run and tunnel:
1npx tsx src/http.ts &2cloudflared tunnel --url http://localhost:3000
Expected:
1MCP listening on :30002+--------------------------------------------------------+3| https://spare-koala-fjord.trycloudflare.com |4+--------------------------------------------------------+
Verify with a raw JSON-RPC call — this is the test that tells you whether the problem is your server or Claude:
1curl -sS https://spare-koala-fjord.trycloudflare.com/mcp \2 -H 'Content-Type: application/json' \3 -H 'Accept: application/json, text/event-stream' \4 -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | head -40
You should see your tool array. Then add the URL in Claude under Settings → Connectors → Add custom connector. The flow is the same one described in third-party write-ups of adding the Spotify connector — browse, add, authorise — except the endpoint is yours.
For customer-facing use, protect the endpoint with OAuth 2.1 and per-tenant rate limits. Marketplace APIs enforce their own quotas; Shopee and Lazada both throttle per app, and an enthusiastic agent loop will exhaust your quota for every seller on the platform, not just the noisy one.
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
Step 5: Decide what belongs in MCP and what belongs in n8n
Not every workflow should be a tool call. The split we use:
MCP tools — synchronous, user-initiated, needs language understanding. "Where is order 240118ABCDEFGH?" "Which SKUs in the Malaysia warehouse are below reorder point?"
n8n or Make workflows — scheduled, event-driven, deterministic. Marketplace webhook fires → normalise payload → write to ERP → push to 3PL. No model needed, and you do not want token costs on a path that runs 40,000 times a day.
The bridge is a webhook node that calls Claude only for the judgement step. A pattern from a Hong Kong multi-brand catering group we worked with: inbound supplier emails with attached delivery notes landed in n8n, which extracted line items with an Anthropic node, then wrote structured output back to the purchasing system. The model handled the messy Chinese-English-abbreviation mix in the PDFs; n8n handled everything deterministic. We were explicit with the client that the extraction step needed a human review queue for low-confidence rows — that queue is not optional, and pretending otherwise is how these projects fail in month three.
On cost: model calls in a customer-facing loop are a per-conversation variable expense, not a fixed one. Model it before launch. A 10,000-conversation month at multi-turn depth with tool results in context is a real line item. Caching tool descriptions and using a smaller model for classification, escalating to Sonnet or Opus only for reasoning, is the lever that actually works.
Troubleshooting: what breaks and where to look
Connector added but Claude never calls the tool. Your descriptions are too vague. Anthropic's help documentation explains that Claude infers which connected app to use from the tool metadata. Rewrite the description as a sentence a new hire could follow: "Look up fulfilment status of a marketplace order by order number" beats "order tool."
error_sign on Shopee, IncompleteSignature on Lazada. Print the exact base string. For Shopee, confirm you used the shop signing form (partner_id + path + timestamp + access_token + shop_id), not the public form. For Lazada, confirm parameters are sorted and concatenated as key-value pairs with no separators.
Works in Inspector, fails in Claude Desktop. Almost always the Accept header or a missing full restart. Confirm your server accepts both application/json and text/event-stream.
Intermittent timeouts from Vietnam or Indonesia. Check your egress region. Also check the marketplace's own regional endpoint — Lazada uses different gateway hosts per venture.
Token expiry mid-conversation. Refresh in the token layer with a mutex, and return a retryable error rather than a stack trace so the model can call again cleanly.
The GitHub route. If you want to read working code before writing your own, the community mcp-claude-spotify repository on GitHub is a compact example of the same pattern against a consumer API, and Instacart's developer documentation covers the hosted MCP variant. Both are more useful than any "claude spotify instacart api integration example" blog post, including this one, for seeing the wire format.
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
What to do next
Run this checklist before you commit engineering time:
- Is there a language problem to solve? If your workflow is deterministic end to end, use n8n and skip the model. The Claude Spotify Instacart API integration pattern earns its cost only where free-text or judgement is involved.
- Do you have one narrow, high-volume use case? Order status lookup, stock enquiry, or returns eligibility. One tool shipped beats six half-built.
- Is your token store atomic and encrypted? If tokens live in
.env, fix that before anything else. - Have you written the PII boundary down? Which fields never enter model context, in a document your CS lead has read. PDPA in Singapore, PDPO in Hong Kong, Australia's Privacy Act — the answer differs by market you serve.
- Is read-only mode the default? Ship it read-only, watch two weeks of real transcripts, then enable writes behind confirmation tokens.
- Have you modelled per-conversation cost at 10× current volume? If the number scares you at 10×, it will scare your CFO at 3×.
- Where does a human take over? Name the escalation path and the SLA. Every deployment without one degrades into a worse version of a FAQ page.
If you want a second pair of eyes on the architecture — token store, tool boundary, or the MCP-versus-workflow split for your marketplace mix — talk to the Branch8 team. We build these across Hong Kong, Singapore, Taiwan and Southeast Asia, and we will tell you when the answer is a workflow rather than an agent.
Sources
- Model Context Protocol — Documentation and SDKs
- Anthropic — Claude Developer Documentation
- Anthropic Help Center — Connected apps and connectors
- Instacart — Developer Platform Documentation
- Spotify Newsroom — Music and Podcast Recommendations in Claude
- Shopee Open Platform — API Documentation
- Lazada Open Platform — Developer Portal
- Momentum Works — Ecommerce in Southeast Asia research
FAQ
Spotify publishes an integration that Claude connects to via OAuth, after which Claude can query playback state, search catalogue items and generate recommendations from your listening taste. In the desktop app you go to Settings, open Connectors, browse the directory and authorise your Spotify account. Under the hood it follows the same Model Context Protocol tool-and-auth pattern you would use for a custom commerce connector.
About the Author
Matt Li
Co-Founder & CEO, Branch8 & Second Talent
Matt Li is Co-Founder and CEO of Branch8, a Y Combinator-backed (S15) Adobe Solution Partner and e-commerce consultancy headquartered in Hong Kong, and Co-Founder of Second Talent, a global tech hiring platform ranked #1 in Global Hiring on G2. With 12 years of experience in e-commerce strategy, platform implementation, and digital operations, he has led delivery of Adobe Commerce Cloud projects for enterprise clients including Chow Sang Sang, HomePlus (HKBN), Maxim's, Hong Kong International Airport, Hotai/Toyota, and Evisu. Prior to founding Branch8, Matt served as Vice President of Mid-Market Enterprises at HSBC. He serves as Vice Chairman of the Hong Kong E-Commerce Business Association (HKEBA). A self-taught software engineer, Matt graduated from the University of Toronto with a Bachelor of Commerce in Finance and Economics.