Developer docs
Custom Store API contract
Two endpoints connect any custom ecommerce platform to ProdexIQ — full audits plus one-click fixes, same as Shopify/WooCommerce.
1 · Read — list products
We call GET {apiBase}/products with your bearer token. Return up to 250 products — more is truncated. Missing fields are fine; we only check what you send.
GET /products?limit=250
Authorization: Bearer <token>
→ 200 OK — array (or {"products": [...]})
[{
"id": "123",
"handle": "trail-runner-cap", // optional — derived from name if absent
"name": "Trail Runner Cap",
"description": "<p>…</p>", // html or plain text
"short_description": "Lightweight…", // optional — near-price summary slot
"price": "24.00",
"sku": "TR-CAP-01",
"brand": "Summit Pro", // or "vendor"
"categories": [{"name": "Clothing"}], // or ["Clothing"]
"tags": ["cap", "running"],
"status": "publish", // publish|draft — drafts counted separately
"seo_title": "Trail Runner Cap | Store", // optional — meta title
"seo_description": "…", // optional — meta description
"images": [{"url": "https://…", "alt": "…"}],
"variants": [{"sku": "…", "price": "…", "barcode": "…"}] // optional
}]2 · Write — apply fixes
Approved fixes arrive as a PUT patch to the product. Only send the fields you want to support — unsupported fields can be ignored safely. Return the updated product so we can verify the write persisted.
PUT /products/{id}
Authorization: Bearer <token>
Content-Type: application/json
{
"description": "…",
"short_description": "…",
"seo_title": "…",
"seo_description": "…",
"categories": ["Clothing"], // name list — create terms as needed
"images": [{"url": "…", "alt": "…"}] // full array with alt patched
}
→ 200 OK — respond with the updated product object (same shape as GET)Read-only? Implement just GET — the connected audit works fully; the fixes page will report write failures clearly.
Starter implementation
// Next.js App Router example — app/api/catalog/products/route.ts
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db"; // your data layer
const TOKEN = process.env.PRODEXIQ_API_TOKEN!;
function authed(req: NextRequest) {
return req.headers.get("authorization") === `Bearer ${TOKEN}`;
}
export async function GET(req: NextRequest) {
if (!authed(req)) return NextResponse.json({}, { status: 401 });
const products = await db.product.findMany({ take: 250 });
return NextResponse.json(products.map((p) => ({
id: p.id, name: p.name, description: p.description,
price: p.price, sku: p.sku, brand: p.brand,
categories: p.categories, images: p.images,
seo_title: p.seoTitle, seo_description: p.seoDescription,
status: p.published ? "publish" : "draft",
})));
}
// app/api/catalog/products/[id]/route.ts
export async function PUT(req: NextRequest, { params }) {
if (!authed(req)) return NextResponse.json({}, { status: 401 });
const { id } = await params;
const patch = await req.json();
const p = await db.product.update({ where: { id }, data: patch });
return NextResponse.json(p);
}Security
- HTTPS only — we reject plain-http and private/localhost addresses
- Generate a long random token (e.g.
openssl rand -hex 32) and keep it in an env var - Your token is AES-256-GCM encrypted at rest in ProdexIQ and never displayed again
- Only expose catalog endpoints — never admin or customer data
- Rotate the token anytime to revoke access