# Swiggy Instamart API for agents

> API for Agents · https://apiforagents.dev/platforms/instamart · HTML twin: https://apiforagents.dev/platforms/instamart

A product's price and stock at one dark store, right now, from Swiggy Instamart.

Endpoint: `POST https://apiforagents.dev/v1/instamart`. One op per call. Quote first with `"estimateOnly": true`.

## Prices (USD per record, pay as you go)

| Record | Per record |
|---|---|
| category | $0.0009 |
| products | $0.0009 |
| search | $0.0009 |

## Operations

### products

Full product detail at one store. Price, MRP, discount, stock count, rating, seller, manufacturer, specifications. By product URL.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | Product URLs at that store. |
| store | yes | object |  |
| store.storeId | no | string | The dark store's own id, when a previous answer or a store URL gave you one. The most exact way to name a store; wins over the others. |
| store.city | no | string | The city the pincode is in ("Agra"). Helps the pincode resolve to the right store; ignored when storeId or lat/lon are given. |
| store.pincode | no | string | A 6-digit Indian postal code ("282003"); the nearest serving store is used. Give city too when the pincode is ambiguous. |
| store.lat | no | number | Latitude in decimal degrees, with lon: the store serving that point. |
| store.lon | no | number | Longitude in decimal degrees; only read together with lat. |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| productId | string |
| variantId | string |
| storeScope | string |
| storeId | string |
| vendorProductId | string |
| productName | string |
| brand | string |
| price | number |
| mrp | number |
| discountPct | number |
| packSize | string |
| inStock | boolean |
| stockCount | integer |
| rating | number |
| ratingCount | integer |
| category | string |
| rank | integer |
| sponsored | boolean |
| images | list of string |
| productUrl | string |
| description | string |
| countryOfOrigin | string |
| manufacturer | string |
| seller | string |
| specifications | any |
| latitude | number |
| longitude | number |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/instamart \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"products","subjects":["https://www.swiggy.com/instamart/item/<item-id>"],"store":{"city":"Delhi","pincode":"110001"}}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "productName": "Bananas, Robusta",
    "brand": "Fresh",
    "price": 42,
    "mrp": 55,
    "discountPct": 24,
    "packSize": "6 pcs",
    "inStock": true,
    "category": "Fruits",
    "rank": 1,
    "rating": 4.3,
    "ratingCount": 1200,
    "productId": "3188413045",
    "variantId": "3193636747",
    "storeId": "3779976944",
    "vendorProductId": "3920638163",
    "images": [
      "https://img.swiggy.com/bananas-robusta.jpg"
    ],
    "productUrl": "https://www.swiggy.com/instamart/bananas-robusta-1000",
    "details": {}
  },
  {
    "productName": "Eggs, Brown",
    "brand": "Farmnest",
    "price": 96,
    "mrp": 110,
    "discountPct": 13,
    "packSize": "6 pcs",
    "inStock": true,
    "category": "Eggs & Meat",
    "rank": 2,
    "rating": 4.3,
    "ratingCount": 1200,
    "productId": "3220125645",
    "variantId": "741222204",
    "storeId": "26123741",
    "vendorProductId": "2960127665",
    "images": [
      "https://img.swiggy.com/eggs-brown.jpg"
    ],
    "productUrl": "https://www.swiggy.com/instamart/eggs-brown-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=instamart&op=products (sign in first).

### search

Search the app as a shopper at that store would. Listings with price, MRP, stock and rank.

| Field | Required | Type | Meaning |
|---|---|---|---|
| query | yes | string (≤300 chars) |  |
| store | yes | object |  |
| store.storeId | no | string | The dark store's own id, when a previous answer or a store URL gave you one. The most exact way to name a store; wins over the others. |
| store.city | no | string | The city the pincode is in ("Agra"). Helps the pincode resolve to the right store; ignored when storeId or lat/lon are given. |
| store.pincode | no | string | A 6-digit Indian postal code ("282003"); the nearest serving store is used. Give city too when the pincode is ambiguous. |
| store.lat | no | number | Latitude in decimal degrees, with lon: the store serving that point. |
| store.lon | no | number | Longitude in decimal degrees; only read together with lat. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| productId | string |
| variantId | string |
| storeScope | string |
| storeId | string |
| vendorProductId | string |
| productName | string |
| brand | string |
| price | number |
| mrp | number |
| discountPct | number |
| packSize | string |
| inStock | boolean |
| stockCount | integer |
| rating | number |
| ratingCount | integer |
| category | string |
| rank | integer |
| sponsored | boolean |
| images | list of string |
| productUrl | string |
| description | string |
| countryOfOrigin | string |
| manufacturer | string |
| seller | string |
| specifications | any |
| latitude | number |
| longitude | number |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/instamart \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"search","query":"Maggi noodles","store":{"city":"Bengaluru","pincode":"560001"},"limit":20}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "productName": "Instant Noodles, Masala",
    "brand": "Noodo",
    "price": 14,
    "mrp": 15,
    "discountPct": 7,
    "packSize": "70 g",
    "inStock": true,
    "category": "Instant Food",
    "rank": 1,
    "rating": 4.3,
    "ratingCount": 1200,
    "productId": "2927721665",
    "variantId": "1659626997",
    "storeId": "2249531317",
    "vendorProductId": "3505215323",
    "images": [
      "https://img.swiggy.com/instant-noodles-masala.jpg"
    ],
    "productUrl": "https://www.swiggy.com/instamart/instant-noodles-masala-1000",
    "details": {}
  },
  {
    "productName": "Hakka Noodles",
    "brand": "Wokit",
    "price": 55,
    "mrp": 60,
    "discountPct": 8,
    "packSize": "150 g",
    "inStock": true,
    "category": "Instant Food",
    "rank": 2,
    "rating": 4.3,
    "ratingCount": 1200,
    "productId": "1063549028",
    "variantId": "446777371",
    "storeId": "3334597586",
    "vendorProductId": "305940609",
    "images": [
      "https://img.swiggy.com/hakka-noodles.jpg"
    ],
    "productUrl": "https://www.swiggy.com/instamart/hakka-noodles-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=instamart&op=search (sign in first).

### category

One category page at one store. Names must be the app's own menu names; a name that is not on the menu is refused and nothing is charged.

| Field | Required | Type | Meaning |
|---|---|---|---|
| category | yes | string (≤80 chars) | The top-level aisle as the app names it ("Dairy, Bread & Eggs"). |
| subCategory | yes | string (≤80 chars) | The shelf inside it, again as the app names it ("Milk"). Both are required: the listing is one shelf at one store. |
| store | yes | object |  |
| store.storeId | no | string | The dark store's own id, when a previous answer or a store URL gave you one. The most exact way to name a store; wins over the others. |
| store.city | no | string | The city the pincode is in ("Agra"). Helps the pincode resolve to the right store; ignored when storeId or lat/lon are given. |
| store.pincode | no | string | A 6-digit Indian postal code ("282003"); the nearest serving store is used. Give city too when the pincode is ambiguous. |
| store.lat | no | number | Latitude in decimal degrees, with lon: the store serving that point. |
| store.lon | no | number | Longitude in decimal degrees; only read together with lat. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| productId | string |
| variantId | string |
| storeScope | string |
| storeId | string |
| vendorProductId | string |
| productName | string |
| brand | string |
| price | number |
| mrp | number |
| discountPct | number |
| packSize | string |
| inStock | boolean |
| stockCount | integer |
| rating | number |
| ratingCount | integer |
| category | string |
| rank | integer |
| sponsored | boolean |
| images | list of string |
| productUrl | string |
| description | string |
| countryOfOrigin | string |
| manufacturer | string |
| seller | string |
| specifications | any |
| latitude | number |
| longitude | number |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/instamart \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"category","category":"Atta, Rice and Dal","subCategory":"Atta","store":{"city":"Delhi","pincode":"110001"},"limit":50}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "productName": "Orange Juice, No Added Sugar",
    "brand": "Squeezy",
    "price": 120,
    "mrp": 135,
    "discountPct": 11,
    "packSize": "1 L",
    "inStock": true,
    "category": "Beverages",
    "rank": 1,
    "rating": 4.3,
    "ratingCount": 1200,
    "productId": "2876090726",
    "variantId": "4056194219",
    "storeId": "3566173443",
    "vendorProductId": "3732201011",
    "images": [
      "https://img.swiggy.com/orange-juice-no-added-sugar.jpg"
    ],
    "productUrl": "https://www.swiggy.com/instamart/orange-juice-no-added-sugar-1000",
    "details": {}
  },
  {
    "productName": "Coconut Water",
    "brand": "Tenderco",
    "price": 60,
    "mrp": 65,
    "discountPct": 8,
    "packSize": "200 ml",
    "inStock": true,
    "category": "Beverages",
    "rank": 2,
    "rating": 4.3,
    "ratingCount": 1200,
    "productId": "1437839382",
    "variantId": "1897365453",
    "storeId": "3109076870",
    "vendorProductId": "4292472465",
    "images": [
      "https://img.swiggy.com/coconut-water.jpg"
    ],
    "productUrl": "https://www.swiggy.com/instamart/coconut-water-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=instamart&op=category (sign in first).

### history (free)

The stored price/stock series of products already held at a store. Free.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) |  |
| store | yes | object |  |
| store.storeId | no | string | The dark store's own id, when a previous answer or a store URL gave you one. The most exact way to name a store; wins over the others. |
| store.city | no | string | The city the pincode is in ("Agra"). Helps the pincode resolve to the right store; ignored when storeId or lat/lon are given. |
| store.pincode | no | string | A 6-digit Indian postal code ("282003"); the nearest serving store is used. Give city too when the pincode is ambiguous. |
| store.lat | no | number | Latitude in decimal degrees, with lon: the store serving that point. |
| store.lon | no | number | Longitude in decimal degrees; only read together with lat. |
| metric | no | enum |  Values: price, mrp, discount_pct, stock_count, rating, rating_count. |
| days | no | integer (1-730) |  |

Request shape:

```json
{
  "op": "history",
  "subjects": [
    "example"
  ],
  "store": {
    "pincode": "560001"
  }
}
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=instamart&op=history (sign in first).

## Notes for the agent

Measured Swiggy Instamart data, one operation per call. A product's price and stock at ONE dark store, right now. Every op takes `store`: a storeId, or a pincode (with city), or lat/lon. Prices, MRP, discounts and stock are per store and every fetch adds a point to that product's price history at that store. ops: products (full detail for up to ten swiggy.com/instamart product URLs at the store. Price, MRP, discount, stock count, rating, seller, manufacturer, specifications), search (what a shopper at that store sees for a query. Listings with price, stock and rank), category (one page of the app's own menu at that store; names must match the app exactly, e.g. category "Atta, Rice and Dal", subCategory "Atta". The pair must belong together), history (stored price/stock series for products already held, free). Ops are independent. Issue several as PARALLEL tool calls. Fresh fetches are charged per record; your own answer is free while fresh.
