API Reference

Everything a Custom Website storefront needs to call ExiusCart directly — products, checkout, payment, customer accounts, and more. No ExiusCart login is required to read this page or to call any endpoint marked No auth.

Base URLhttps://api.exiuscart.com/api/v1

Every path below is appended directly to that base URL. Every endpoint is scoped to your store either by a {shop_slug} in the path, or by an opaque token (order number + email, a review link, a download code) — never by an ExiusCart seller login. CORS is open, so you can call these directly from the browser.

No authCustomer tokenOptional customer tokenGateway webhook only

Customer token and Optional customer token mean a JWT from Customer Auth below, sent as Authorization: Bearer <token>. Gateway webhook only means your storefront should never call it — it exists purely for PayHere/Stripe to call directly.

Categories

Your storefront’s category tree, for nav menus and category pages.

GET/public/store/{shop_slug}/categoriesNo auth

Storefront category tree, for nav/grid display.

Params/Body Query: channel (default "custom")
Response [{ id, name, slug, icon_url, parent_id }]

Products

Listing, detail, and reviews for products you’ve enabled on your Custom Website channel. A product only appears here once the seller has explicitly turned it on for this channel — nothing shows by default.

GET/public/store/{shop_slug}/productsNo auth

Product listing for a grid/search page.

Params/Body Query: search, featured, trending, category (slug)
Response Array of products: id, name, slug, description, currency, price, compare_at_price, in_stock, product_type, affiliate_url, affiliate_cta_text, faq[] ({question, answer}), shipping_note, shipping_steps[], seo_keywords[], highlights[] ({icon, label}), quantity, images[], video_url, videos[], tags[], variants[], category_id, category_slug, category_ids[], category_slugs[], quantity_tiers[], avg_rating, review_count, view_count, units_sold, custom_fields
GET/public/store/{shop_slug}/products/{slug}No auth

Single product detail page (PDP). Increments the product’s view count on each call.

Response Same shape as the listing, single object. category_ids/category_slugs carry every category the product belongs to — a product can be filed under more than one. product_type is "physical" | "digital" | "affiliate" — for "affiliate", render affiliate_cta_text (fallback "Buy Now") as a link straight to affiliate_url instead of an Add to Cart button; the checkout endpoint below rejects affiliate products server-side if one is submitted anyway. description is rich HTML from the dashboard editor — render it with dangerouslySetInnerHTML (or equivalent), not as plain text. It can include a seller-inserted pill row (a <div> of <span> tags for things like skills/features) that carries its own inline style="..." attributes rather than relying on any ExiusCart stylesheet — if you sanitize this HTML before rendering, make sure your sanitizer’s allowlist keeps the style attribute on div/span, or those pills will silently lose their styling and show as plain text. faq is an optional seller-written Q&A list to render below the description; shipping_note is an optional free-text shipping/returns blurb (physical products only); shipping_steps is an optional ordered string array — render as a connected arrow-flow, falling back to shipping_note when empty; seo_keywords is an optional string array the seller is targeting — use it to build your own meta title/description and schema.org Product structured data, it is not meant to populate a raw <meta name="keywords"> tag; highlights is an optional array of {icon, label} short facts meant to render under the price (e.g. "1 Year Access", "Delivered by Email") — never sent for affiliate products — where icon is always one of a fixed set: clock, calendar, mail, truck, package, shield, download, check-circle, refresh-cw, star, gift, tag. All render only when non-empty, no fallback copy.
GET/public/store/{shop_slug}/products/{slug}/reviewsNo auth

Approved reviews for one product.

Response [{ id, customer_name, rating, comment, photo_url, submitted_at }]
GET/public/product/{barcode}No auth

Product + active reservations lookup for a QR/barcode page. Not shop_slug-scoped.

Response name, sku, barcode, price, currency, stock, reserved, available, shop_name, image_url, category, reservations[]

Reviews

Submitting a review from a post-delivery email link, and the embeddable review widget.

GET/public/review/{token}No auth

Review-request landing page data, from the link in a post-delivery email.

Response product_name, product_image, shop_name, customer_name, already_submitted, rating, comment
POST/public/review/{token}/submitNo auth

Submit a review via the request-link token.

Params/Body Body: rating (1–5), comment?, photo_url?
Response { submitted: true }
POST/public/review/{token}/photoNo auth

Upload a photo for that review.

Params/Body multipart file (≤ 8MB, jpg/jpeg/png/webp)
Response { url }
GET/public/products/{product_id}/reviewsNo auth

Approved reviews for the embeddable widget, by raw product id.

Response { avg_rating, count, reviews: [{ customer_name, rating, comment, photo_url, submitted_at }] }
GET/widget/reviews.jsNo auth

Static embeddable script — drop it in and it auto-mounts any element with data-exiuscart-reviews.

Customer Auth

Signup/login for shoppers on your storefront. Returns a customer JWT (type: "customer") that’s only valid on the customer-scoped endpoints below — it’s a different token type than a seller session and can’t be used to access the ExiusCart dashboard.

POST/public/store/{shop_slug}/auth/signupNo auth

Create a storefront customer account.

Params/Body Body: name, email, password (min 8 chars)
Response { token, customer: { id, name, email } }
POST/public/store/{shop_slug}/auth/loginNo auth

Log an existing customer in.

Params/Body Body: email, password
Response { token, customer: { id, name, email } }

Send the token as Authorization: Bearer <token> on any endpoint below marked "customer" or "optional".

Checkout & Orders

Placing an order, guest or logged-in, and tracking it afterward.

POST/public/store/{shop_slug}/checkoutOptional customer token

Create a pending order and get back the payment gateway’s request parameters. Works for a guest (just name/email) or a logged-in customer. Stock is validated here but not yet decremented — that happens once payment is confirmed.

Params/Body Body: items [{ product_id, quantity, variant_id? }], name, email, phone?, shipping_address?, use_wallet_amount? (logged-in only), return_url? / cancel_url? (Stripe & PayPal)
Response { order_number, total, payment: { gateway, order_id, ...gateway-specific fields — see Payment below } }
GET/public/store/{shop_slug}/orders/{order_number}No auth

Guest order lookup/tracking — matched by order number + the email it was placed with.

Params/Body Query: email (required)
Response { order_number, status, payment_status, total, items: [{ product_name, quantity, unit_price, total_price, variant_size, variant_color }], created_at, tracking_number, carrier, shipped_at, estimated_delivery }. status is "pending" | "confirmed" | "processing" | "shipped" | "delivered" | "cancelled" — moves to "confirmed" automatically once payment_status becomes "paid"; every status after that is set manually by the seller from their dashboard. tracking_number/carrier/shipped_at are null until the seller marks the order shipped — treat null as "not shipped yet", not an error.
GET/public/store/{shop_slug}/payment-return/paypalNo auth

PayPal redirects the shopper back here after approval; this captures the payment server-to-server, then redirects onward to your site.

Params/Body Query: order_number, redirect_to, token (PayPal order id)
Response 302 redirect to {redirect_to}?payment=success|failed&order_number=...

Payment

PayHere, Stripe, and PayPal are all supported. The gateway is configured per-seller in their ExiusCart dashboard; checkout’s response tells you which one is active and what to do with it.

POST/public/payment-webhook/{shop_slug}Gateway webhook only

Server-to-server only — the payment gateway calls this directly, your storefront never does. Signature-verified before anything is trusted; marks the order paid, decrements stock, credits wallet cashback, and triggers digital delivery if applicable.

Wallet

Store credit earned as cashback on paid orders, spendable at checkout.

GET/public/store/{shop_slug}/walletCustomer token

Balance and the last 50 transactions for the logged-in customer.

Response { balance, currency, transactions: [{ type, amount, description, created_at }] }

Spend it by passing use_wallet_amount in the checkout body above — capped server-side at the real balance, and only ever debited from the authenticated customer’s own account, never a guest email.

Digital Delivery

The download gate for digital products — the real file link is only ever revealed after a code sent by email is verified.

GET/public/download/{token}No auth

Download gate landing page — reveals the product/shop name only, never the file.

Response { product_name, shop_name }
POST/public/download/{token}/verifyNo auth

Verify the emailed access code. Rate-limited to 10 attempts/hour/token.

Params/Body Body: code
Response { file_url, file_name }

Blog

GET/public/store/{shop_slug}/blogNo auth

Published post list (omits the full content field, for a lighter list view).

Params/Body Query: tag?
Response [{ id, title, slug, excerpt, cover_image_url, status, published_at, author_name, tags[], cta_text, cta_url, view_count, created_at, updated_at }]
GET/public/store/{shop_slug}/blog/{slug}No auth

Single post detail. Increments view count.

Response Same shape, plus content.

Popups

Announcement, exit-intent, email-capture, and countdown popups the seller has built.

GET/public/popups/{shop_id}No auth

Active popups for the embed script. Note: shop_id, not slug.

Response { popups: [{ id, popup_type, title, message, button_text, button_link, discount_code, image_url, delay_seconds }] }
POST/public/popups/{popup_id}/trackNo auth

Track an impression or click.

Params/Body Query: event ("impression" | "click")
Response { ok: true }
GET/widget/popup.jsNo auth

Static embeddable script that renders the popups above.

Signup Forms & Lead Capture

Seller-built lead forms, plus a way to mirror submissions from a form that already exists on your own site.

GET/public/signup-forms/{shop_id}No auth

Active custom-built signup/inquiry forms.

Response { forms: [{ id, title, description, fields[], delay_seconds }] }
POST/public/signup-forms/{form_id}/trackNo auth

Track a form impression.

Response { ok: true }
POST/public/signup-forms/{form_id}/submitNo auth

Submit answers — creates a Lead in the seller’s CRM if an email field is present.

Params/Body Body: { answers: { field_id: value } }
Response { status, success_message, discount_code }
POST/public/capture-form/{shop_id}/submitNo auth

Mirrors a submission of your own existing HTML form (tagged data-exiuscart-capture) into the Lead CRM, without changing how that form behaves.

Params/Body Body: { fields: [{ name?, id?, type?, value? }], url? }
Response { status: "ok" }
GET/widget/signup-form.jsNo auth

Static embeddable script — renders custom forms and passively mirrors tagged existing forms.

Misc & Utility

GET/public/check-ref/{code}No auth

Check whether an affiliate referral code is active.

Response { valid: boolean }
GET/public/reservation/{reservation_id}No auth

Reservation info for a QR-code public page.

Response id, customer_name, customer_phone, product_name, quantity, reservation_type, status, advance_amount, notes, expires_at, shop_name, currency, product_stock, product_reserved
GET/public/quotation/{token}No auth

A client views a shared B2B quotation.

Response quote_number, shop_name, items, subtotal, discount, tax, total, status, valid_until, and more
POST/public/quotation/{token}/respondNo auth

Client accepts or rejects a quotation.

Params/Body Body: { action: "accept" | "reject", name? }
Response { status }
GET/shops/exchange-ratesNo auth

Live currency conversion rates (12h cache). Not shop-scoped — a general utility.

Params/Body Query: base (default "USD")
Response { base, rates, cached, stale? }
Questions about integrating? Reach out at dropshipping@exiuscart.com.
1