- AgentPay access and a client API key for sandbox (for testing) or production (for live payments). To get both, contact the Cashfree sales team. They set up AgentPay for you and share your API keys. You don’t need a Cashfree merchant account.
- An AI agent or MCP client that supports the Streamable HTTP transport and custom request headers, such as Claude Code, Cursor, or a custom agent built with an MCP SDK.
Connect your agent
Sandbox and production work the same way. Only the server URL and your API key change:- Claude Code
- Cursor
- Custom agent
- curl (for debugging)
-s user to make AgentPay available in all your projects. Run claude mcp list to check it. The output lists agentpay as connected.Supported bill categories
The wallet can pay most bill categories, including Electricity, Water, Gas, LPG, Mobile Postpaid, Broadband, Landline, DTH, Cable TV, Insurance, Fastag, Education, Municipal Taxes, Rental, Subscription, Hospital, Donation and Clubs. Some billers also don’t accept wallet payments.wallet_pay refuses these with wallet_not_supported_by_biller.
Choose a payment flow
Each biller inlist_billers tells you whether your agent fetches the bill, validates the customer’s details, or pays directly. Check fetch_requirement and support_bill_validation, then follow the matching flow:
Pay a bill, step by step
Here is the whole journey at a glance for a biller whose bill your agent fetches. The consent step happens only the first time a customer pays: The following steps continue the BESCOM example from the AgentPay MCP overview and show the tool calls your agent makes at each stage.Find the biller
list_biller_categories to map words like “electricity” to a category, then search for the biller by name with list_billers:biller_id, the details the customer must provide (in biller_customer_params), and which flow to follow (fetch_requirement and support_bill_validation). Here, BESCOM needs a Customer ID and the bill must be fetched.Fetch the bill
request_bill_fetch:ref_id. The bill takes a moment to arrive, so call poll_bill_fetch with the ref_id every 2 to 3 seconds until response_code is 000. Both the status and the bill are inside data, in bill_fetch_response and biller_response:ref_id. A ref_id is valid for 15 minutes, so if more time passes before you debit the wallet, fetch the bill again.Confirm with the customer
Get the customer's consent (first time only)
create_mandate_session with their mobile number. You get a consent_link to send them, ideally in the same message as the bill.The customer opens the link, logs in with a one-time password (OTP), and approves a mandate for your agent. Meanwhile, call get_mandate_session with the session_id until the status is CONFIRMED. That response contains:- An
access_token, which lets you use the customer’s wallet. It lasts about an hour. - A
refresh_token, which gets you a newaccess_tokenlater without asking the customer again. - The
termsthe customer agreed to, such asmax_amount_per_monthandmax_debits_per_month.
Check the wallet balance
get_wallet_balance with the access_token. Go ahead only when eligibility is true, blocked is false, wallet_exists is true, and balance covers the bill.If the balance doesn’t cover the bill, call topup_wallet to create a top-up and send the customer the payment_link. Call get_topup_status until the order is PAID, then check the balance again.Debit the wallet
wallet_pay to take the money from the wallet. Use a new, unique order_id and pass the bill’s ref_id as reference_id:ACCEPTED, which isn’t the final result yet. Call get_pay_status with the same order_id until txstatus is SUCCESS, and save the transaction_id it returns.Pay the biller
request_bill_payment with the transaction_id from step 6 and the ref_id from step 2:transaction_ref_id. Call poll_bill_payment with it and the ref_id until the status is SUCCESS or FAILURE.Share the receipt
SUCCESS, tell the customer the bill is paid and give them the utr (unique transaction reference). This is their proof of payment.If the status is FAILURE, the wallet has already been debited, so don’t charge it again. Refund the customer with refund_payment instead (see Refunds).Flow variations
The step-by-step flow covers a first-time customer paying a fetched bill. The following variations change only some of the steps.Returning customers
Once a customer has approved your agent and you hold their tokens, skip the consent step entirely:access_token has expired, call refresh_access_token with the refresh_token first. Send a new consent link only if the refresh fails, which happens when the customer’s consent expires or is revoked.
Validate-first billers
Some billers can’t return a bill, but they can check that the customer’s details are valid. For these billers, the flow changes in the following places:- Call
request_bill_fetchas usual. Cashfree validates the customer’s details instead of fetching a bill, and the response hasflowset toVALIDATE_AND_PAY. - Poll with
poll_bill_fetchuntilresponse_codeis000. The response confirms the details are valid but has nobiller_response, so there’s no bill amount. - Ask the customer how much to pay, and read it back to confirm.
- In
wallet_pay, pass theref_idasreference_idand the customer’s amount asorder_amount. - In
request_bill_payment, passbill_fetch_ref_idas usual, pluscustomer_params(the sameparam_nameandparam_valuepairs you sent torequest_bill_fetch) andamount(the same amount as the debit).
Direct payments such as donations
Some billers have no bill to fetch or validate, and donations are the most common example. The customer chooses the amount. For these billers, the flow changes in the following places:- Skip
request_bill_fetchandpoll_bill_fetch. Ask the customer for the details inbiller_customer_paramsand the amount, and read them back to confirm. - In
wallet_pay, sendbiller_idinstead ofreference_id. - In
request_bill_payment, leave outbill_fetch_ref_id. Sendcustomer_params(the biller’sbiller_customer_params, asparam_nameandparam_valuepairs) andamount(the same amount as the debit). - In
poll_bill_payment, leave outbill_fetch_ref_id.
Handle failures
When a tool fails, the result hasisError: true and a message that explains what went wrong, for example Cashfree API error 400 for POST /pg/agentpay/wallet/pay: {...}. For the full result format, see Technical details. Return that message to your agent unchanged so it can recover. Tell the customer only that the agent couldn’t fetch or pay the bill, and offer to try again.
Recover without charging twice
The most important question after a failure is whether money has already left the wallet. Use this table to decide what to do:Refunds
If a bill payment fails after the wallet debit succeeds, return the money to the wallet:- Call
refund_paymentwith theorder_idof the debit, a uniquerefund_idyou create, and therefund_amount. - Call
get_refund_statusuntilrefund_statuschanges fromPENDINGtoSUCCESS.
refund_status is SUCCESS, the money is back in the wallet.
You can refund a debit whose txstatus is SUCCESS in either of these cases:
- The bill payment failed.
- The bill payment never reached the biller, and the debit is at least 15 minutes old. This covers a
ref_idthat expired between the debit and the bill payment.
access_token is optional for them.
Troubleshooting
Expand a problem to see the likely cause and fix.Connection issues
HTTP 401 with authentication_error when connecting
HTTP 401 with authentication_error when connecting
Authorization: Bearer header is missing or malformed, so the Cashfree gateway rejects the request before it reaches the server. Add the header to your MCP client configuration.Cashfree API error 401
Cashfree API error 401
The server won't connect
The server won't connect
/mcp.Payment issues
list_billers returns a very long or truncated list
list_billers returns a very long or truncated list
biller_name. Add it to narrow the search.The bill fetch failed or expired
The bill fetch failed or expired
ref_id is valid for 15 minutes. Call request_bill_fetch again to get a fresh one.request_bill_fetch says the biller doesn't support bill fetch
request_bill_fetch says the biller doesn't support bill fetch
Wallet tools return 401 or 403
Wallet tools return 401 or 403
access_token is missing, wrong or expired. Call refresh_access_token. If that fails, send the customer a new consent link.The wallet balance is too low
The wallet balance is too low
topup_wallet, send the customer the payment_link, and wait until get_topup_status shows PAID.The wallet is not eligible, is blocked or doesn't exist
The wallet is not eligible, is blocked or doesn't exist
reason field in the get_wallet_balance response. Usually, the fix is to start a new consent session.wallet_pay returns monthly_debit_limit_exceeded
wallet_pay returns monthly_debit_limit_exceeded
wallet_pay returns agent_pay_bill_fetch_required
wallet_pay returns agent_pay_bill_fetch_required
biller_id for a biller that supports bill fetch or validation. Call request_bill_fetch and pay with its ref_id as reference_id.wallet_pay returns invalid_order_amount
wallet_pay returns invalid_order_amount
payment_amount_exactness, for example the exact bill amount. Every amount must also stay within the biller’s limits for wallet payments and have at most 2 decimal places.wallet_pay returns wallet_not_supported_by_biller
wallet_pay returns wallet_not_supported_by_biller
wallet_pay returns order_id_conflict
wallet_pay returns order_id_conflict
order_id for a different payment. Check get_pay_status for the first order before you try again with a new order_id. Every order_id must be unique across all your customers.request_bill_payment says customer_params and amount are required
request_bill_payment says customer_params and amount are required
customer_params and amount, as described in Flow variations.refund_payment returns bill_already_paid or bill_payment_not_terminal
refund_payment returns bill_already_paid or bill_payment_not_terminal
bill_already_paid means the biller received the payment, so you can’t refund it. bill_payment_not_terminal means the bill payment is still in progress. Poll poll_bill_payment until it’s final, then refund only if it failed.Amounts are 100 times too big or too small
Amounts are 100 times too big or too small
An ID isn't found or doesn't match
An ID isn't found or doesn't match
Security
Two kinds of credentials protect AgentPay: your API key, which identifies your business, and the customer tokens, which let your agent pay from a customer’s wallet.Protect your API key
Your MCP client sends your API key as a Bearer token on every request. The server forwards it to Cashfree and never stores it. It handles each request separately, so you see only your own customers and payments. The server masks the key as*** in any error message. Keep the key in your MCP client configuration or an environment variable, never in prompts or chat messages.
Protect customer tokens
The tokens from the consent step let your agent pay on the customer’s behalf. Follow these practices to keep them safe:- Never ask the customer for a token. Customers only know their bill and mobile number. Your agent gets tokens from the consent flow, not from the customer.
- Store tokens securely on your side, encrypted and linked to the customer. The MCP server doesn’t keep them, so you pass the
access_tokenon every wallet call. - Reuse them. The mandate is a standing permission, so don’t send a new consent link for every bill.
- Stay within the limits. Track how much you’ve debited this month. Cashfree refuses debits that go over
max_amount_per_monthormax_debits_per_month. - Refresh when expired. Use
refresh_access_token. Callingget_mandate_sessionagain doesn’t extend the token. - Revoke when the customer asks. If the customer wants your agent to stop paying from their wallet, call
revoke_consent. Every token for that consent stops working. Payments already in progress still complete, and refunds remain possible.
Test in sandbox
Before you go live, run the full flow in sandbox. Use these test values:- First-time payment. Follow every step in Pay a bill, step by step. It passes when
poll_bill_paymentreturnsSUCCESSwith autr. - Returning customer. Pay a second bill with the same
access_token, without a new consent link. - Direct payment. Pay a Donation biller without fetching a bill.
- Validate-first biller. If you plan to support these billers, pay one with an amount the customer gives.
- Revoke consent. Call
revoke_consent, then check that wallet tools reject the oldaccess_token. - Error handling. Check that your agent responds sensibly to each of the following cases:
- A missing
Authorizationheader returns HTTP 401 with"type": "authentication_error". - Reusing an
order_idfor a different payment returnsorder_id_conflict. - Going over
max_debits_per_monthreturnsmonthly_debit_limit_exceeded. - Paying a Credit Card or Loan Repayment bill is refused.
- A wrong
access_tokenreturns 401 or 403.
- A missing
Go live
When every sandbox check passes, complete the following steps to go live:- Replace your sandbox API key with your production API key.
- Change the server URL to
https://mcp.cashfree.com/agentpay/mcp. - Remove any sandbox-only values from your agent, such as the test OTP
111000. In production, customers receive a real OTP on their mobile number. - Pay one small real bill end to end and check that the customer gets a
utr.
Get help
Raise a support request through the Merchant Support form. Include theorder_id, transaction_id, transaction_ref_id and the time of the payment you’re asking about.