---
title: "Use Case 5: Phone normalization"
description: "Custom Action Jail action: raw_phone → normalized_phone, success and error edges, self-check of three UA number formats."
---

# Use Case 5: Phone number format

**Level:** basic · **Modules:** Scenario Builder, Action Jail · **Action:** custom Action Jail action

## Required permissions and access

| What you need | Where in the menu | Why |
|---------------|-------------------|-----|
| **Scenario Builder** | Menu → Scenario Builder | WaitForInput, call the custom action |
| **Action Jail** | Menu → Action Jail | Create and test the JS action |

If a section is missing from the menu — check your account permissions or contact ConnectiveOne support.

## Business context

The customer enters a phone in different formats (`0800…`, `380…`, `+380…`) — CRM, Registered Users, and API need a single format `+380XXXXXXXXX`.

## Expected result

- Action Jail action: input `raw_phone` → output `normalized_phone`.
- Call from the scenario → show the normalized number to the customer.
- Invalid input → edge **error** and a retry prompt (not silence).

## Flow architecture

```text
WaitForInput (raw_phone) → Action (custom Action Jail action)
   ├─ success → MessageKeyboard “Your number: {{normalized_phone}}”
   └─ error   → “Invalid format” → loop to WaitForInput
```

## Step-by-step implementation

### Step 1. Action Jail — new action

Action Jail → **Create action** (you can use AI generation with the prompt below).

**Action contract (what the code must do):**

| Input (from scenario) | Output | Logic |
|-----------------------|--------|-------|
| `raw_phone` (string) | `normalized_phone` | Strip spaces/parentheses; if 10 digits starting with `0` — prepend `+38`; if already `+380…` — keep |
| — | event `error` | If fewer than 10 digits or not like a UA number |

**Prompt for AI generation (example):**  
“Action Jail: normalize a Ukrainian phone to +380XXXXXXXXX. Input `raw_phone`, output `normalized_phone`, return error if invalid.”

**Test in Action Jail (“Testing” tab):**

| raw_phone | Expected |
|-----------|----------|
| `0800123456` | `+380800123456` or `+380…` per your rule |
| `380501234567` | normalizes to `+380501234567` |
| `+380501234567` | unchanged |
| `abc` | error |

---

### Step 2. WaitForInput — raw number

| Parameter | Value |
|-----------|-------|
| messageText | “Enter phone number” |
| outputVariable | `raw_phone` |
| Validation | `phone` or `none` on the first pass |

**Edges:** → Action (custom action).

---

### Step 3. Action — custom action from Action Jail

| node_params | Value | Why |
|-------------|-------|-----|
| `raw_phone` | `{{raw_phone}}` | Pass input from WaitForInput |

*(Parameter names — as in your action form in Inspector.)*

**Edges:**

| Edge | Where | Why |
|------|-------|-----|
| **success** / main | MessageKeyboard “Your number: {{normalized_phone}}” | Show the result |
| **error** | “Invalid format. Try again” → loop to WaitForInput | Do not leave the customer without a reply |

---

### Step 4. MessageKeyboard — result

| Text | `Normalized number: {{normalized_phone}}` |

---

### Step 5 (optional). MessageKeyboard with a URL button

| Parameter | Value | Why |
|-----------|-------|-----|
| Button | Text + **URL** in advanced button settings | No Action Jail for a simple link |
| ActionType | `open-url` (Telegram) | Check in preview / TG |

→ Use Case 11 (advanced level) for broadcast alias and mass sending.

## Acceptance criteria (self-check Runs)

- [ ] `+380XXXXXXXXX` — success, number shown to the customer.
- [ ] `380XXXXXXXXX` — normalizes to `+380…`.
- [ ] `0XXXXXXXXX` — normalizes to `+380…`.
- [ ] Invalid input (`abc`) — edge **error**, message to the customer, option to retry.
- [ ] Run in Runs; optionally — same test in a real channel (Telegram or widget).
- [ ] Edge **error** connected on the canvas.

## Common mistakes

| Symptom | Cause | What to do |
|---------|-------|------------|
| `{{normalized_phone}}` empty | No `return { normalized_phone: '…' }` in the code | Fix Action Jail |
| Always error | Scenario parameter ≠ name in Action Jail | Match node_params and the action form |
| Bot “goes silent” | Edge **error** not connected | Connect error → MessageKeyboard |
| Action Jail test OK, Runs fail | Different action name in the scenario | Select the correct action in Inspector |

## Related documentation

- [Action Jail — integrations](/en/actionjail/how-to/integrator-embed-actions.md)
- [Actions glossary](/en/learn/implementer/training/reference/actions-glossary.md)
- [FAQ — Action Jail](/en/learn/implementer/training/reference/faq.md)
- Next: [Use Case 6 — Registered Users](/en/learn/implementer/training/basic/use-case-06-registered-users.md)
