Tutorial: Bill payment

A focused walkthrough of menus and calling a payment API from a flow, then branching on its result — the core of any 'pay for something' flow.

What you'll build

A short-code where a caller picks a bill type, enters their account and an amount, then the flow submits the charge to a payment API and confirms the result. This is the Bill Payment template, explained step by step.

Prerequisites

None beyond a published flow. The payment step is an api node that posts to your payment provider — swap the example URL for your own endpoint.

1 · Bill-type menu

Start, then a menu node. All three options lead to the same account-number input, so wire handles 1, 2 and 3 to the same node. The prompt is just a header — the options render underneath it automatically.

menu · data
{
  "prompt": "Pay a Bill",
  "options": [
    { "key": "1", "label": "Electricity" },
    { "key": "2", "label": "Water" },
    { "key": "3", "label": "DSTV / GOtv" }
  ]
}

2 · Capture account & amount

Two input nodes, chained:

input (account) · data
{ "prompt": "Enter your account / meter number:", "variable": "account" }
input (amount) · data
{ "prompt": "Enter amount (GHS):", "variable": "amount" }

3 · Submit the payment & branch on the result

Add an api node that posts the account and amount to your payment endpoint. It routes on two handles — wire next (accepted) to a confirmation end and error (declined / unreachable) to a retry end.

api (submit payment) · data
{
  "method": "POST",
  "url": "https://api.example.com/bills/pay",
  "body": { "account": "{{account}}", "amount": "{{amount}}" },
  "timeoutMs": 8000,
  "saveAs": "billPayment"        // response → {{billPayment}}
}
HandleMeaningWire to
nextPayment accepted (2xx)Confirmation end
errorDeclined / timeout / non-2xx'Try again' end
Always wire the errorhandle so a slow or failing provider doesn't dead-end the session.

4 · Confirmation ends

Two end nodes — one for each branch. They reference the captured variables.

end (accepted) · data
{ "message": "Your payment of GHS {{amount}} for account {{account}} is being processed." }
end (failed) · data
{ "message": "We could not process your payment. Please try again." }

Test it

Run the flow in the simulator and step through each branch. Ready for more? See Flows & the Studio for conditions, database writes and the full node reference.