New to Kestra?
Use blueprints to kickstart your first workflows.
Read recent Razorpay settlements every morning, change nothing, and alert Slack when money to the bank has failed, is delayed, or is on hold.
Razorpay collects a business's payments and settles them to its bank account, usually two working days later. When a settlement fails because the bank details are wrong, or stops because the account is on hold, nothing pages the business: the finance team finds out days later when the bank balance does not match. This blueprint turns a scheduled, read-only call to the Razorpay Settlements API into a cash-flow gate: io.kestra.plugin.core.http.Request reads recent settlements, one jq query counts processed, failed and stuck settlements and adds up the money that reached the bank, and the result routes to a quiet log or a Slack alert.
list_settlements (io.kestra.plugin.core.http.Request) calls GET /v1/settlements with from and to covering the last lookback_days (Unix seconds) and count=100, using HTTP basic auth with the Razorpay key ID and key secret. It is a read: nothing is created or changed. Retries cover short network blips, and allowFailed plus allowFailure keep an API error from aborting the flow so it can be reported instead.summarize_settlements (io.kestra.plugin.core.debug.Return) first guards for a missing or non-200 response (UNREACHABLE). Otherwise one jq query counts settlements by status, marks any still created for longer than max_pending_hours as delayed, adds up the amount of processed settlements (converted from paise to rupees), keeps the UTR of the latest one, and classifies the window: any failed settlement is FAILED, any delayed one is DELAYED, no settlements at all is NONE when expect_settlements is true, otherwise HEALTHY.route_by_settlement_state (io.kestra.plugin.core.flow.Switch) branches on that classification: HEALTHY logs the settled amount and latest UTR, DELAYED and NONE post a Slack message, FAILED and UNREACHABLE page Slack. A defaults fallback logs anything unexpected.log_audit_result (io.kestra.plugin.core.log.Log) writes one audit line per run with the HTTP status and the full summary, so the check's own history survives a Slack outage.errors block pages Slack if the flow itself fails, so a broken sentinel is never mistaken for settlements arriving normally.morning_check trigger runs at 10:00 IST (04:30 UTC) every day and ships disabled: true.status output (HEALTHY / DELAYED / NONE / FAILED / UNREACHABLE) and a settled_rupees output other flows can use, for example to hold a vendor payout run until settlements have landed.Razorpay's Dashboard shows settlement status when someone opens it, and a failed or held settlement is easy to miss in a busy week. Kestra turns a plain, read-only API call into a scheduled, typed classification with retries, a failure path and a full execution history, and the status output lets other flows wait for the money before paying vendors or closing the day's books.
rzp_test_) in the Dashboard under Account & Settings > API Keys.RAZORPAY_KEY_ID: the Razorpay API key ID.RAZORPAY_KEY_SECRET: the matching key secret.SLACK_WEBHOOK: Slack incoming webhook used for every alert branch and the flow-failure alert.In Kestra OSS, secrets are supplied as environment variables prefixed SECRET_ and base64-encoded, for example SECRET_RAZORPAY_KEY_ID=$(echo -n 'rzp_test_xxxxxxxx' | base64), and read back with {{ secret('RAZORPAY_KEY_ID') }}. Use the Enterprise secrets backend for encryption at rest and access control.
RAZORPAY_KEY_ID, RAZORPAY_KEY_SECRET and SLACK_WEBHOOK as secrets.status, settled_rupees and the latest UTR in the logs against the Settlements page in the Razorpay Dashboard.max_pending_hours to match your settlement cycle (for example 48 for T+2, 24 if you use instant settlements) and enable morning_check.GET /v1/settlements/recon/combined to list the payments, refunds and fees inside each settlement for line-by-line reconciliation.status == HEALTHY with a Flow trigger.lookback_days: type INT, default 3.max_pending_hours: type INT, default 48.expect_settlements: type BOOL, default true.status: one of HEALTHY, DELAYED, NONE, FAILED, UNREACHABLE.settled_rupees: total amount of processed settlements in the window, in rupees.{{ fromJson(outputs.summarize_settlements.value).latest_utr }} for the bank UTR of the latest settlement.count is capped at 100 per call; that covers more than three months of daily settlements, but add paging with skip if you use a much longer window.settled_rupees is in rupees.NONE fire with a 1-day window; keep lookback_days at 3 or more, or set expect_settlements to false.