/integrate — Juspay Integration Orchestrator
PRIME DIRECTIVE: This file is a decision engine. It contains no product knowledge.
Product knowledge lives in
. Authoritative implementation facts come only from MCP tool calls — never from memory or training.
MCP PREFERENCE: Always prefer
tools for live merchant data (credentials, settings, gateway config, integration status). Use
only for documentation structure and page content.
AGENT SELF-CHECK (run mentally before each phase)
- Did I authenticate with before calling any tools? If not, Please trigger the authentication flow now.
- Did I call
juspay_get_merchant_details
to establish merchant context before asking for credentials?
- Did I read before calling ? Can I conclude from the catalog alone?
- Did I scan the codebase before asking disambiguation questions (language, framework)?
- Did I call before writing any code?
- Am I using method names and field names from the fetched docs, not from memory?
- For SDK/web redirect products: did I fetch test resources and run tests for each checklist stage wherever possible
FLAG PARSING
Extract flags before starting:
| Flag | Effect |
|---|
| Skip recommendation. Confirm the product in one line, then go to Phase 1. Still run catalog-first check. |
| Hint for platform selection in Phase 2 — still verify against codebase before asking. |
UI INTERACTION RULES
Whenever the user must choose between fixed options:
- Use native select / choice UI
- Do NOT ask for free-text replies if options are known
- Wait for a selection before continuing
- Do NOT rephrase the same question again after rendering choices
- Do NOT ask for information you can derive — from the codebase, from live data, or from the catalog
Format choices as structured options, not inline prose.
PHASE 0 — Intent Collection and Product Selection
Step 0A — Load product catalog
Read all files in
. Each file has: product ID, platforms, use cases, and intent signals.
Store the full set as
. This is your local knowledge for matching — do not use training-data knowledge about products.
Step 0B — Auto-resolve integration type from merchant account
Call:
juspay-mcp:juspay_get_merchant_details()
Extract and store:
- — from the field
- — always default to . Never extract this from the API response. Inform the user:
"Client ID is typically the same as your merchant ID (
). If you use a different client ID, please provide it now — otherwise I'll proceed with
."
Wait for confirmation or a custom value before continuing.
- — from the field, which is an array; take the first element (e.g. → )
Map
to a recommended product:
| Recommended product ID |
|---|
| |
| |
| |
| (anything else or absent) | No inference — fall back to Step 0B-Fallback |
Step 0B-Confirm — Present inferred recommendation
If a mapping was found, present a single confirmation:
"Based on your account configuration, it looks like you're set up for [Product Name].
Shall I proceed with integrating [Product Name]?
- Yes, proceed
- No, let me choose a different product type
- No, let me choose a specific product"
- Option 1 → set to the inferred product ID and skip to Phase 1
- Option 2 → go to Step 0B-Fallback (product type list)
- Option 3 → show the full flat product list from and let the user pick directly
Step 0B-Fallback — Ask the user what they want to build
Only reached if
is absent, unrecognized, or the user chose Option 2 above.
What type of product are you looking to integrate?
- Checkout
- UPI
- Payouts
- Billing
- Not sure
Step 0B1 — Ask the User to Choose a Product
Based on the selected category, ask the relevant follow-up question.
If the user selects Checkout
Which Checkout product would you like to integrate?
- Hyper Checkout
- Express Checkout SDK
- Express Checkout API
If the user selects UPI
Which UPI product would you like to integrate?
and so on for Payouts and Billing categories...
If the user selects Not sure
ask:
Please describe your use case and I'll recommend the right product and integration flow.
Step 0C — Match intent to candidates
Using
and the
field in each
entry, select 1–3 products as
.
Matching rules:
- "checkout UI", "payment page", "mobile SDK" → prefer products with runtime platforms (android, ios, web, etc.)
- "API only", "server-side", "REST", "backend" → prefer products with no runtime platforms
- "recurring", "subscriptions", "mandates" → billing/mandate products
- "payout", "transfer", "disburse" → payout products
- "UPI", "TPAP", "P2P", "P2M" → UPI products
Aim for 1–3 candidates. Fewer is better.
Step 0D — Catalog-first product resolution
Before calling , check if the catalog entry is conclusive:
A catalog entry is conclusive if:
- The list either matches exactly, or has only one option
- No further platform disambiguation is required to start code generation
If conclusive → skip
for this candidate and proceed.
If
not conclusive (e.g. multiple overlapping platforms, need page count for complexity signal) → call:
juspay-docs-mcp:explore_product({ product: <candidate-id> })
Extract only what you need for recommendation:
- Product title
- Platform IDs — runtime IDs signal a client SDK; only signals a server API; a mix signals both
- Number of numbered base integration pages (complexity signal)
- List of supported platforms if a client SDK is present
Do not fetch individual doc pages here.
Step 0E — Recommend and confirm
Present your recommendation grounded in what you read from
and
:
"Based on what you described, here's what I recommend:
[Product Title] — [one-line reason tied to their intent]
(Alternative) [Product Title] — [reason]
Which would you like to integrate? Or pick from the full list below:"
List all products from
as a numbered reference so the user can override.
Store the confirmed choice as
(the product ID from the products/ file).
PHASE 1 — Full Product Exploration
Only call if it wasn't already called in Phase 0D for .
If already called and
is populated → skip directly to Phase 1A.
Otherwise call:
juspay-docs-mcp:explore_product({ product: $PRODUCT })
Read the full response. This is the authoritative doc structure.
1A — Parse into $DOC_MAP
Extract and store:
- Product title and description
- — every platform entry with its ID and title
- For each platform: → for each section: ,
- For each page: and the URL
Pages numbered "1. …", "2. …" are base integration pages in required order. Preserve that order exactly.
1B — Classify product type
| Platform IDs observed | Classification |
|---|
| Runtime IDs: , , , , , , , | |
| Only | |
| Mix of + runtime IDs | |
PHASE 2 — Adaptive Flow
If
No platform question. Backend language comes from
— only ask if not detected.
If
Step 2-SDK-A — Detect platform from codebase
Before asking the user, scan the working directory for platform signals:
| File / pattern found | Detected platform |
|---|
| |
| with in dependencies | |
| with in dependencies | |
| or with in dependencies | |
| or (no Flutter/RN/Cordova/Capacitor signals) | |
| or (no Flutter/RN signals) | |
| with no mobile framework signals, or / files | or |
If a platform is detected with confidence, present it as the pre-selected recommendation:
"I detected your project is a
[Platform] app (found
).
Shall I proceed with [Platform]?
- Yes, use [Platform]
- No, let me choose a different platform"
If the user confirms, skip to disambiguation. If they choose option 2, or if no signal is found, present the full platform list from
.
Step 2-SDK-B — Disambiguation
Apply after platform is confirmed:
- Android: ask Java vs Kotlin
- iOS: ask Swift vs Objective-C, CocoaPods vs SPM
- Web: if both and are in the doc map, ask which variant
Store as
. Filter
to the chosen platform's pages.
If
Ask first:
"This product has both a backend API and a client SDK. What do you need?
- Backend API only
- Client SDK only
- Both"
Then follow the
path,
path, or both, as appropriate.
PHASE 3 — Doc Fetch
Always use . Only fall back to WebFetch if MCP returns an explicit error on a valid URL.
juspay-docs-mcp:doc_fetch_tool({ url: "<md content link from $DOC_MAP>" })
Fetch order:
- Pre-Requisites / Overview — always first; defines credentials, auth format, version constraints
- Numbered base integration pages — in exact numbered order from
- Webhooks, Order Status API
- Error Codes (resources section)
- Advanced sections — only if user asks
While reading each page, extract and store:
- — every request field, method param, constructor arg (required vs optional)
- — exact method names, class names, key identifiers from the docs
- — all status values, error codes, failure reasons
- — min SDK version, min language/platform version
- — any "note", "important", "warning" callout blocks
PHASE 4 — Parameter Collection
Tell the user:
"I've read the documentation. I'll collect what I need."
Step 4A — Auto-resolve merchant context via MCP
,
, and
were already fetched in Phase 0B — reuse those values. Do not call
juspay_get_merchant_details()
again.
Then call both in parallel:
juspay-mcp:juspay_get_webhook_settings()
juspay-mcp:juspay_get_general_settings()
From webhook settings, extract:
- — existing webhook URL if configured (check if non-empty)
- — currently subscribed events
From general settings, extract:
- — existing return URL if configured (check if non-empty)
If is empty or not configured:
First, scan the codebase for an existing webhook handler (e.g.
,
,
route). If one exists, note its path as
.
Then ask the user:
"No webhook URL is configured. Your app has a webhook handler at
.
Please provide your deployed base URL so I can set it to
https://<your-domain>/$WEBHOOK_PATH
.
If you don't have a deployed URL yet, you can:
- Run locally to get a temporary public URL
- Leave this for now and configure it on the Juspay dashboard before going live"
Do
not set a placeholder URL (e.g.
) — only call
juspay_update_webhook_settings
if the user provides a real, publicly reachable HTTPS URL that routes to the webhook handler.
Once a valid URL is provided, call:
juspay-mcp:juspay_update_webhook_settings({
webHookurl: <base-url> + "/" + <$WEBHOOK_PATH>,
webhookEvents: <merge existing $WEBHOOK_EVENTS with standard events for this product>
})
After updating, confirm what was set:
"Webhook URL set to
. The following events are now enabled:
- (list every event where the value is in the updated config)"
If is empty or not configured:
First, scan the codebase for an existing return URL page or handler that can receive the Juspay redirect and handle order status response. If one exists, note its path and use that when asking the user.
Ask the user:
"No return URL is configured for your account. Please provide the URL customers should be redirected to after payment completes. This must be a real route in your app that can handle the payment return/order status response."
After the user provides a URL, validate that it matches an existing route or handler in the codebase.
juspay-mcp:juspay_update_general_settings({ returnUrl: <user-provided URL> })
- If it does not match, warn the user:
"The URL you provided does not appear to exist in the current codebase as a return handler. Are you sure you want to use this?"
Environment is always production. Do not ask the user. Use production host URLs from the docs.
Step 4B — Auto-provision API key
Do not ask the user for an API key. Instead, call:
juspay-mcp:juspay_create_api_key({ description: "integrate-skill-<product>-<date>" })
Store the returned plaintext value as
. Warn the user:
"A new API key has been created for your account for testing this integration"
Never display the key to the user.
Step 4C — Collect remaining required params
Ask in order:
- Required params — each required field the user must supply (skip auto-generated fields and anything already resolved: $MERCHANT_ID, $CLIENT_ID, $API_KEY, $WEBHOOK_URL)
- Platform version check (SDK path only) — if docs specify a minimum version
- Backend language — if not already detected from codebase
PHASE 5 — Code Generation
Rule: use code examples and method names from fetched docs as the base. Substitute collected values. Do not use method or class names you did not see in the docs.
Generate in order:
-
Auth / credentials setup — use environment variables, never hardcode values
-
Core integration — API call or SDK install → init → open → response handler
-
Webhook handler — if docs have a webhooks section; include signature verification
-
Status verification utility — if docs have a status/order API
-
DB schema — Read existing codebase to generate a DB schema for storing transaction/order IDs, statuses, and any other relevant info for reconciliation and status checks. Use field names from the docs.
- Ask the user if they want to see the raw SQL or a Prisma/TypeORM/Mongoose schema based on their detected backend language/framework.
- If the product has a status API, include fields for storing Juspay order/transaction IDs to correlate with their internal orders.
- Generate validation rules based on any constraints mentioned in the docs (e.g. max length, required fields).
-
Error handling — use error codes from the docs to show how to handle different cases
PHASE 6 — Checklist and Error Reference
Checklist
Generate a checklist from what you actually fetched — every item must reflect something real in this product's docs.
## Integration Checklist — [Product] on [Platform or API]
### Credentials
- [ ] [credential from docs] stored as env var
- [ ] API key generated via dashboard or juspay-mcp
### [Backend / API]
[items derived from API doc pages]
### [Frontend / SDK] (if applicable)
[items derived from SDK doc pages]
### Testing
- [ ] Successful sandbox transaction
- [ ] Error case from $ERROR_CODES tested
- [ ] Webhooks verified end-to-end
### Integration Stages (from Juspay)
Call:
juspay-mcp:juspay_integration_monitoring_status({
platform: <$PLATFORM mapped to "Backend" | "Web" | "Android" | "IOS">,
product_integrated: <mapped from $PRODUCT — see mapping below>,
merchant_id: $MERCHANT_ID,
start_time: <30 days ago in YYYY-MM-DDTHH:MM:SSZ>,
end_time: <now in YYYY-MM-DDTHH:MM:SSZ>
})
**Product mapping for `product_integrated`:**
| $PRODUCT | product_integrated |
|---|---|
| hyper-checkout | Payment Page Session |
| ec-headless | EC + SDK |
| ec-api | EC Only |
| *(others)* | Payment Page Session |
**Platform mapping for `platform`:**
| $PLATFORM | platform |
|---|---|
| web, iframe-web | Web |
| android | Android |
| ios | IOS |
| flutter, react-native, cordova, capacitor | Android |
| api-only products | Backend |
Render the response as a checklist. For each stage where `visibilityResult` is `true` and `disableStage` is `false`:
[sectionDisplayName or section key]
- Do **not** show `status` — it is not updated in real time
- Mark stages with `criticalResult: true` as ⚠️ Critical
- Group stages by their parent section key
### Go-Live
- [ ] Switched to production environment and keys
- [ ] Production end-to-end test passed
Error Reference
## Error Codes
| Code / Status | Meaning | Recommended action |
|---------------|---------|-------------------|
[from $ERROR_CODES]
What's next
Briefly offer to go deeper on sections from
that weren't part of the base integration — but only mention things you actually saw in the doc map.
PHASE 7 — Live Testing
Always attempt to run the server and test the integration yourself. Do not tell the user to test manually if you can do it.
Step 7A — Start the dev server
Scan the codebase for the start command:
| Signal | Command |
|---|
| with script | (or ) |
| Cannot run — skip to Step 7C |
| Mobile-only project (no web server) | Cannot run — skip to Step 7C |
Run the server in the background, wait for it to be ready, then proceed.
Important: Shell environment variables override
files in Vite/Node. Before starting the server, check if any required env vars (e.g.
) are already set in the shell and would conflict with the project's
. Unset them if they don't belong to this project.
Step 7B — Run backend API tests
For each backend endpoint generated in Phase 5, send a real HTTP request using
and verify both the HTTP response AND any DB/state side-effects:
- Session / order creation endpoint — POST with a real order ID from the DB; expect a payment link back; verify is written to the DB row.
- Order status endpoint — GET with the Juspay order ID from step 1; expect a status response from Juspay.
- Webhook endpoint — POST a synthetic payload using the from step 1; use and assert the HTTP status code is 200 (Juspay marks a webhook as "not notified" for any non-200 response and retries with progressive delays); also verify the body contains and query the DB to confirm and were updated.
- Webhook endpoint (failure) — POST a synthetic payload; assert HTTP 200 and verify in the DB.
If any test fails:
- Read the server logs for the actual error message
- Diagnose and fix the root cause (wrong env var, bad header, type mismatch, etc.)
- Re-run until the test passes
Step 7C — Run browser-based integration stage tests (SDK/web redirect products only)
This step applies when or and the product uses a Juspay-hosted payment page (web redirect flow).
The integration checklist stages from Phase 6 (New Card, UPI Collect, UPI Intent, Wallet, etc.) are registered on Juspay's servers only when real transactions flow through Juspay's hosted payment page. Some of these can be tested via curls, call out clearly what you can't test instead of silently skipping.
Step 7C-1: Fetch test credentials
fetch the test resources page for the platform:
juspay-docs-mcp:doc_fetch_tool({ url: "<test-resources md content link from $DOC_MAP>" })
Extract:
- — card numbers, expiry, CVV for the Dummy PG / simulator
- — VPA values for UPI success/failure (e.g. , )
- — how to trigger success vs failure for each payment method on the simulator
Step 7D — Report results
After all testing, report a unified pass/fail table covering both backend and browser tests:
| Test | Type | Result |
|------|------|--------|
| POST /api/juspay/session → payment link + DB write | Backend | ✅ / ❌ |
| GET /api/juspay/order-status | Backend | ✅ / ❌ |
| POST /api/juspay/webhook ORDER_SUCCEEDED → DB updated | Backend | ✅ / ❌ |
| POST /api/juspay/webhook ORDER_FAILED → DB updated | Backend | ✅ / ❌ |
| Payment Page Opens | Browser | ✅ / ❌ |
| New Card — success | Browser | ✅ / ❌ |
| New Card — failure | Browser | ✅ / ❌ |
| UPI Collect — success | Browser | ✅ / ❌ |
| UPI Collect — failure | Browser | ✅ / ❌ |
| [other visible stages] | Browser | ✅ / ❌ |
If a browser test cannot be completed (Juspay payment page blocks headless browsers, CAPTCHA, etc.), say so explicitly — do not silently skip it.
TOOL CALL REFERENCE
| When | Tool | Purpose |
| ------------- | ------------------------------------------- | ----------x----------------------------------------------------------------------------------- |
| Phase 0A | Read
| Load product summaries for intent matching |
| Phase 0B |
juspay_get_merchant_details()
| Auto-resolve merchant ID, client ID, integration type — infer recommended product |
| Phase 0D |
explore_product(candidate-id)
| Probe type and platforms before recommending |
| Phase 1 |
explore_product($PRODUCT)
| Get full doc structure and page URLs |
| Phase 3 |
| Fetch individual doc pages for implementation details |
| Phase 4A |
juspay_get_webhook_settings()
| Check if webhook URL is already configured |
| Phase 4A |
juspay_get_general_settings()
| Check if return URL is already configured |
| Phase 4A |
juspay_update_webhook_settings(...)
| Configure webhook URL if not already set |
| Phase 4A |
juspay_update_general_settings(...)
| Configure return URL if not already set |
| Phase 4B |
juspay_create_api_key(...)
| Provision a new API key; returned plaintext shown once |
| Phase 6 |
juspay_integration_monitoring_status(...)
| Fetch live integration stages; render as checklist with criticality + description (no status) |
| Fallback only | WebFetch | Only if
returns an error on a valid URL |
Never construct doc URLs yourself. All URLs come from the
field in
responses.
GUARDRAILS
-
No product knowledge in this file. Product IDs, platform lists, and credential names come from
or MCP responses — never from this file or training data.
-
Read before matching intent. Do not guess which product fits based on training-data familiarity.
-
Call before recommending. Phase 0D is mandatory. You must know the product's type and integration complexity before presenting it as a recommendation.
-
Never construct doc URLs. All URLs come from the
field in
responses.
-
Never fabricate. If a page didn't load or a section wasn't in the docs, say so. Offer the raw URL for the user to check manually.
-
Product type comes from . Do not infer type from the product name or training data.
-
Platform list comes from . Present exactly the platforms that
returned — no more, no less.
-
API-only products never get a platform question. If
has no runtime platform IDs, skip platform selection entirely.
-
Code examples come from the docs. Use the exact method names, class names, and code structure from the fetched documentation pages as your source of truth.
-
Parameters come from the docs. The actual required fields are what the fetched pages say.
-
Code uses doc-sourced names only. If a method or class name doesn't appear in the fetched pages, do not use it.
-
Error codes come from the docs. Collect them from every page you fetch. Do not invent them.