nanocart

API Documentation

Everything you need to integrate nanocart into your site.

https://api.nanocart.io

Widget Integration

Add the nanocart widget to any page with a single script tag. No build step, no dependencies.

Script Tag

Include this once per page, replacing your-store with your store ID:

HTML
<script src="https://cdn.nanocart.io/v1/nanocart.min.js"
  data-store-id="your-store"></script>

Button Types

Use data attributes to create interactive buttons. All you need is the product slug from your admin panel.

AttributeBehaviorExample
data-nanocart-buy="slug"Adds product to cart and opens the cart drawer. Best for "Buy Now" actions.<button data-nanocart-buy="trucker-hat">Buy Now</button>
data-nanocart-add="slug"Adds product to cart and opens the cart drawer. Same as buy, use whichever label fits.<button data-nanocart-add="trucker-hat">Add to Cart</button>
data-nanocart-product="slug"Opens a product detail modal with image, variant selector, and add-to-cart.<button data-nanocart-product="trucker-hat">View Details</button>

Full Example

HTML
<!DOCTYPE html>
<html>
<body>
  <h1>My Store</h1>

  <button data-nanocart-buy="trucker-hat">Buy Now</button>
  <button data-nanocart-product="trucker-hat">View Details</button>

  <script src="https://cdn.nanocart.io/v1/nanocart.min.js"
    data-store-id="your-store"></script>
</body>
</html>

JavaScript API

The widget exposes window.nanocart for programmatic control:

JS
// Add product by slug
nanocart.addBySlug('trucker-hat');

// Open product detail modal
nanocart.viewProduct('trucker-hat');

// Cart controls
nanocart.open();
nanocart.close();
nanocart.toggle();
nanocart.getItems();
nanocart.getCount();
nanocart.getSubtotal();
nanocart.clear();

Authentication

Public endpoints (products, categories, checkout) require no authentication. They're meant to be called from your storefront.

Admin endpoints require an API key passed in the x-api-key header. You can find your API key in the admin panel under Settings.

bash
curl https://api.nanocart.io/shop/my-store/admin/products \
  -H "x-api-key: sc_live_your_api_key_here"
API Key Format: sc_live_ followed by 64 hex characters. Keep your API key secret — it provides full admin access to your store.

Conventions

Prices

All monetary values are in cents (integers). Divide by 100 for display.

API ValueDisplay
999$9.99
2800$28.00
0$0.00 (free)

Pagination

List endpoints return a lastKey field. If non-null, pass it as a query parameter to get the next page:

GET /shop/my-store/products?limit=20&lastKey=eyJzdG9yZUlkIjoi...

Dates

All timestamps are ISO 8601 UTC strings: 2026-02-24T15:30:00Z

Response Format

All responses return JSON with appropriate HTTP status codes. Error responses include an error field and optional code field.

Service Tiers

Each store has a tier that determines limits. Upgrade from the admin panel or via the subscription API.

LimitFreeStandardProExpert
Price$0$5/mo$10/mo$25/mo
Active Products525100Unlimited
Monthly Orders55005,000Unlimited
Coupons1510Unlimited
File Upload5 MB25 MB50 MB500 MB
Shipping MethodsFlat rate, FreeAllAllAll
Local PickupNoYesYesYes

Public API

These endpoints require no authentication. Call them from your storefront to display products and process orders.

GET /shop/{storeId}/products
List active products with optional filtering, sorting, and pagination.

Query Parameters

ParameterTypeDefaultDescription
categorystringFilter by category slug
sortstringnewestnewest, price, or featured
limitinteger50Max results per page (max 50)
lastKeystringPagination token from previous response

Response

JSON
{
  "products": [
    {
      "productId": "dd9392ed-ea5a-494c-adbc-a8ce5288c2e8",
      "slug": "trucker-surf-hat",
      "name": "Trucker Surf Hat",
      "price": 2800,
      "compareAtPrice": null,
      "images": ["https://images.unsplash.com/photo-..."],
      "variants": [
        {
          "variantId": "d90da05a",
          "name": "Adjustable / Navy",
          "price": 2800,
          "sku": "TSH-ADJ-NVY"
        }
      ],
      "featured": false,
      "categoryId": "abc-123",
      "inventory": 50,
      "productType": "physical",
      "status": "active",
      "createdAt": "2026-02-23T20:59:28Z",
      "updatedAt": "2026-02-23T20:59:28Z"
    }
  ],
  "lastKey": null
}
GET /shop/{storeId}/products/{slug}
Get full details for a single product by slug.

Response

JSON
{
  "product": {
    "productId": "dd9392ed-ea5a-494c-adbc-a8ce5288c2e8",
    "slug": "trucker-surf-hat",
    "name": "Trucker Surf Hat",
    "description": "Classic trucker hat with embroidered surf logo.",
    "price": 2800,
    "compareAtPrice": null,
    "categoryId": "abc-123",
    "images": ["https://images.unsplash.com/photo-..."],
    "variants": [
      {
        "variantId": "d90da05a",
        "name": "Adjustable / Navy",
        "price": 2800,
        "sku": "TSH-ADJ-NVY",
        "inventory": 25
      }
    ],
    "options": [
      { "name": "Size", "values": ["Adjustable"] },
      { "name": "Color", "values": ["Navy", "Black"] }
    ],
    "inventory": 50,
    "productType": "physical",
    "shippingRequired": true,
    "taxable": true,
    "tags": ["hats", "surf"],
    "featured": false,
    "status": "active",
    "createdAt": "2026-02-23T20:59:28Z",
    "updatedAt": "2026-02-23T20:59:28Z"
  }
}

Errors

StatusResponse
404{"error": "Product not found"}
GET /shop/{storeId}/categories
List all active categories for a store, sorted by sortOrder. Categories support a parent/child hierarchy via the parentId field. Top-level categories have an empty parentId. Subcategories reference their parent's categoryId.

Response

JSON
{
  "categories": [
    {
      "categoryId": "cat-001",
      "name": "Men's",
      "slug": "mens",
      "description": "Men's clothing and accessories",
      "image": "https://...",
      "parentId": "",
      "sortOrder": 0,
      "status": "active"
    },
    {
      "categoryId": "cat-002",
      "name": "Shirts",
      "slug": "shirts",
      "description": "Men's shirts",
      "image": "https://...",
      "parentId": "cat-001",
      "sortOrder": 0,
      "status": "active"
    },
    {
      "categoryId": "cat-003",
      "name": "Pants",
      "slug": "pants",
      "description": "",
      "image": "",
      "parentId": "cat-001",
      "sortOrder": 1,
      "status": "active"
    }
  ]
}

Category Fields

FieldTypeDescription
categoryIdstringUnique category identifier
namestringCategory display name
slugstringURL-friendly name (unique within store)
descriptionstringOptional description
imagestringOptional image URL (for category cards)
parentIdstringEmpty string for top-level categories. Set to a parent categoryId to make this a subcategory.
sortOrdernumberDisplay order (lower = first)
statusstringactive or hidden
Subcategory pattern: To build a hierarchical category tree, filter categories where parentId is empty to get top-level parents, then filter where parentId === parent.categoryId to get children. Products are assigned to a single categoryId — when displaying a parent category, you may want to also include products from its subcategories.
POST /shop/{storeId}/coupons/validate
Validate a coupon code and calculate the discount amount.

Request Body

JSON
{
  "code": "SAVE20",
  "subtotal": 4999
}

Response (valid)

JSON
{
  "valid": true,
  "type": "percent_off",
  "value": 20,
  "discountAmount": 999,
  "message": "20% off applied!"
}

Response (invalid)

JSON
{
  "valid": false,
  "message": "This coupon has expired"
}
Coupon Types: percent_off, fixed_amount, free_shipping
POST /shop/{storeId}/checkout
Create a Stripe Checkout Session. Validates inventory, applies coupons, calculates shipping and tax, and returns a Stripe payment URL.

Request Body

JSON
{
  "items": [
    {
      "productId": "dd9392ed-ea5a-494c-adbc-a8ce5288c2e8",
      "variantId": "d90da05a",
      "quantity": 2
    }
  ],
  "email": "customer@example.com",
  "couponCode": "SAVE20",
  "shippingMethod": "standard"
}
FieldTypeRequiredDescription
itemsarrayrequiredCart items with productId, optional variantId, and quantity
emailstringrequiredCustomer email for order confirmation
couponCodestringoptionalCoupon code to apply
shippingMethodstringoptionalstandard (default) or local_pickup

Response

JSON
{
  "sessionUrl": "https://checkout.stripe.com/c/pay/cs_live_...",
  "orderId": "a1b2c3d4-e5f6-..."
}

Redirect the customer to sessionUrl to complete payment on Stripe.

Errors

StatusError
400Cart is empty
400Email address is required for checkout.
400Product {id} is not available
400{item} is out of stock
403This store has reached its monthly order limit
GET /shop/{storeId}/orders/{orderId}?email=customer@example.com
Look up an order by ID. Requires the customer's email for verification.

Query Parameters

ParameterTypeRequiredDescription
emailstringrequiredMust match the order's email

Response

JSON
{
  "order": {
    "orderId": "a1b2c3d4-e5f6-...",
    "orderNumber": "MYS-1001",
    "email": "customer@example.com",
    "customerName": "John Doe",
    "items": [
      {
        "productId": "dd9392ed-...",
        "name": "Trucker Surf Hat",
        "variantName": "Adjustable / Navy",
        "price": 2800,
        "quantity": 2
      }
    ],
    "subtotal": 5600,
    "shippingCost": 499,
    "shippingMethod": "standard",
    "taxAmount": 336,
    "discountAmount": 0,
    "total": 6435,
    "shippingAddress": {
      "name": "John Doe",
      "line1": "123 Main St",
      "city": "Charleston",
      "state": "SC",
      "zip": "29401",
      "country": "US"
    },
    "status": "paid",
    "createdAt": "2026-02-24T12:00:00Z"
  }
}
GET /shop/{storeId}/storefront-config
Get the storefront configuration for a hosted store. Used by the storefront SPA on page load to get template, branding, and content settings. Only works for stores with an active hosted plan.

Response

JSON
{
  "storeId": "my-store",
  "storeName": "My Store",
  "currency": "usd",
  "template": "classic",
  "accentColor": "#418a9e",
  "backgroundColor": "#FFFFFF",
  "textColor": "#333333",
  "storeDescription": "Your store description here",
  "aboutContent": "About page content...",
  "aboutTitle": "About My Store",
  "aboutImage": "https://...",
  "heroTitle": "Welcome to My Store",
  "heroLayout": "center",
  "heroImage": "",
  "logo": "https://...",
  "showStoreName": true,
  "favicon": "",
  "announcementBar": {
    "enabled": false,
    "text": "",
    "backgroundColor": "#418a9e",
    "textColor": "#FFFFFF"
  },
  "socialLinks": {
    "instagram": "",
    "twitter": "",
    "facebook": "",
    "tiktok": "",
    "youtube": ""
  },
  "showPoweredBy": true
}

Admin API

All admin endpoints require authentication via the x-api-key header.

Stores

GET /shop/admin/stores
List all stores you have access to.

Response

JSON
{
  "stores": [
    {
      "storeId": "my-store",
      "name": "My Store",
      "tier": "standard",
      "status": "active",
      "domain": "https://mystore.com",
      "contactEmail": "me@mystore.com",
      "currency": "usd",
      "brandColor": "#418a9e",
      "apiKey": "sc_live_...",
      "createdAt": "2026-02-20T10:00:00Z"
    }
  ]
}
POST /shop/admin/stores
Create a new store. Returns the store details and API key.

Request Body

JSON
{
  "storeId": "my-store",
  "name": "My Store",
  "domain": "https://mystore.com",
  "contactEmail": "me@mystore.com",
  "stripePublishableKey": "pk_live_...",
  "stripeSecretKey": "sk_live_...",
  "stripeWebhookSecret": "whsec_...",
  "brandColor": "#418a9e"
}
FieldTypeRequiredDescription
storeIdstringrequired3-32 chars, lowercase alphanumeric + hyphens
namestringoptionalDisplay name
domainstringoptionalYour storefront URL
contactEmailstringoptionalStore contact email
stripePublishableKeystringoptionalStripe publishable key (pk_live_ or pk_test_)
stripeSecretKeystringoptionalStripe secret key (sk_live_ or sk_test_)
stripeWebhookSecretstringoptionalStripe webhook secret (whsec_)
brandColorstringoptionalHex color for widget branding

Response (201)

JSON
{
  "store": { ... },
  "apiKey": "sc_live_abc123...",
  "message": "Store created successfully. Save your API key."
}
PUT /shop/admin/stores/{storeId}
Update store settings. Only include fields you want to change.

Request Body

JSON
{
  "name": "New Store Name",
  "domain": "https://newdomain.com",
  "brandColor": "#4292e7",
  "allowedDomains": ["mystore.com", "www.mystore.com"]
}
Allowed Domains: If set, only these domains can call your public API. Max 10 domains. Leave empty to allow all origins.
POST /shop/admin/stores/{storeId}/regenerate-key
Regenerate your API key. The old key becomes invalid immediately.

Response

JSON
{
  "apiKey": "sc_live_new_key_here...",
  "message": "API key regenerated. Old key is now invalid."
}

Products

POST /shop/{storeId}/admin/products
Create a new product.

Request Body

JSON
{
  "name": "Trucker Surf Hat",
  "price": 2800,
  "description": "Classic trucker hat with embroidered surf logo.",
  "categoryId": "abc-123",
  "compareAtPrice": 3500,
  "inventory": 50,
  "images": ["https://..."],
  "variants": [
    {
      "variantId": "d90da05a",
      "name": "Adjustable / Navy",
      "price": 2800,
      "sku": "TSH-ADJ-NVY",
      "inventory": 25
    }
  ],
  "options": [
    { "name": "Size", "values": ["Adjustable"] },
    { "name": "Color", "values": ["Navy", "Black"] }
  ],
  "productType": "physical",
  "taxable": true,
  "tags": ["hats"],
  "status": "active",
  "featured": false
}
FieldTypeRequiredDescription
namestringrequiredProduct name
priceintegerrequiredPrice in cents
descriptionstringoptionalHTML description
categoryIdstringoptionalCategory UUID
compareAtPriceintegeroptionalOriginal price for sale display (must be > price)
inventoryintegeroptionalStock quantity. Null = unlimited.
imagesarrayoptionalArray of image URLs
variantsarrayoptionalProduct variants (variantId, name, price, sku, inventory)
optionsarrayoptionalOption definitions for variant generation
productTypestringoptionalphysical (default) or digital
statusstringoptionaldraft (default), active
featuredbooleanoptionalFeatured product flag
slugstringoptionalURL slug. Auto-generated from name if omitted.
taxablebooleanoptionalSubject to tax (default true)
tagsarrayoptionalString tags for organization
shippingCostintegeroptionalPer-item shipping cost in cents (for per_item method)

Response (201)

JSON
{
  "product": {
    "productId": "dd9392ed-...",
    "slug": "trucker-surf-hat",
    "name": "Trucker Surf Hat",
    ...
  }
}
PUT /shop/{storeId}/admin/products
Update an existing product. Only include fields you want to change.

Request Body

JSON
{
  "productId": "dd9392ed-ea5a-494c-adbc-a8ce5288c2e8",
  "price": 3200,
  "inventory": 40,
  "status": "active"
}
FieldTypeRequiredDescription
productIdstringrequiredProduct UUID to update

All other fields from Create are accepted. Only provided fields are updated.

DELETE /shop/{storeId}/admin/products
Archive a product. It remains in the database but is hidden from public listings.

Request Body

JSON
{
  "productId": "dd9392ed-ea5a-494c-adbc-a8ce5288c2e8"
}

Categories

POST /shop/{storeId}/admin/categories
Create a new category. Set parentId to create a subcategory under an existing parent category.

Request Body

FieldTypeRequiredDescription
namestringrequiredCategory name
descriptionstringoptionalCategory description
imagestringoptionalImage URL (use the upload endpoint to get a URL first)
parentIdstringoptionalSet to a parent categoryId to make this a subcategory. Omit or send empty string for top-level.
sortOrdernumberoptionalDisplay order (default: 0)
statusstringoptionalactive (default) or hidden

Example: Top-level category

JSON
{
  "name": "Men's",
  "description": "Men's clothing and accessories",
  "image": "https://...",
  "sortOrder": 0
}

Example: Subcategory

JSON
{
  "name": "Shirts",
  "description": "Men's shirts",
  "parentId": "cat-001",
  "image": "https://...",
  "sortOrder": 0
}
PUT /shop/{storeId}/admin/categories
Update a category. Only include the fields you want to change (plus categoryId which is always required).

Updatable Fields

name, slug, description, image, parentId, sortOrder, status

Example: Move to subcategory and update sort order

JSON
{
  "categoryId": "cat-002",
  "parentId": "cat-001",
  "sortOrder": 2
}

Example: Promote to top-level

JSON
{
  "categoryId": "cat-002",
  "parentId": ""
}
DELETE /shop/{storeId}/admin/categories
Hide a category. Sets status to "hidden". Note: hiding a parent category does not automatically hide its subcategories.
JSON
{
  "categoryId": "abc-123"
}

Coupons

GET /shop/{storeId}/admin/coupons
List all coupons for this store.
JSON
{
  "coupons": [
    {
      "code": "SAVE20",
      "type": "percent_off",
      "value": 20,
      "minOrderAmount": 5000,
      "maxUses": 100,
      "currentUses": 42,
      "expiresAt": "2026-12-31T23:59:59Z",
      "status": "active"
    }
  ]
}
POST /shop/{storeId}/admin/coupons
Create a new coupon.
JSON
{
  "code": "SAVE20",
  "type": "percent_off",
  "value": 20,
  "minOrderAmount": 5000,
  "maxUses": 100,
  "expiresAt": "2026-12-31T23:59:59Z",
  "status": "active"
}
FieldTypeRequiredDescription
codestringrequiredCoupon code (auto-uppercased)
typestringrequiredpercent_off, fixed_amount, or free_shipping
valueintegerrequiredPercentage (1-100) or cents amount
minOrderAmountintegeroptionalMinimum subtotal in cents
maxUsesintegeroptionalMax number of times coupon can be used
expiresAtstringoptionalISO datetime when coupon expires
PUT /shop/{storeId}/admin/coupons
Update a coupon. Code is required to identify which coupon to update.
JSON
{
  "code": "SAVE20",
  "value": 25,
  "maxUses": 200
}
DELETE /shop/{storeId}/admin/coupons
Deactivate a coupon.
JSON
{
  "code": "SAVE20"
}

Orders

GET /shop/{storeId}/admin/orders
List orders with optional filtering.

Query Parameters

ParameterTypeDescription
statusstringFilter by status (e.g. paid, shipped)
fromstringISO datetime to filter from
tostringISO datetime to filter to
limitintegerResults per page (default 50)
lastKeystringPagination token

Response

JSON
{
  "orders": [
    {
      "orderId": "a1b2c3d4-...",
      "orderNumber": "MYS-1001",
      "email": "customer@example.com",
      "customerName": "John Doe",
      "items": [...],
      "subtotal": 5600,
      "shippingCost": 499,
      "taxAmount": 336,
      "discountAmount": 0,
      "total": 6435,
      "status": "paid",
      "trackingNumber": null,
      "createdAt": "2026-02-24T12:00:00Z"
    }
  ],
  "lastKey": null
}
PUT /shop/{storeId}/admin/orders/{orderId}
Update order status, tracking number, or notes.
JSON
{
  "status": "shipped",
  "trackingNumber": "1Z999AA10123456784",
  "notes": "Shipped via UPS"
}

Settings

GET /shop/{storeId}/admin/settings
Get all store settings (tax, shipping, email, order config).
JSON
{
  "settings": {
    "tax_config": {
      "enabled": true,
      "defaultRate": 0.06,
      "stateRates": { "SC": 0.06, "NC": 0.07, "NY": 0.08 }
    },
    "shipping_config": {
      "method": "flat_rate",
      "flatRate": 499,
      "freeShippingEnabled": false,
      "freeShippingThreshold": 5000,
      "localPickupEnabled": false
    },
    "email_config": {
      "fromEmail": "noreply@mystore.com",
      "fromName": "My Store"
    },
    "order_config": {
      "orderPrefix": "MYS",
      "nextOrderNumber": 1001
    }
  }
}
PUT /shop/{storeId}/admin/settings
Update a specific setting.
JSON
{
  "settingKey": "shipping_config",
  "value": {
    "method": "flat_rate",
    "flatRate": 599,
    "freeShippingEnabled": true,
    "freeShippingThreshold": 7500,
    "localPickupEnabled": true,
    "localPickupInstructions": "Pick up at 123 Main St, 9AM-5PM"
  }
}
Setting KeyDescription
tax_configTax rates (default rate + state-specific rates)
shipping_configShipping method, rates, free shipping, local pickup
email_configFrom email address and name for order emails
order_configOrder number prefix and next number
Shipping Methods: flat_rate (single rate), per_item (per product), tiered (by subtotal), free. Free tier stores are limited to flat_rate and free.

Reports

GET /shop/{storeId}/admin/reports
Get sales reports with revenue, order counts, top products, and tax breakdown.

Query Parameters

ParameterTypeDefaultDescription
fromstring2020-01-01Start date (ISO)
tostringnowEnd date (ISO)
statusstringpaid,shipped,deliveredComma-separated order statuses to include

Response

JSON
{
  "period": { "from": "2026-02-01", "to": "2026-02-28" },
  "totalRevenue": 523400,
  "totalOrders": 156,
  "averageOrderValue": 3355,
  "totalTaxCollected": 28450,
  "taxByState": { "SC": 18900, "NC": 6200 },
  "totalShipping": 45200,
  "totalDiscounts": 12300,
  "topProducts": [
    { "productId": "...", "name": "Trucker Hat", "unitsSold": 156, "revenue": 155844 }
  ]
}

Uploads

POST /shop/{storeId}/admin/upload-url
Get a presigned S3 URL for uploading images or digital files. Use the returned fileUrl when creating/updating products or categories.

Request Body

FieldTypeRequiredDescription
fileNamestringrequiredOriginal file name
contentTypestringrequiredMIME type (e.g. image/jpeg, image/png)
uploadTypestringrequiredproduct_image, digital_file, category_image, or storefront_image
fileSizeMBnumberrequiredFile size in megabytes (validated against tier limits)

Upload Types & S3 Paths

uploadTypeS3 PathUse For
product_image{storeId}/products/{file}Product images array
digital_file{storeId}/digital/{file}Downloadable digital products
category_image{storeId}/categories/{file}Category/subcategory card images
storefront_image{storeId}/storefront/{file}Hero images, about page images, logo

Example

JSON
{
  "fileName": "product-photo.jpg",
  "contentType": "image/jpeg",
  "uploadType": "product_image",
  "fileSizeMB": 2.5
}

Response

JSON
{
  "uploadUrl": "https://shoppingcart-assets.s3.amazonaws.com/...?X-Amz-Signature=...",
  "fileUrl": "https://shoppingcart-assets.s3.amazonaws.com/my-store/products/abc.jpg",
  "s3Key": "my-store/products/abc.jpg"
}

Upload your file with a PUT request to uploadUrl with the Content-Type header matching what you specified. Then use fileUrl in your product images array, category image field, etc.

Storefront

GET /shop/{storeId}/admin/storefront
Get the current storefront settings for your store.

Response

JSON
{
  "storefront": {
    "enabled": true,
    "template": "classic",
    "logo": "https://...",
    "showStoreName": true,
    "accentColor": "#418a9e",
    "backgroundColor": "#FFFFFF",
    "textColor": "#333333",
    "heroTitle": "Welcome to My Store",
    "heroLayout": "center",
    "heroImage": "",
    "storeDescription": "Your store description",
    "aboutTitle": "About My Store",
    "aboutContent": "About page content...",
    "aboutImage": "",
    "announcementBar": {
      "enabled": false,
      "text": "",
      "backgroundColor": "#418a9e",
      "textColor": "#FFFFFF"
    },
    "socialLinks": {
      "instagram": "",
      "twitter": "",
      "facebook": "",
      "tiktok": "",
      "youtube": ""
    },
    "showPoweredBy": true
  }
}
PUT /shop/{storeId}/admin/storefront
Update storefront settings. Only include the fields you want to change. Requires an active hosted plan.

Updatable Fields

FieldTypeDescription
templatestringTemplate name: classic, bold, compact
logostringStore logo URL (recommended 240×72px). Use upload endpoint with storefront_image type.
showStoreNamebooleanShow store name text next to logo in nav (default: true)
accentColorstringPrimary accent color hex (e.g. #418a9e)
backgroundColorstringPage background color hex
textColorstringBody text color hex
heroTitlestringHero section heading (defaults to store name)
heroLayoutstringcenter (default), image-left, or image-right
heroImagestringHero image URL (used with image-left/image-right layouts)
storeDescriptionstringHero description text (displayed below title)
aboutTitlestringAbout page heading (defaults to "About {storeName}")
aboutContentstringAbout page body content (line breaks preserved)
aboutImagestringAbout page image URL
announcementBarobject{ enabled, text, backgroundColor, textColor }
socialLinksobject{ instagram, twitter, facebook, tiktok, youtube }
showPoweredBybooleanShow "Powered by Nanocart" in footer
faviconstringFavicon URL

Example

JSON
{
  "heroTitle": "Welcome to My Shop",
  "heroLayout": "image-right",
  "heroImage": "https://...",
  "accentColor": "#e74c3c",
  "aboutTitle": "Our Story"
}

Tier & Usage

GET /shop/{storeId}/admin/tier
Get current tier info, limits, and usage.
JSON
{
  "tier": "standard",
  "limits": {
    "maxProducts": 25,
    "maxMonthlyOrders": 500,
    "maxCoupons": 5,
    "maxUploadMB": 25,
    "allowedShippingMethods": ["flat_rate", "per_item", "tiered", "free"],
    "localPickup": true
  },
  "usage": {
    "activeProducts": 12,
    "activeCoupons": 2,
    "monthlyOrders": 47
  }
}

Subscriptions

POST /shop/admin/stores/{storeId}/subscribe
Create a Stripe subscription checkout session to upgrade your plan.
JSON
{
  "tier": "pro",
  "billingPeriod": "monthly"
}
FieldTypeOptions
tierstringstandard, pro, expert
billingPeriodstringmonthly, annual

Response

JSON
{
  "sessionUrl": "https://checkout.stripe.com/c/pay/..."
}
GET /shop/admin/stores/{storeId}/subscription
Get current subscription details.
JSON
{
  "tier": "pro",
  "subscriptionId": "sub_...",
  "subscriptionStatus": "active",
  "billingPeriod": "monthly",
  "cancelAtPeriodEnd": false
}
POST /shop/admin/stores/{storeId}/cancel-subscription
Cancel subscription at end of billing period. Store keeps current tier until then.
JSON
{
  "message": "Subscription will cancel at end of billing period."
}

Error Codes

Error responses include an error message and an optional code for programmatic handling:

JSON
{
  "error": "Free plan allows 5 active products. Upgrade to Standard for 25.",
  "code": "TIER_PRODUCT_LIMIT",
  "tierLimit": true
}
CodeHTTPDescription
INVALID_API_KEY401API key doesn't exist or is invalid
STORE_SUSPENDED403Store has been suspended
INVALID_INPUT400Missing or malformed request data
STRIPE_NOT_CONFIGURED400Store has no Stripe keys set up
STRIPE_INVALID_KEYS400Stripe key format is wrong
STRIPE_AUTH_ERROR400Stripe rejected the keys
DOMAIN_NOT_ALLOWED403Origin domain not in allowedDomains
TIER_PRODUCT_LIMIT403Exceeded active product limit for tier
TIER_ORDER_LIMIT403Exceeded monthly order limit for tier
TIER_COUPON_LIMIT403Exceeded coupon limit for tier
TIER_UPLOAD_LIMIT403File size exceeds tier upload limit
TIER_SHIPPING_RESTRICTED403Shipping method not available on tier
DUPLICATE_COUPON409Coupon code already exists
Tier limit errors include "tierLimit": true so your app can detect upgrade prompts. The error message includes the current limit and the next tier's limit.

© 2026 nanocart. All rights reserved.  |  Admin Panel  |  hello@nanocart.io

Last updated: February 2026