Subversion Repositories SmartDukaan

Rev

Rev 37296 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
37150 amit 1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
<meta charset="utf-8">
5
<meta name="viewport" content="width=device-width, initial-scale=1">
6
<title>SmartDukaan External API — Partner Documentation</title>
7
<style>
8
  body { font-family: -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 0; color: #1f2933; line-height: 1.55; }
9
  .wrap { max-width: 960px; margin: 0 auto; padding: 24px 20px 80px; }
10
  h1 { font-size: 1.7em; border-bottom: 2px solid #e4e7eb; padding-bottom: 10px; }
11
  h2 { font-size: 1.25em; margin-top: 2em; border-bottom: 1px solid #e4e7eb; padding-bottom: 6px; }
12
  h3 { font-size: 1.05em; margin-top: 1.6em; }
13
  code, pre { font-family: SFMono-Regular, Consolas, Menlo, monospace; font-size: 0.9em; background: #f5f7fa; border-radius: 4px; }
14
  code { padding: 1px 5px; }
15
  pre { padding: 12px 14px; overflow-x: auto; border: 1px solid #e4e7eb; }
16
  table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 0.93em; }
17
  th, td { border: 1px solid #d3dae1; padding: 7px 10px; text-align: left; vertical-align: top; }
18
  th { background: #f5f7fa; }
19
  .method { display: inline-block; background: #0b7a3e; color: #fff; border-radius: 4px; padding: 1px 8px; font-size: 0.8em; font-weight: 600; margin-right: 8px; }
20
  .note { background: #fff8e1; border: 1px solid #f0d580; border-radius: 4px; padding: 10px 14px; }
21
</style>
22
</head>
23
<body>
24
<div class="wrap">
25
 
26
<h1>SmartDukaan External API <small>v1</small></h1>
27
<p>Read-only APIs giving approved partners visibility into store-level stock, proposed selling prices
28
and catalog master data of SmartDukaan partner stores.</p>
29
 
30
<h2>Basics</h2>
31
<table>
32
  <tr><th>Base URL</th><td><code>https://apis.smartdukaan.com/external/v1</code></td></tr>
33
  <tr><th>Authentication</th><td>Header <code>X-Api-Key: &lt;your key&gt;</code> on every request. Keys are issued per partner by SmartDukaan.</td></tr>
34
  <tr><th>Format</th><td>All endpoints are <code>GET</code> and return JSON.</td></tr>
35
  <tr><th>Timestamps</th><td>All times are Unix epoch <strong>milliseconds</strong> (IST server clock).</td></tr>
36
</table>
37
 
38
<h3>Response envelope</h3>
39
<p>Every response is wrapped in a standard envelope; the payload is under <code>response</code>:</p>
40
<pre>{
41
  "statusCode": "200 OK",
42
  "statusMessage": "OK",
43
  "responseStatus": "SUCCESS",
44
  "response": { ... }
45
}</pre>
46
 
47
<h3>Errors</h3>
48
<table>
49
  <tr><th>HTTP</th><th>Code</th><th>Meaning</th></tr>
50
  <tr><td>401</td><td><code>EXT_401</code></td><td>Missing, invalid or inactive <code>X-Api-Key</code>.</td></tr>
51
  <tr><td>403</td><td><code>EXT_403</code></td><td><code>storeId</code> is not mapped to your account.</td></tr>
52
  <tr><td>400</td><td><code>EXT_400</code></td><td>Bad or over-sized id list parameter.</td></tr>
53
</table>
54
 
55
<h2>Data model</h2>
37219 amit 56
<pre>categoryId = a product category exposed to you        → listed in categoryMaster
57
catalogId  = a product model (e.g. "Galaxy A15")     → content in catalogMaster
37296 amit 58
itemId     = a sellable SKU (variant of a catalog)     → listed in catalogSkuMaster
37150 amit 59
storeId    = a physical partner store mapped to you   → listed in storeMaster
60
stock      = (storeId, itemId) → availability          → skuMaster / stock</pre>
61
<p>Prices per SKU: <code>mop</code> is the proposed selling price; <code>mrp</code> is the maximum retail
62
price (strike-through display). A SKU with <code>active: false</code> is delisted and should not be sold.</p>
37856 amit 63
<p><code>brandIdentifier</code> is the brand's own article/SKU code and is maintained <strong>per itemId</strong>
64
(one colour variant of a catalog), not per catalog. It is returned on every SKU-level row —
65
<code>/catalogSkuMaster</code>, <code>/catalogSkus</code>, <code>/skuMaster</code> and <code>/stock</code> — and is
66
<code>null</code> where it has not yet been maintained. Always key SKUs by <code>itemId</code>.</p>
37219 amit 67
<div class="note">
68
  <strong>Category scoping:</strong> your account is mapped to specific categories (see
69
  <code>/categoryMaster</code>). Every feed and lookup only ever returns catalogs, SKUs and stock within
70
  those categories. <code>title</code> is present and non-empty on catalog, SKU and stock records — the
71
  same derived product title everywhere.
72
</div>
37150 amit 73
 
37291 amit 74
<h2>Parameters at a glance</h2>
75
<table>
76
  <tr><th>Endpoint</th><th>Required</th><th>Optional (default)</th></tr>
77
  <tr><td><code>/categoryMaster</code></td><td>—</td><td>—</td></tr>
78
  <tr><td><code>/catalogMaster</code></td><td>—</td><td><code>offset</code> (0), <code>limit</code> (100, max 100), <code>updatedSince</code></td></tr>
79
  <tr><td><code>/catalogSkuMaster</code></td><td>—</td><td><code>offset</code> (0), <code>limit</code> (100, max 500), <code>updatedSince</code></td></tr>
80
  <tr><td><code>/skuMaster</code></td><td>—</td><td><code>offset</code> (0), <code>limit</code> (100, max 500), <code>updatedSince</code>, <code>storeId</code></td></tr>
81
  <tr><td><code>/storeMaster</code></td><td>—</td><td><code>offset</code> (0), <code>limit</code> (100, max 500)</td></tr>
82
  <tr><td><code>/stock</code></td><td><code>storeId</code></td><td><code>itemIds</code> (≤100 ids); without it: <code>offset</code> (0), <code>limit</code> (100, max 500)</td></tr>
83
  <tr><td><code>/catalogs</code></td><td><code>catalogIds</code> (≤50 ids)</td><td>—</td></tr>
84
  <tr><td><code>/catalogSkus</code></td><td><code>catalogIds</code> (≤50 ids)</td><td>—</td></tr>
85
</table>
86
<p>Every optional parameter can simply be omitted. <code>updatedSince</code> is epoch
87
<strong>milliseconds</strong>; omit it for a full sync. <code>limit</code> above its maximum is
88
silently clamped; <code>limit</code> ≤ 0 falls back to the default.</p>
89
 
37150 amit 90
<h2>Master feeds (paginated sync)</h2>
37219 amit 91
 
92
<h3><span class="method">GET</span>/categoryMaster</h3>
93
<p>The categories your key may access, each with its spec schema (the keys you will find in
37291 amit 94
<code>categorySpecs</code> on catalog content). Full list, no pagination, no parameters.</p>
37219 amit 95
<pre>GET /external/v1/categoryMaster
96
→ [ { "categoryId": 10006, "label": "Mobile", "displayName": "Mobile Phones",
97
      "specs": [ { "key": "ram", "label": "RAM", "position": 1 },
98
                 { "key": "memory", "label": "Internal Storage", "position": 2 } ] } ]</pre>
37291 amit 99
<p>All other feeds accept optional <code>offset</code>, <code>limit</code> and
100
<code>updatedSince</code> (see table above) and return:</p>
37150 amit 101
<pre>{
102
  "serverTime": 1753600000000,   // pass back as next updatedSince
103
  "offset": 0, "limit": 100,
104
  "totalCount": 5321,
105
  "records": [ ... ]
106
}</pre>
107
 
108
<h3><span class="method">GET</span>/catalogMaster</h3>
37219 amit 109
<p>Full catalog content documents of your categories. <code>limit</code> max 100 (documents are large).
110
<code>content.title</code> is always non-empty; <code>content.categorySpecs</code> holds the
111
category-governed key specs (see <code>/categoryMaster</code> for the schema).</p>
37150 amit 112
<pre>GET /external/v1/catalogMaster?offset=0&amp;limit=100
113
→ records: [ { "catalogId": 12345, "lastModified": 1753500000000,
37219 amit 114
               "content": { "title": "Samsung Galaxy A15 SM-A155F", "categoryId": 10006,
115
                            "categorySpecs": [ { "key": "ram", "label": "RAM", "value": "8GB" },
116
                                               { "key": "memory", "label": "Internal Storage", "value": "256GB" } ],
117
                            "name": "...", "keySpecs": [...], "detailedSpecs": [...],
37150 amit 118
                            "images": [...], "defaultImageUrl": "...", ... } } ]</pre>
119
 
120
<h3><span class="method">GET</span>/catalogSkuMaster</h3>
37219 amit 121
<p>Catalog → SKU map with prices. <code>limit</code> max 500. <code>brandIdentifier</code> is the
37280 amit 122
brand's own article/SKU code where known (else <code>null</code>). <code>addedOn</code> (epoch ms) is
123
when the SKU was first added to our catalog — filter client-side on <code>addedOn &gt; X</code> to pick up
124
only newly introduced SKUs, as opposed to <code>updatedSince</code> which also returns price/stock/listing
125
updates of existing SKUs.</p>
37150 amit 126
<pre>GET /external/v1/catalogSkuMaster?offset=0&amp;limit=500
37219 amit 127
→ records: [ { "catalogId": 12345, "itemId": 101, "title": "Samsung Galaxy A15 SM-A155F",
128
               "brand": "Samsung", "modelName": "Galaxy A15", "modelNumber": "SM-A155F",
37296 amit 129
               "brandIdentifier": "SM-A155FZKW",
37280 amit 130
               "mop": 14999.0, "mrp": 17999.0, "active": true,
131
               "updatedAt": 1753500000000, "addedOn": 1750000000000 } ]</pre>
37150 amit 132
 
133
<h3><span class="method">GET</span>/skuMaster</h3>
37856 amit 134
<p>Per-store stock + price rows for <em>your mapped stores</em>, with full item identity on every row
135
(including the per-itemId <code>brandIdentifier</code>).
37291 amit 136
<code>limit</code> max 500. Optional <code>storeId</code> narrows to one store (must be mapped to you;
137
an unmapped id → 403 <code>EXT_403</code>). Omitting <code>storeId</code> returns rows across all your
138
mapped stores.</p>
37150 amit 139
<pre>GET /external/v1/skuMaster?offset=0&amp;limit=500
37219 amit 140
→ records: [ { "storeId": 2116665, "itemId": 101, "title": "Samsung Galaxy A15 SM-A155F",
141
               "brand": "Samsung", "modelName": "Galaxy A15", "modelNumber": "SM-A155F",
37296 amit 142
               "brandIdentifier": "SM-A155FZKW", "availability": 7,
37150 amit 143
               "mop": 14999.0, "mrp": 17999.0, "active": true, "updatedAt": 1753500000000 } ]</pre>
144
 
145
<h3><span class="method">GET</span>/storeMaster</h3>
37224 amit 146
<p>Your mapped stores with location and GST details, in the standard paginated envelope
147
(<code>limit</code> max 500; no <code>updatedSince</code> — store data has no delta feed, sync it fully).</p>
148
<pre>GET /external/v1/storeMaster?offset=0&amp;limit=100
149
→ records: [ { "storeId": 2116665, "code": "NSPRJ39290", "name": "XYZ Mobiles",
150
               "addressLine1": "...", "addressLine2": "...", "city": "Jaipur",
151
               "state": "Rajasthan", "pincode": "302001", "latitude": "26.91", "longitude": "75.78",
152
               "gstNumber": "08ABCDE1234F1Z5" } ]</pre>
37150 amit 153
 
154
<h2>Incremental sync (updatedSince)</h2>
155
<ol>
156
  <li>First sync: call each feed <strong>without</strong> <code>updatedSince</code> and page through with
157
      <code>offset</code>/<code>limit</code>. Full feeds contain active records only.</li>
158
  <li>Save the <code>serverTime</code> returned by the first page.</li>
159
  <li>Next sync: pass that value as <code>updatedSince</code>. You receive only records whose stock,
160
      price, listing or content changed since then — <strong>including delisted records with
161
      <code>active: false</code></strong>, which you should remove/hide on your side.</li>
162
  <li>Each delta response again carries a fresh <code>serverTime</code>; use it for the next cycle.</li>
163
</ol>
164
<div class="note">
165
  Records deleted outright from our systems do not appear in deltas. Run a <strong>weekly full sync</strong>
166
  (no <code>updatedSince</code>) to reconcile. Receiving the same record twice is normal — treat every
167
  record as an upsert keyed by <code>(storeId, itemId)</code> / <code>itemId</code> / <code>catalogId</code>.
168
</div>
169
 
170
<h2>Real-time lookups</h2>
171
 
172
<h3><span class="method">GET</span>/stock</h3>
37291 amit 173
<p>Live stock + price in one mapped store, with item identity on every row. <code>storeId</code> is
174
required; <code>itemIds</code> is optional and selects the mode:</p>
37219 amit 175
<ul>
176
  <li><strong>By ids</strong> — pass <code>itemIds</code> (up to 100). Every requested <code>itemId</code> is
177
      returned; no stock row means <code>availability: 0</code>, no active listing means
178
      <code>mop/mrp: null</code>. Ids outside your categories come back as id-only rows with
37291 amit 179
      <code>availability: 0</code>. <code>offset</code>/<code>limit</code> are ignored in this mode.</li>
37219 amit 180
  <li><strong>Full store</strong> — omit <code>itemIds</code> to page through the store's entire stock with
37291 amit 181
      optional <code>offset</code> (default 0) / <code>limit</code> (default 100, max 500); the response is
182
      the standard paginated envelope (<code>serverTime</code>/<code>totalCount</code>/<code>records</code>).
183
      One loop replaces batching ids across many calls.</li>
37219 amit 184
</ul>
185
<pre>GET /external/v1/stock?storeId=2116665&amp;itemIds=101,102
186
→ [ { "storeId": 2116665, "itemId": 101, "title": "Samsung Galaxy A15 SM-A155F",
37296 amit 187
      "brand": "Samsung", "modelName": "Galaxy A15", "modelNumber": "SM-A155F",
37219 amit 188
      "brandIdentifier": "SM-A155FZKW", "availability": 7, "mop": 14999.0, "mrp": 17999.0, "active": true },
189
    { "storeId": 2116665, "itemId": 102, "title": null, "availability": 0, "mop": null, "mrp": null, "active": false } ]
37150 amit 190
 
37219 amit 191
GET /external/v1/stock?storeId=2116665&amp;offset=0&amp;limit=500
192
→ { "serverTime": ..., "offset": 0, "limit": 500, "totalCount": 812, "records": [ ...same row shape... ] }</pre>
193
 
37150 amit 194
<h3><span class="method">GET</span>/catalogs</h3>
195
<p>Catalog content for up to 50 catalogIds. Response is an object keyed by catalogId; ids without a
196
document are omitted.</p>
197
<pre>GET /external/v1/catalogs?catalogIds=12345,12346</pre>
198
 
199
<h3><span class="method">GET</span>/catalogSkus</h3>
200
<p>Active-listed SKUs (with prices) of up to 50 catalogIds, as flat rows.</p>
201
<pre>GET /external/v1/catalogSkus?catalogIds=12345,12346</pre>
202
 
203
<h2>Quick start</h2>
204
<pre>curl -H 'X-Api-Key: YOUR_KEY' 'https://apis.smartdukaan.com/external/v1/storeMaster'
205
curl -H 'X-Api-Key: YOUR_KEY' 'https://apis.smartdukaan.com/external/v1/skuMaster?limit=500'
206
curl -H 'X-Api-Key: YOUR_KEY' 'https://apis.smartdukaan.com/external/v1/stock?storeId=STORE&amp;itemIds=101,102'</pre>
207
 
208
<h2>Fair use</h2>
209
<ul>
210
  <li>Sync feeds at most every 15 minutes; use <code>/stock</code> for point-in-time checks.</li>
211
  <li>Keep your API key secret; it identifies your organisation. Contact SmartDukaan to rotate or revoke.</li>
212
</ul>
213
 
214
</div>
215
</body>
216
</html>