Install and configure Saleor Agentic Commerce SDK in a Next.js storefront. Use when a developer wants to make their Saleor store shoppable by AI agents via UCP/ACP protocols.
You are helping a developer add AI agent commerce support to their Saleor storefront. The SDK enables AI shopping agents to discover products, create checkouts, and complete purchases through UCP (Universal Commerce Protocol) and ACP (Agentic Commerce Protocol) endpoints.
Before starting, verify the project:
next.config.js or next.config.mjs and package.json with next as a dependency.SALEOR_API_URL or NEXT_PUBLIC_SALEOR_API_URL in .env* files, or @saleor/* packages in package.json.package.json to confirm.src/app/ or app/ directory structure. The SDK uses App Router route handlers.If any check fails, explain what's missing and what the developer needs first.
If the SDK packages are already installed (check package.json for @financedistrict/saleor-agentic-commerce-core), skip to the configuration step and ask what needs to be changed.
Install the core and Next.js packages:
npm install @financedistrict/saleor-agentic-commerce-core @financedistrict/saleor-agentic-commerce-nextjs
If the project uses pnpm or yarn, detect this from the lockfile (pnpm-lock.yaml → pnpm, yarn.lock → yarn) and use the correct command.
Create a configuration file. Detect the project's source directory structure first:
src/lib/ exists → create src/lib/agentic-commerce.tssrc/ exists but no lib/ → create src/lib/agentic-commerce.ts (make the dir)lib/ exists at root → create lib/agentic-commerce.tssrc/lib/agentic-commerce.tsFile contents:
import { createAgenticCommerce } from "@financedistrict/saleor-agentic-commerce-nextjs"
// If the Saleor Agentic Commerce App is installed in the Dashboard,
// use configFromApp: true to load config from the App's metadata.
// Otherwise, configure everything explicitly here.
export const agenticCommerce = createAgenticCommerce({
saleorApiUrl: process.env.NEXT_PUBLIC_SALEOR_API_URL!,
saleorAuthToken: process.env.SALEOR_AGENTIC_AUTH_TOKEN!,
storefrontUrl: process.env.NEXT_PUBLIC_STOREFRONT_URL!,
storeName: process.env.SALEOR_AGENTIC_STORE_NAME!,
storeDescription: process.env.SALEOR_AGENTIC_STORE_DESCRIPTION,
})
Important: Look at the project's existing env var naming patterns. If they use NEXT_PUBLIC_SALEOR_API_URL, match that. If they use SALEOR_API_URL (without NEXT_PUBLIC_), use that instead.
Create the following route handler files. Detect the app router root:
src/app/ or app/ — whichever exists.All routes go under {app-root}/api/ucp/.
api/ucp/route.tsimport { NextRequest, NextResponse } from "next/server"
import { agenticCommerce } from "@/lib/agentic-commerce"
import { formatUcpProfile } from "@financedistrict/saleor-agentic-commerce-core"
export async function GET() {
const profile = formatUcpProfile(agenticCommerce.formatterContext)
return NextResponse.json(profile, {
headers: { "X-UCP-Version": agenticCommerce.config.ucpVersion },
})
}
api/ucp/checkout/route.tsimport { NextRequest, NextResponse } from "next/server"
import { agenticCommerce } from "@/lib/agentic-commerce"
import { formatUcpCheckoutSession } from "@financedistrict/saleor-agentic-commerce-core"
export async function POST(request: NextRequest) {
const body = await request.json()
const { items, buyer } = body
const lines = items.map((item: any) => ({
variantId: item.variant_id || item.id,
quantity: item.quantity,
}))
const result = await agenticCommerce.saleorClient.createCheckout({
lines,
email: buyer?.email,
})
if (!result.ok) {
return NextResponse.json(
{ error: { message: result.error } },
{ status: 400 }
)
}
const session = formatUcpCheckoutSession(
result.data,
agenticCommerce.formatterContext
)
return NextResponse.json(session, { status: 201 })
}
api/ucp/checkout/[id]/route.tsimport { NextRequest, NextResponse } from "next/server"
import { agenticCommerce } from "@/lib/agentic-commerce"
import { formatUcpCheckoutSession } from "@financedistrict/saleor-agentic-commerce-core"
export async function GET(
_request: NextRequest,
{ params }: { params: { id: string } }
) {
const result = await agenticCommerce.saleorClient.getCheckout(params.id)
if (!result.ok) {
return NextResponse.json(
{ error: { message: result.error } },
{ status: 404 }
)
}
const session = formatUcpCheckoutSession(
result.data,
agenticCommerce.formatterContext
)
return NextResponse.json(session)
}
api/ucp/checkout/[id]/complete/route.tsimport { NextRequest, NextResponse } from "next/server"
import { agenticCommerce } from "@/lib/agentic-commerce"
import { formatUcpCompleteResponse } from "@financedistrict/saleor-agentic-commerce-core"
export async function POST(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const body = await request.json()
// Handle payment if credential provided
if (body.payment?.credential) {
const handler = agenticCommerce.paymentHandlers.getHandler(
body.payment.credential.handler_id || body.payment.handler_id
)
if (handler) {
await handler.settlePayment({
checkoutId: params.id,
handlerId: handler.id,
amount: body.payment.amount,
currency: body.payment.currency,
credential: body.payment.credential,
metadata: {},
})
}
}
const result = await agenticCommerce.saleorClient.completeCheckout(params.id)
if (!result.ok) {
return NextResponse.json(
{ error: { message: result.error } },
{ status: 400 }
)
}
const response = formatUcpCompleteResponse(
result.data,
agenticCommerce.formatterContext
)
return NextResponse.json(response)
}
api/ucp/orders/[id]/route.tsimport { NextRequest, NextResponse } from "next/server"
import { agenticCommerce } from "@/lib/agentic-commerce"
import { formatUcpOrder } from "@financedistrict/saleor-agentic-commerce-core"
export async function GET(
_request: NextRequest,
{ params }: { params: { id: string } }
) {
const result = await agenticCommerce.saleorClient.getOrder(params.id)
if (!result.ok) {
return NextResponse.json(
{ error: { message: result.error } },
{ status: 404 }
)
}
const order = formatUcpOrder(result.data, agenticCommerce.formatterContext)
return NextResponse.json(order)
}
Add these to the project's .env.local (or .env). Check which env file the project uses.
Also update .env.example if it exists — append to the end under a clear section header.
# ─── Agentic Commerce (AI Agent Shopping) ───────────────
SALEOR_AGENTIC_AUTH_TOKEN= # Saleor App Token with MANAGE_CHECKOUTS + MANAGE_ORDERS
SALEOR_AGENTIC_STORE_NAME= # Store name shown to AI agents
SALEOR_AGENTIC_STORE_DESCRIPTION= # Optional store description
NEXT_PUBLIC_STOREFRONT_URL= # Public URL of this storefront (e.g., https://store.com)
Important: SALEOR_AGENTIC_AUTH_TOKEN is a Saleor App Token — not a user token. The developer needs to create an App in Saleor Dashboard → Configuration → Service Accounts (or Apps) with MANAGE_CHECKOUTS and MANAGE_ORDERS permissions.
After creating all files, show the developer:
The route structure created:
api/ucp/
├── route.ts → GET /api/ucp (discovery profile)
└── checkout/
├── route.ts → POST /api/ucp/checkout (create)
└── [id]/
├── route.ts → GET /api/ucp/checkout/:id
└── complete/
└── route.ts → POST /api/ucp/checkout/:id/complete
api/ucp/orders/
└── [id]/
└── route.ts → GET /api/ucp/orders/:id
Required env vars that need values.
How to test:
# Start the dev server
npm run dev
# Test the discovery endpoint
curl http://localhost:3000/api/ucp | jq .
Next steps:
/add-payment-handler to add stablecoin payments via PrismIf you encounter issues during setup:
Module not found after install → Check the import paths match the project's tsconfig paths (@/ alias).next version too old → SDK requires Next.js 14+. Suggest upgrading.