Skip to content

GetCustomerInput

Collect DTMF (keypad) or voice input from customers. This block presents a prompt and waits for the customer to respond.

Signature

csharp
// 1) Prompt + optional action configuration (returns branch builder)
IInputBuilder GetCustomerInput(
    string promptText,
    Action<GetCustomerInputAction>? configure = null,
    string? identifier = null);

// 2) Prompt + branches callback (returns parent flow builder)
// Use this overload when you want to configure all branches inline, then continue chaining
// on the parent flow builder (often paired with ThenContinue()).
IFlowBuilder GetCustomerInput(
    string promptText,
    Action<IInputBuilder> branches,
    Action<GetCustomerInputAction>? configure = null,
    string? identifier = null);

// 3) Advanced configuration with InputConfiguration (Sequential / ASR + DTMF)
IFlowBuilder GetCustomerInput(
    Action<InputConfiguration> configure,
    string? identifier = null);

Required branches

GetCustomerInput is a branching action. Always configure all required branches before you continue your flow:

  • OnTimeout(...)
  • OnDefault(...)
  • OnError(...) (or OnInvalidInput(...) which maps to the same error branch)

Parameters

ParameterTypeRequiredDescription
promptTextstringYesThe prompt text to play
configureAction<GetCustomerInputAction>NoConfigure input settings
branchesAction<IInputBuilder>Only for overload (2)Configure all branches (digits/intents + required fallbacks)
identifierstring?NoOptional identifier for the action

GetCustomerInputAction Properties

PropertyTypeDefaultDescription
TimeoutSecondsint5Time to wait for input
MaxDigitsint1Maximum digits to collect
EncryptInputboolfalseEncrypt collected input
MaxAttemptsint1Number of retry attempts
TerminatingDigitstring?nullDigit that ends input (e.g., "#")

Return Value

Overload (1) returns IInputBuilder which provides branch handlers:

MethodDescription
.OnDigit(string digit, Action<IFlowBuilder>)Handle specific digit input
.OnDigits(Action<IFlowBuilder>)Handle any collected digits
.OnTimeout(Action<IFlowBuilder>)Handle input timeout
.OnError(Action<IFlowBuilder>)Handle errors
.OnDefault(Action<IFlowBuilder>)Handle unmatched input
.OnIntent(string, Action<IFlowBuilder>)Handle Lex bot intent (ASR)
.OnNoMatch(Action<IFlowBuilder>)Handle ASR no match
.OnLowConfidence(Action<IFlowBuilder>)Handle low confidence ASR
.WithRetry(Action<IRetryBuilder>)Configure automatic retry
.WithLexBot(Action<LexBotConfiguration>)Configure Lex bot for ASR

Overload (2) returns IFlowBuilder (the parent builder). This is useful when you want to:

  • configure branches inline via branches:
  • then continue chaining on the parent builder (for example, add shared actions after a successful branch calls ThenContinue())

Examples

Simple Menu

csharp
Flow.Create("Main Menu")
    .PlayPrompt("Welcome to Nick Software.")
    .GetCustomerInput("Press 1 for Sales, 2 for Support, or 3 for Billing.")
        .OnDigit("1", sales => sales
            .PlayPrompt("Transferring to Sales.")
            .TransferToQueue("Sales")
            .Disconnect())
        .OnDigit("2", support => support
            .PlayPrompt("Transferring to Support.")
            .TransferToQueue("Support")
            .Disconnect())
        .OnDigit("3", billing => billing
            .PlayPrompt("Transferring to Billing.")
            .TransferToQueue("Billing")
            .Disconnect())
        .OnTimeout(timeout => timeout
            .PlayPrompt("No input received. Goodbye.")
            .Disconnect())
        .OnError(error => error
            .PlayPrompt("An error occurred. Goodbye.")
            .Disconnect())
        .OnDefault(def => def
            .PlayPrompt("Invalid selection. Goodbye.")
            .Disconnect());

With Configuration

csharp
Flow.Create("Account Entry")
    .GetCustomerInput("Please enter your account number followed by the pound key.",
        input =>
        {
            input.TimeoutSeconds = 15;
            input.MaxDigits = 10;
            input.TerminatingDigit = "#";
        })
        .OnDigits(digits => digits
            .SetContactAttributes(attrs =>
            {
                attrs["AccountNumber"] = Attributes.System(SystemAttributes.LastCollectedDigits);
            })
            .InvokeLambda("ValidateAccount"))
        .OnTimeout(timeout => timeout
            .PlayPrompt("We didn't receive your account number.")
            .Disconnect())
        .OnDefault(def => def
            .PlayPrompt("Invalid entry.")
            .Disconnect())
        .OnError(error => error
            .PlayPrompt("An error occurred.")
            .Disconnect());

With Retry Logic

csharp
Flow.Create("PIN with Retry")
    .Loop(3, loop => loop
        .WhileLooping(attempt => attempt
            .GetCustomerInput("Please enter your PIN.", input =>
            {
                input.MaxDigits = 4;
                input.TimeoutSeconds = 10;
            })
            .OnDigits(pin => pin
                .InvokeLambda("ValidatePIN")
                    .OnSuccess(success => success
                        .PlayPrompt("PIN accepted.")
                        .TransferToQueue("Authenticated")
                        .Disconnect())
                    .OnError(error => error
                        .PlayPrompt("Invalid PIN. Please try again.")))
            .OnTimeout(timeout => timeout
                .PlayPrompt("No input received. Please try again."))
            .ThenContinue())
        .WhenDone(maxAttempts => maxAttempts
            .PlayPrompt("Maximum attempts reached. Goodbye.")
            .Disconnect()));

With Lex Bot (ASR)

csharp
Flow.Create("Voice Menu")
    .GetCustomerInput("How can I help you today?")
        .WithLexBot(lex =>
        {
            lex.BotName = "CustomerServiceBot";
            lex.BotAlias = "$LATEST";
            lex.Locale = "en_US";
        })
        .OnIntent("OrderStatus", orderStatus => orderStatus
            .PlayPrompt("Let me check your order status.")
            .InvokeLambda("GetOrderStatus"))
        .OnIntent("ReturnItem", returnItem => returnItem
            .PlayPrompt("I can help you return an item.")
            .TransferToQueue("Returns"))
        .OnNoMatch(noMatch => noMatch
            .PlayPrompt("I didn't understand. Let me transfer you to an agent.")
            .TransferToQueue("General"))
        .OnError(error => error
            .PlayPrompt("An error occurred.")
            .Disconnect());

Sequential ASR to DTMF Fallback

csharp
Flow.Create("Sequential Input")
    .GetCustomerInput("Say or press 1 for Sales, 2 for Support.")
        .WithSequentialInput(
            asrPrompt: "I can help with Sales or Support. Which would you like?",
            dtmfPrompt: "Press 1 for Sales, or 2 for Support.",
            lexBotName: "MenuBot",
            maxDigits: 1,
            fallbackTriggers: FallbackTrigger.AnyError)
        .OnDigit("1", sales => sales.TransferToQueue("Sales").Disconnect())
        .OnDigit("2", support => support.TransferToQueue("Support").Disconnect())
        .OnIntent("Sales", sales => sales.TransferToQueue("Sales").Disconnect())
        .OnIntent("Support", support => support.TransferToQueue("Support").Disconnect())
        .OnTimeout(t => t.Disconnect())
        .OnError(e => e.Disconnect())
        .OnDefault(d => d.Disconnect());

Complex Authenticated Menu

csharp
private static void BuildAuthenticatedMenu(IFlowBuilder flow)
{
    flow.PlayPrompt($"Welcome {Attributes.External("CustomerName")}. You are now authenticated.")
        .GetCustomerInput(
            promptText: """
                To check your balance, press 1.
                To check your orders, press 2.
                To speak to an agent, press 3.
                """,
            branches: input => input
                .OnDigit("1", balance => balance
                    .PlayPrompt($"Your balance is {Attributes.External("Balance")} dollars.")
                    .ThenContinue())
                .OnDigit("2", orders => orders
                    .InvokeLambda("GetOrders")
                        .OnSuccess(s => s.PlayPrompt("You have 3 active orders."))
                        .OnError(e => e.PlayPrompt("Could not retrieve orders."))
                    .ThenContinue())
                .OnDigit("3", agent => agent
                    .PlayPrompt("Transferring to an agent.")
                    .TransferToQueue("Support")
                    .Disconnect())
                .OnTimeout(timeout => timeout
                    .PlayPrompt("No selection received. Goodbye.")
                    .Disconnect())
                .OnError(menuError => menuError
                    .PlayPrompt("An error occurred. Goodbye.")
                    .Disconnect())
                .OnDefault(def => def
                    .PlayPrompt("Invalid selection.")
                    .ContinueAt("AuthMenu")),
            configure: action => action.TimeoutSeconds = 10,
            identifier: "AuthMenu")
        .GetCustomerInput(
            promptText: "Press 1 to return to the menu, or 2 to disconnect.",
            branches: input => input
                .OnDigit("1", returnMenu => returnMenu.ContinueAt("AuthMenu"))
                .OnDigit("2", disconnect => disconnect.Disconnect())
                .OnDefault(d => d.Disconnect())
                .OnTimeout(t => t.Disconnect())
                .OnError(e => e.Disconnect()),
            configure: action => action.TimeoutSeconds = 5,
            identifier: "AuthMenuPostAction");
}

Branch Continuation

csharp
Flow.Create("Menu with Continuation")
    .GetCustomerInput(
        promptText: "Press 1 or 2",
        branches: input => input
            .OnDigit("1", one => one
                .SetContactAttributes(attrs => attrs["Selection"] = "Option1")
                .ThenContinue())
            .OnDigit("2", two => two
                .SetContactAttributes(attrs => attrs["Selection"] = "Option2")
                .ThenContinue())
            .OnDefault(d => d.Disconnect())
            .OnTimeout(t => t.Disconnect())
            .OnError(e => e.Disconnect()),
        configure: action => action.TimeoutSeconds = 5,
        identifier: "menu")
    .TransferToQueue("General")
    .Disconnect();

AWS Connect Block Type

This block generates the GetParticipantInput action type in the exported flow JSON.

Input Types

TypeDescriptionUse Case
DTMFKeypad digit inputMenu selection, account numbers
ASRAutomatic Speech RecognitionNatural language input
SequentialASR with DTMF fallbackBest user experience

Best Practices

  1. Always handle all branches - Include OnTimeout, OnError, and OnDefault
  2. Keep menus simple - Maximum 4-5 options per menu
  3. Set appropriate timeouts - 5-10 seconds for simple selections
  4. Use retry loops - Allow multiple attempts for complex input
  5. Provide clear prompts - Tell customers exactly what to press
  6. Use ThenContinue() - When branches should converge

See Also

Preview release - Licensing terms TBD before 1.0