How it works
Oyklane is an e-commerce platform for Indian brands. Sellers run their store from the Oyklane admin and add themes and apps from the Oyklane Store. You build them; Oyklane hosts the listing, takes the seller's payment and pays you your share.
- Create a developer account. Sign up with your email. Add your name or company, website and the UPI ID your earnings are paid to.
- Create a listing. Choose theme or app, name it, say what it does, set a price (free, or ₹99 and up) and add screenshots.
- Build and test. Themes: upload a .zip and click through it on our demo store. Apps: point the listing at your app and install it on your own test store.
- Send it for review. We check it works, is honest and asks only for what it needs. If something needs fixing, you get a note.
- Listed on the Oyklane Store. Approved listings show on the Oyklane Store, where sellers find them and install them in one click.
- Get paid. You keep 80% of every theme sale and of every paid app month, paid to your UPI ID.
Environments
- Developer account — sign up here. Your listings, uploads, review notes and earnings live in your dashboard.
- Theme preview — every upload runs on our demo store straight away, on every page with sample products, for you and our reviewers.
- Test store for apps — make your own store at store.oyklane.com and install your app on it from your listing. Test with your own sample data, not a seller's store.
- API —
https://api.oyklane.com/api/v1. The key your app gets works only for the store that installed it.
Themes
Oyklane themes are Liquid, the same shape as Oyklane's own (Classic, Modern, Atelier, Fresh, Lumière). Your theme draws the home page, the header and footer, and the sections sellers place around pages. The platform draws product, collection, search, cart, checkout, account, order, blog and contact pages in your theme's colours and fonts, so checkout and payments work the same in every store.
my-theme/
layout/theme.liquid required — wraps every page
templates/index.json required — the home page's sections
templates/product.json optional — sections around the product page
templates/collection.json, page.json, contact.json optional, the same way
sections/*.liquid each with a {% schema %} for the editor
snippets/*.liquid
assets/*.css, *.js, *.svg
config/settings_schema.json required — theme settings in the editor
config/settings_data.json required — their starting values
locales/*.jsonLayout
<!doctype html>
<html lang="en">
<head>
<title>{{ page_title }}</title>
<link rel="stylesheet" href="{{ 'theme.css' | asset_url }}">
</head>
<body>
{% section 'header' %}
<main>{{ content_for_layout }}</main>
{% section 'footer' %}
</body>
</html>Sections
A section is a Liquid file with a {% schema %} listing its settings (and blocks, for repeatable items). Sellers add, reorder and edit sections in the visual editor; templates/index.json sets which sections the home page starts with.
<section class="rich-text">
<h2>{{ section.settings.heading }}</h2>
<p>{{ section.settings.text }}</p>
<a href="{{ routes.all_products_url }}">Shop all</a>
</section>
{% schema %}
{
"name": "Rich text",
"settings": [
{ "type": "text", "id": "heading", "label": "Heading", "default": "Honest products" },
{ "type": "textarea", "id": "text", "label": "Text" },
{ "type": "select", "id": "align", "label": "Alignment", "default": "center",
"options": [{ "value": "left", "label": "Left" }, { "value": "center", "label": "Centre" }] }
]
}
{% endschema %}Product, collection, page and contact pages
These pages keep the platform's own main section (sys-product, sys-collection, sys-page, sys-contact), and your sections can go around it — add templates/product.json and so on for a starting layout. Cart and checkout can't be changed.
Rules
- Upload a .zip of the folder: up to 6 MB unzipped, 512 KB a file, 600 files. Text files only: .liquid .json .css .js .svg .txt.
- Every Liquid and JSON file is checked on upload; problems are listed file by file.
- Build every link from
routes(e.g.{{ routes.cart_url }}), never a fixed path — stores run on their own domains. - A paid theme's code is locked in the seller's store; they customise it in the editor.
- Versions: upload 1.0.1, 1.1.0… and send each for review. Sellers who bought it can install the new version.
Liquid reference
Objects on every page
shop— name, handle, currency, support_email, support_phone, logoroutes— root_url, all_products_url, collections_url, cart_url, cart_add_url, search_url, account_url, blog_url, contact_url, pages_url…collections(by handle),all_products,best_sellers,blog,linklists(menus)cart,customer(when signed in),page_titlesettings— your theme settings; inside a section,section.settingsandblock.settings
Oyklane filters and tags
{{ product.price | money }}andmoney_without_trailing_zeros— prices in the store's currency{{ 'theme.css' | asset_url }}— a file from your assets/ folderimage_url,placeholder_svg,color_on(black or white text for a background colour){% section 'name' %}— places a section in the layout
Standard Liquid tags and filters work as usual (if, for, assign, capture, date, escape, url_encode…).
Apps
An app is your own web app, on your own server. When a store installs it, Oyklane makes an API key for that store with only the permissions your listing asks for, and sends it to your install webhook. Sellers open your app from their Apps page.
What you set on the listing
- App link (https) — where sellers land when they open your app.
- Install webhook (https) — install and uninstall events are posted here, signed with your app secret.
- Permissions — the API scopes your app needs (below). Ask only for what it uses.
- Storefront script (optional, https) — added to every page of stores that install your app, never checkout or payment pages.
- Support email and privacy policy — needed for review.
Install webhook
POST <your install webhook>
X-Oyklane-Event: app.installed
X-Oyklane-Signature: <hex HMAC-SHA256 of the body>
{
"event": "app.installed",
"store": { "id": "…", "handle": "my-store", "name": "My Store", "url": "https://…" },
"apiBase": "https://api.oyklane.com/api/v1",
"apiKey": "oyk_…", // only the permissions your listing asked for
"scopes": ["read_products", "read_orders"],
"at": "2026-10-08T10:00:00.000Z"
}When it's removed you get app.uninstalled and the key stops working. Keep each store's key safe on your server.
Checking it's really from Oyklane
// Node: check a webhook from Oyklane
import crypto from "crypto";
function fromOyklane(rawBody, signatureHeader, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(String(signatureHeader)));
}Opening your app
https://yourapp.com/oyklane?store=my-store&ts=1791450000&signature=<hex>
// signature = HMAC-SHA256("store=my-store&ts=1791450000", your app secret)
// Refuse links older than 5 minutes.Pricing
Free, or a monthly price (₹99 or more) billed with the seller's Oyklane plan. You get 80% of every month that's paid.
API
Send the key as Authorization: Bearer oyk_…. Lists are paginated with ?page= and ?limit= (up to 100), newest first. Up to 240 requests a minute per key. Errors come back as { "error": "…" } with a 4xx status.
curl "https://api.oyklane.com/api/v1/products?page=1&limit=50" \
-H "Authorization: Bearer oyk_…"
{ "data": [ … ], "page": 1, "limit": 50, "total": 132 }| Method | Path | Scope | Notes |
|---|---|---|---|
| GET | /shop | — | The store's name, handle and currency |
| GET | /products, /products/:id | read_products | Filter with ?q= ?status= ?sku= ?handle= |
| POST, PATCH, DELETE | /products | write_products | Create, edit, delete |
| GET, POST | /categories, /collections | read_products / write_products | |
| GET | /inventory | read_inventory | Stock per variant |
| POST | /inventory/adjust | write_inventory | Add or take away stock |
| GET | /orders, /orders/:id | read_orders | |
| POST | /orders/:id/fulfillments | write_orders | Mark shipped with courier and tracking |
| POST | /orders/import | import_orders | Past orders from another platform |
| GET, POST, PATCH | /customers | read_customers / write_customers | |
| GET, POST | /discounts | read_discounts / write_discounts |
Scopes
read_products— Read products, categories and collectionswrite_products— Create, edit and delete products, categories and collectionsread_inventory— Read stock levelswrite_inventory— Change stock levelsread_orders— Read orderswrite_orders— Ship orders (add tracking)import_orders— Import past orders (no payment, stock or messages)read_customers— Read customerswrite_customers— Create and edit customersread_discounts— Read discountswrite_discounts— Create discounts
Review
- It works on phones and desktops, and every page loads.
- No tracking or scripts the listing doesn't mention; nothing that asks shoppers for payment details.
- An honest description and screenshots — no claims you can't back up.
- For apps: permissions only for what the app does; a support email and a privacy policy.
Questions? partners@oyklane.com