# Swiggy MCP Payments

> Take payment on Swiggy MCP — the shared Payment stage (get_payment_options → place-order → check_payment_status → confirm_order) for Food, Instamart and Dineout, with UPI app intent, scan-QR, Cash and Swiggy Money, in both widget and headless clients. Use whenever an order or paid booking must be paid for, a place-order tool returned PENDING_PAYMENT, or the user asks about payment status. Assumes the swiggy-mcp skill.

- Skill: `hktitan/swiggy-mcp-payments` (Agent Skill)
- Install (CLI): `npx skillmds@latest add hktitan/swiggy-mcp-payments`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hktitan/swiggy-mcp-payments/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: HKTITAN (https://skillmd.com/u/hktitan)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/hktitan/swiggy-mcp-payments

---


# swiggy-mcp-payments

```
cart ready → get_payment_options → place-order (paymentMethod …) → PENDING_PAYMENT { paasId, orderId, bridgeUrl, pollingIntervalInMs, maxTimeToPollForInMs }
           → check_payment_status (long-poll ~19 s)  → confirm_order → PLACED  → track
```

Place-order tools: Food `place_food_order`, Instamart `checkout`, Dineout `book_table` (paid deal, after `create_cart`). The three payment tools have the same name and shape on every server.

## Rules

1. **`get_payment_options` is the only source of methods.** Offer exactly what `data.allMethods` (or `platforms.mobile/desktop.methods`, `cod`) returns; never invent a method. Food: pass the same `addressId` used for `get_food_cart` so the picker can place directly.
2. **Never ask which device the user is on and never ask for a UPI ID/VPA.** The picker/QR handle it; UPI Collect and saved VPAs are not surfaced (NPCI compliance).
3. **Pass the user's pick byte-for-byte.** UPI app → `paymentMethod: "UPI"` + `intentApp: <method.id>`. Desktop scan-QR → `paymentMethod: "UPI"` + `generateUPIQR: true`, no `intentApp`. Cash → `paymentMethod: "Cash"` (only when `cod.available`). Swiggy Money → `paymentMethod: "SwiggyPay"` only if a method with that group is returned. `paymentMethod` is always the group name, never an app id.
4. **`PENDING_PAYMENT` is not an order.** Say "Complete the payment in your UPI app — I'll confirm your order once payment succeeds." Never say placed/confirmed/successful until `confirm_order` succeeds (or `check_payment_status` reports `confirmed: true`). Only then use the branded `message` ("Swiggy order placed successfully").
5. **Widget hosts (Claude Desktop, ChatGPT, Cursor…): do not poll.** The confirmation widget polls `check_payment_status` and auto-finalizes. Call it once only if the user asks "did my payment go through?". Call `confirm_order` yourself only if the result says auto-confirm could not run.
6. **Headless clients (no widget): you own the loop.** Give the user `data.bridgeUrl` (opens a scan-or-tap page: QR on desktop, app button on mobile; present for both intent and QR choices — read it from `data`, do not parse `message`). Then poll `check_payment_status` every `pollingIntervalInMs`, capped at `maxTimeToPollForInMs`. Never tight-loop: it is a long-poll and hammering it stresses the payment cache.
7. **Echo identifiers; never reconstruct them.**

| Server | `check_payment_status` args | `confirm_order` args |
| --- | --- | --- |
| Food | `paasId, orderId, addressId, cartId, lat, lng` (all echoed from `place_food_order`; without them the order stays pending) | `orderId, addressId, lat, lng` (+`cartId`) — **no `paasId`** |
| Instamart | `paasId, orderId` | `orderId, paasId` (+`transactionId`) |
| Dineout | `paasId, orderId` | `orderId, paasId` (+`transactionId`) |

`paasId` is the payment transaction id from the place-order response — never `"UPI"`, `"PayWithQR"` or an app id. If you do not have a real `paasId`, do not call the tool.

## Branch on `check_payment_status.data`

| `status` / flags | Then |
| --- | --- |
| `success` / `paid` (`isTerminalSuccess`) | if `confirmed` is true → done; else `confirm_order` once |
| `failed` (`isTerminalFailure`) | **do not confirm**; re-show `get_payment_options` and place again (fresh transaction, same cart) |
| `cancelled` | order cancelled; any debit is refunded; do not retry on your own |
| `cart_changed` | not a payment failure: price/stock changed, order NOT placed; review the cart with the user, then place again |
| `refund-initiated` | debited and refund underway; tell the user; stop |
| `pending`, `terminal: false` | keep waiting on the cadence; at the cap call `confirm_order` once (backend marks it failed if still unpaid; a late success reconciles server-side) |

`confirm_order` is idempotent and never places an unpaid order; a duplicate call is harmless, a call after a terminal failure is pointless.

## Cash

No payment leg: place with `paymentMethod: "Cash"` and go straight to tracking. Cash is the automatic fallback when UPI is unavailable for the cart (`platforms` omitted, only `cod`).

## Swiggy Money

Announced for MCP on 4 Sept 2026: the user adds money once and the agent pays without a per-order payment step. It surfaces as a `SwiggyPay` group in `get_payment_options` when enabled for the account and cart; treat it like Cash (no pending leg) and never pass it when it is not listed.

