Building a Delivery ETA Dashboard: Compare Quick Commerce Speed
Build a dashboard that compares delivery times across 7 quick commerce platforms in real-time.
In the quick commerce wars, delivery speed is everything. When a customer is choosing between BlinkIt, Zepto, and Swiggy Instamart, the promise of "10-minute delivery" can make or break a sale. But how fast do these platforms actually deliver? And does it vary by location, time of day, or day of the week? In this tutorial, we will build a real-time delivery ETA dashboard that answers these questions by pulling live ETA data from all 7 quick commerce platforms using the QuickCommerce API.
Whether you are a consumer app helping users find the fastest delivery, a business analyst tracking competitor logistics, or just a curious developer, this dashboard gives you a single view of delivery speeds across the entire quick commerce landscape in India.
Supported Platforms
The groupeta endpoint supports all 7 quick commerce platforms available in the API. Each platform returns its current estimated delivery time for the given location. Some platforms like BlinkIt and Zepto focus on ultra-fast 10-minute delivery, while others like DMart and BigBasket offer scheduled slots.
Understanding the groupeta Endpoint
The groupeta endpoint queries delivery ETAs across multiple platforms in a single call. You provide latitude, longitude, and a list of platforms, and it returns the current delivery estimate for each platform at that location. The response includes the ETA in minutes, the delivery promise text (e.g. "Delivery in 8 minutes"), and whether the platform is currently serviceable at that location.
Let us start by making a groupeta call for a location in Koramangala, Bangalore, one of the best-served areas for quick commerce in India. You can test this yourself in the API Playground.
curl -X GET "https://api.quickcommerceapi.com/api/v1/groupeta?lat=12.9352&lng=77.6245&platforms=blinkit,zepto,swiggy,bigbasket,dmart,jiomart,minutes" \
-H "X-API-Key: YOUR_API_KEY" \
-H "x-geolocation-pincode: 560034"{
"location": {
"lat": 12.9352,
"lng": 77.6245,
"pincode": "560034"
},
"platforms": {
"blinkit": {
"status": "success",
"eta_minutes": 8,
"eta_text": "Delivery in 8 minutes",
"serviceable": true,
"store_name": "Blinkit Koramangala"
},
"zepto": {
"status": "success",
"eta_minutes": 10,
"eta_text": "10 min delivery",
"serviceable": true,
"store_name": "Zepto Cafe - Koramangala"
},
"swiggy": {
"status": "success",
"eta_minutes": 12,
"eta_text": "Get it in 12 mins",
"serviceable": true,
"store_name": "Swiggy Instamart - Koramangala 5th Block"
},
"bigbasket": {
"status": "success",
"eta_minutes": 18,
"eta_text": "Delivery in 15-20 min",
"serviceable": true,
"store_name": "bb now - Koramangala"
},
"dmart": {
"status": "success",
"eta_minutes": 45,
"eta_text": "Delivery by 2:30 PM",
"serviceable": true,
"store_name": "DMart Ready - Koramangala"
},
"jiomart": {
"status": "success",
"eta_minutes": 60,
"eta_text": "Delivery within 1 hour",
"serviceable": true,
"store_name": "JioMart Express"
},
"minutes": {
"status": "success",
"eta_minutes": 15,
"eta_text": "In 15 minutes",
"serviceable": true,
"store_name": "Minutes - Koramangala"
}
},
"credits_used": 7,
"response_time_ms": 2341
}ETA Comparison at a Glance
Here is how delivery ETAs compare at a Koramangala, Bangalore address during a typical afternoon. BlinkIt leads with an 8-minute estimate, while scheduled-delivery platforms like DMart and JioMart trade speed for lower prices. The sweet spot for most users is the 10-15 minute range where Zepto, Swiggy, and Minutes compete.
| Platform | ETA | Delivery Promise | Serviceable | Type |
|---|---|---|---|---|
| BlinkIt | 8 min | Delivery in 8 minutes | Yes | Ultra-fast |
| Zepto | 10 min | 10 min delivery | Yes | Ultra-fast |
| Swiggy Instamart | 12 min | Get it in 12 mins | Yes | Quick |
| Minutes | 15 min | In 15 minutes | Yes | Quick |
| BigBasket (bb now) | 18 min | Delivery in 15-20 min | Yes | Quick |
| DMart Ready | 45 min | Delivery by 2:30 PM | Yes | Scheduled |
| JioMart | 60 min | Delivery within 1 hour | Yes | Scheduled |
Delivery ETA Comparison (Koramangala, Bangalore)
Quick Commerce Market Share (India 2025)
8 min
Fastest
BlinkIt avg
7
Platforms
Compared
7 credits
API Cost
All platforms
Real-time
Data
Live ETAs
ETA Dashboard Architecture
Info
DMart, JioMart, and Minutes require the x-geolocation-pincode header for accurate ETA results. Without it, these platforms may return an error or inaccurate data. Always pass the pincode for the most reliable results.
Building the Dashboard UI
Let us build a React dashboard component that fetches ETA data and visualizes it using a horizontal bar chart with recharts. The component handles loading, errors, and sorts platforms by fastest delivery. We will also add color coding: green for under 10 minutes, amber for 10-20 minutes, and red for over 20 minutes.
import { useState, useEffect } from "react";
import { BarChart, Bar, XAxis, YAxis, Tooltip, Cell, ResponsiveContainer } from "recharts";
interface PlatformETA {
status: string;
eta_minutes: number;
eta_text: string;
serviceable: boolean;
store_name: string;
}
interface ETAResponse {
platforms: Record<string, PlatformETA>;
credits_used: number;
}
const ALL_PLATFORMS = "blinkit,zepto,swiggy,bigbasket,dmart,jiomart,minutes";
const getColor = (eta: number) => {
if (eta <= 10) return "#22c55e"; // green
if (eta <= 20) return "#f59e0b"; // amber
return "#ef4444"; // red
};
const PLATFORM_LABELS: Record<string, string> = {
blinkit: "BlinkIt",
zepto: "Zepto",
swiggy: "Swiggy",
bigbasket: "BigBasket",
dmart: "DMart",
jiomart: "JioMart",
minutes: "Minutes",
};
export default function ETADashboard() {
const [data, setData] = useState<ETAResponse | null>(null);
const [loading, setLoading] = useState(true);
const [coords, setCoords] = useState({ lat: 12.9352, lng: 77.6245 });
const [pincode, setPincode] = useState("560034");
const fetchETA = async (lat: number, lng: number, pin: string) => {
setLoading(true);
try {
const res = await fetch(
`https://api.quickcommerceapi.com/api/v1/groupeta?lat=${lat}&lng=${lng}&platforms=${ALL_PLATFORMS}`,
{
headers: {
"X-API-Key": process.env.NEXT_PUBLIC_QC_API_KEY!,
"x-geolocation-pincode": pin,
},
}
);
setData(await res.json());
} catch (err) {
console.error("Failed to fetch ETA:", err);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchETA(coords.lat, coords.lng, pincode);
}, [coords, pincode]);
const chartData = data
? Object.entries(data.platforms)
.filter(([_, v]) => v.serviceable)
.map(([key, v]) => ({
name: PLATFORM_LABELS[key] || key,
eta: v.eta_minutes,
text: v.eta_text,
}))
.sort((a, b) => a.eta - b.eta)
: [];
return (
<div className="max-w-3xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-2">Delivery ETA Dashboard</h1>
<p className="text-gray-500 mb-6">
Real-time delivery estimates from 7 platforms at your location
</p>
{/* Location input */}
<div className="flex gap-2 mb-6">
<input
value={pincode}
onChange={(e) => setPincode(e.target.value)}
placeholder="Pincode (e.g. 560034)"
className="border rounded-lg px-4 py-2 w-40"
/>
<button
onClick={() => {
navigator.geolocation.getCurrentPosition((pos) => {
setCoords({ lat: pos.coords.latitude, lng: pos.coords.longitude });
});
}}
className="bg-blue-600 text-white px-4 py-2 rounded-lg"
>
Use My Location
</button>
</div>
{loading ? (
<div className="text-center py-12 text-gray-400">Loading ETAs...</div>
) : (
<>
<ResponsiveContainer width="100%" height={chartData.length * 50 + 40}>
<BarChart data={chartData} layout="vertical" margin={{ left: 80 }}>
<XAxis type="number" domain={[0, "auto"]}
label={{ value: "Minutes", position: "bottom" }} />
<YAxis type="category" dataKey="name" width={80} />
<Tooltip formatter={(val: number) => [`${val} min`, "ETA"]} />
<Bar dataKey="eta" radius={[0, 6, 6, 0]}>
{chartData.map((entry, i) => (
<Cell key={i} fill={getColor(entry.eta)} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
{/* Legend */}
<div className="flex gap-4 mt-4 text-sm">
<span className="flex items-center gap-1">
<span className="w-3 h-3 rounded-full bg-green-500" /> Under 10 min
</span>
<span className="flex items-center gap-1">
<span className="w-3 h-3 rounded-full bg-amber-500" /> 10-20 min
</span>
<span className="flex items-center gap-1">
<span className="w-3 h-3 rounded-full bg-red-500" /> Over 20 min
</span>
</div>
<p className="text-xs text-gray-400 mt-4 text-right">
Credits used: {data?.credits_used}
</p>
</>
)}
</div>
);
}Adding Location Detection
For the best user experience, your dashboard should automatically detect the user's location. Here is a utility function that gets the user's coordinates from the browser and reverse geocodes to find the pincode. This ensures DMart, JioMart, and Minutes return accurate ETAs.
import { useState, useEffect } from "react";
interface LocationState {
lat: number;
lng: number;
pincode: string;
city: string;
loading: boolean;
error: string | null;
}
export function useLocation() {
const [location, setLocation] = useState<LocationState>({
lat: 12.9716, lng: 77.5946, // Default: Bangalore
pincode: "560001", city: "Bangalore",
loading: true, error: null,
});
useEffect(() => {
if (!navigator.geolocation) {
setLocation((prev) => ({ ...prev, loading: false, error: "Geolocation not supported" }));
return;
}
navigator.geolocation.getCurrentPosition(
async (position) => {
const { latitude, longitude } = position.coords;
try {
// Reverse geocode with a free service or Google Maps
const res = await fetch(
`https://nominatim.openstreetmap.org/reverse?lat=${latitude}&lon=${longitude}&format=json`
);
const geo = await res.json();
setLocation({
lat: latitude,
lng: longitude,
pincode: geo.address?.postcode || "560001",
city: geo.address?.city || geo.address?.town || "Unknown",
loading: false,
error: null,
});
} catch {
setLocation({
lat: latitude, lng: longitude,
pincode: "560001", city: "Unknown",
loading: false, error: null,
});
}
},
(err) => {
setLocation((prev) => ({ ...prev, loading: false, error: err.message }));
}
);
}, []);
return location;
}Monitoring ETA Trends Over Time
Delivery ETAs change throughout the day. During lunch and dinner rush, ETAs spike as delivery partners are stretched thin. By tracking ETAs at regular intervals, you can identify patterns like "BlinkIt is fastest before 11am but Zepto wins after 6pm" or "BigBasket ETAs double on weekends." This data is valuable for logistics teams, marketplace analysts, and apps that recommend the fastest platform at any given moment.
You can reuse the same cron-based approach from our price tracking guide to log ETAs to a database every 30 minutes. Combine this with a charting library to build a time-series ETA visualization.
Tip
The groupeta endpoint with all 7 platforms costs 7 credits per call. If you poll every 30 minutes for 24 hours, that is 336 credits per day. Consider reducing the platform list or polling frequency for cost efficiency. Check the pricing page for bulk credit options.
Get Started
Sign up for free
Create your account at quickcommerceapi.com/auth/signup. Get 50 free credits instantly.
Test groupeta in the Playground
Head to the API Playground and try a groupeta call with your coordinates. See how ETAs vary by location.
Build your dashboard
Use the React component above as a starting point. Install recharts with: npm install recharts
Add location detection
Integrate the useLocation hook for automatic location detection. Remember to pass the pincode header for DMart, JioMart, and Minutes.
Deploy and iterate
Deploy to Vercel or Netlify. Add features like ETA history, notifications for fast delivery windows, and multi-location comparison.
Try It Now
Want to see groupeta in action before building anything? The API Playground lets you make live API calls with your key and see real ETA data from your location.
What to Build Next
A delivery ETA dashboard pairs naturally with other QuickCommerce API features. Combine ETA data with price comparison to recommend the cheapest and fastest platform. Use market intelligence data to understand how delivery speed correlates with pricing strategy. Or check out our platform comparison guide for a deep dive into how each platform stacks up across every metric.
Info
The QuickCommerce API returns real-time data from live platforms. ETAs reflect actual current delivery estimates, not historical averages. Results will vary based on time of day, platform load, and local store availability.