Rev 37219 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>SmartDukaan External API — Partner Documentation</title><style>body { font-family: -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 0; color: #1f2933; line-height: 1.55; }.wrap { max-width: 960px; margin: 0 auto; padding: 24px 20px 80px; }h1 { font-size: 1.7em; border-bottom: 2px solid #e4e7eb; padding-bottom: 10px; }h2 { font-size: 1.25em; margin-top: 2em; border-bottom: 1px solid #e4e7eb; padding-bottom: 6px; }h3 { font-size: 1.05em; margin-top: 1.6em; }code, pre { font-family: SFMono-Regular, Consolas, Menlo, monospace; font-size: 0.9em; background: #f5f7fa; border-radius: 4px; }code { padding: 1px 5px; }pre { padding: 12px 14px; overflow-x: auto; border: 1px solid #e4e7eb; }table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 0.93em; }th, td { border: 1px solid #d3dae1; padding: 7px 10px; text-align: left; vertical-align: top; }th { background: #f5f7fa; }.method { display: inline-block; background: #0b7a3e; color: #fff; border-radius: 4px; padding: 1px 8px; font-size: 0.8em; font-weight: 600; margin-right: 8px; }.note { background: #fff8e1; border: 1px solid #f0d580; border-radius: 4px; padding: 10px 14px; }</style></head><body><div class="wrap"><h1>SmartDukaan External API <small>v1</small></h1><p>Read-only APIs giving approved partners visibility into store-level stock, proposed selling pricesand catalog master data of SmartDukaan partner stores.</p><h2>Basics</h2><table><tr><th>Base URL</th><td><code>https://apis.smartdukaan.com/external/v1</code></td></tr><tr><th>Authentication</th><td>Header <code>X-Api-Key: <your key></code> on every request. Keys are issued per partner by SmartDukaan.</td></tr><tr><th>Format</th><td>All endpoints are <code>GET</code> and return JSON.</td></tr><tr><th>Timestamps</th><td>All times are Unix epoch <strong>milliseconds</strong> (IST server clock).</td></tr></table><h3>Response envelope</h3><p>Every response is wrapped in a standard envelope; the payload is under <code>response</code>:</p><pre>{"statusCode": "200 OK","statusMessage": "OK","responseStatus": "SUCCESS","response": { ... }}</pre><h3>Errors</h3><table><tr><th>HTTP</th><th>Code</th><th>Meaning</th></tr><tr><td>401</td><td><code>EXT_401</code></td><td>Missing, invalid or inactive <code>X-Api-Key</code>.</td></tr><tr><td>403</td><td><code>EXT_403</code></td><td><code>storeId</code> is not mapped to your account.</td></tr><tr><td>400</td><td><code>EXT_400</code></td><td>Bad or over-sized id list parameter.</td></tr></table><h2>Data model</h2><pre>categoryId = a product category exposed to you → listed in categoryMastercatalogId = a product model (e.g. "Galaxy A15") → content in catalogMasteritemId = a sellable SKU, one per color → listed in catalogSkuMasterstoreId = a physical partner store mapped to you → listed in storeMasterstock = (storeId, itemId) → availability → skuMaster / stock</pre><p>Prices per SKU: <code>mop</code> is the proposed selling price; <code>mrp</code> is the maximum retailprice (strike-through display). A SKU with <code>active: false</code> is delisted and should not be sold.</p><div class="note"><strong>Category scoping:</strong> your account is mapped to specific categories (see<code>/categoryMaster</code>). Every feed and lookup only ever returns catalogs, SKUs and stock withinthose categories. <code>title</code> is present and non-empty on catalog, SKU and stock records — thesame derived product title everywhere.</div><h2>Master feeds (paginated sync)</h2><h3><span class="method">GET</span>/categoryMaster</h3><p>The categories your key may access, each with its spec schema (the keys you will find in<code>categorySpecs</code> on catalog content). Full list, no pagination.</p><pre>GET /external/v1/categoryMaster→ [ { "categoryId": 10006, "label": "Mobile", "displayName": "Mobile Phones","specs": [ { "key": "ram", "label": "RAM", "position": 1 },{ "key": "memory", "label": "Internal Storage", "position": 2 } ] } ]</pre><p>All feeds accept <code>offset</code> (default 0), <code>limit</code>, and optional<code>updatedSince</code> (epoch ms) and return:</p><pre>{"serverTime": 1753600000000, // pass back as next updatedSince"offset": 0, "limit": 100,"totalCount": 5321,"records": [ ... ]}</pre><h3><span class="method">GET</span>/catalogMaster</h3><p>Full catalog content documents of your categories. <code>limit</code> max 100 (documents are large).<code>content.title</code> is always non-empty; <code>content.categorySpecs</code> holds thecategory-governed key specs (see <code>/categoryMaster</code> for the schema).</p><pre>GET /external/v1/catalogMaster?offset=0&limit=100→ records: [ { "catalogId": 12345, "lastModified": 1753500000000,"content": { "title": "Samsung Galaxy A15 SM-A155F", "categoryId": 10006,"categorySpecs": [ { "key": "ram", "label": "RAM", "value": "8GB" },{ "key": "memory", "label": "Internal Storage", "value": "256GB" } ],"name": "...", "keySpecs": [...], "detailedSpecs": [...],"images": [...], "defaultImageUrl": "...", ... } } ]</pre><h3><span class="method">GET</span>/catalogSkuMaster</h3><p>Catalog → SKU map with prices. <code>limit</code> max 500. <code>brandIdentifier</code> is thebrand's own article/SKU code where known (else <code>null</code>).</p><pre>GET /external/v1/catalogSkuMaster?offset=0&limit=500→ records: [ { "catalogId": 12345, "itemId": 101, "title": "Samsung Galaxy A15 SM-A155F","brand": "Samsung", "modelName": "Galaxy A15", "modelNumber": "SM-A155F","color": "Blue", "brandIdentifier": "SM-A155FZKW","mop": 14999.0, "mrp": 17999.0, "active": true, "updatedAt": 1753500000000 } ]</pre><h3><span class="method">GET</span>/skuMaster</h3><p>Per-store stock + price rows for <em>your mapped stores</em>, with full item identity on every row.<code>limit</code> max 500. Optional <code>storeId</code> narrows to one store (must be mapped to you).</p><pre>GET /external/v1/skuMaster?offset=0&limit=500→ records: [ { "storeId": 2116665, "itemId": 101, "title": "Samsung Galaxy A15 SM-A155F","brand": "Samsung", "modelName": "Galaxy A15", "modelNumber": "SM-A155F","color": "Blue", "brandIdentifier": "SM-A155FZKW", "availability": 7,"mop": 14999.0, "mrp": 17999.0, "active": true, "updatedAt": 1753500000000 } ]</pre><h3><span class="method">GET</span>/storeMaster</h3><p>Your mapped stores with location and GST details, in the standard paginated envelope(<code>limit</code> max 500; no <code>updatedSince</code> — store data has no delta feed, sync it fully).</p><pre>GET /external/v1/storeMaster?offset=0&limit=100→ records: [ { "storeId": 2116665, "code": "NSPRJ39290", "name": "XYZ Mobiles","addressLine1": "...", "addressLine2": "...", "city": "Jaipur","state": "Rajasthan", "pincode": "302001", "latitude": "26.91", "longitude": "75.78","gstNumber": "08ABCDE1234F1Z5" } ]</pre><h2>Incremental sync (updatedSince)</h2><ol><li>First sync: call each feed <strong>without</strong> <code>updatedSince</code> and page through with<code>offset</code>/<code>limit</code>. Full feeds contain active records only.</li><li>Save the <code>serverTime</code> returned by the first page.</li><li>Next sync: pass that value as <code>updatedSince</code>. You receive only records whose stock,price, listing or content changed since then — <strong>including delisted records with<code>active: false</code></strong>, which you should remove/hide on your side.</li><li>Each delta response again carries a fresh <code>serverTime</code>; use it for the next cycle.</li></ol><div class="note">Records deleted outright from our systems do not appear in deltas. Run a <strong>weekly full sync</strong>(no <code>updatedSince</code>) to reconcile. Receiving the same record twice is normal — treat everyrecord as an upsert keyed by <code>(storeId, itemId)</code> / <code>itemId</code> / <code>catalogId</code>.</div><h2>Real-time lookups</h2><h3><span class="method">GET</span>/stock</h3><p>Live stock + price in one mapped store, with item identity on every row. Two modes:</p><ul><li><strong>By ids</strong> — pass <code>itemIds</code> (up to 100). Every requested <code>itemId</code> isreturned; no stock row means <code>availability: 0</code>, no active listing means<code>mop/mrp: null</code>. Ids outside your categories come back as id-only rows with<code>availability: 0</code>.</li><li><strong>Full store</strong> — omit <code>itemIds</code> to page through the store's entire stock with<code>offset</code>/<code>limit</code> (max 500); the response is the standard paginated envelope(<code>serverTime</code>/<code>totalCount</code>/<code>records</code>). One loop replaces batching idsacross many calls.</li></ul><pre>GET /external/v1/stock?storeId=2116665&itemIds=101,102→ [ { "storeId": 2116665, "itemId": 101, "title": "Samsung Galaxy A15 SM-A155F","brand": "Samsung", "modelName": "Galaxy A15", "modelNumber": "SM-A155F", "color": "Blue","brandIdentifier": "SM-A155FZKW", "availability": 7, "mop": 14999.0, "mrp": 17999.0, "active": true },{ "storeId": 2116665, "itemId": 102, "title": null, "availability": 0, "mop": null, "mrp": null, "active": false } ]GET /external/v1/stock?storeId=2116665&offset=0&limit=500→ { "serverTime": ..., "offset": 0, "limit": 500, "totalCount": 812, "records": [ ...same row shape... ] }</pre><h3><span class="method">GET</span>/catalogs</h3><p>Catalog content for up to 50 catalogIds. Response is an object keyed by catalogId; ids without adocument are omitted.</p><pre>GET /external/v1/catalogs?catalogIds=12345,12346</pre><h3><span class="method">GET</span>/catalogSkus</h3><p>Active-listed SKUs (with prices) of up to 50 catalogIds, as flat rows.</p><pre>GET /external/v1/catalogSkus?catalogIds=12345,12346</pre><h2>Quick start</h2><pre>curl -H 'X-Api-Key: YOUR_KEY' 'https://apis.smartdukaan.com/external/v1/storeMaster'curl -H 'X-Api-Key: YOUR_KEY' 'https://apis.smartdukaan.com/external/v1/skuMaster?limit=500'curl -H 'X-Api-Key: YOUR_KEY' 'https://apis.smartdukaan.com/external/v1/stock?storeId=STORE&itemIds=101,102'</pre><h2>Fair use</h2><ul><li>Sync feeds at most every 15 minutes; use <code>/stock</code> for point-in-time checks.</li><li>Keep your API key secret; it identifies your organisation. Contact SmartDukaan to rotate or revoke.</li></ul></div></body></html>