# Phone sign-in from any country: make the same change in the app (2026-10-22)

**For:** the mobile app developer. On the website, the customer can now pick **any country** (243) for the phone number
they sign in with by WhatsApp code. Before, only 8 countries were offered. Please make the same change in the app.
This file describes what the website does (§1), what to change in the app (§2), the endpoints (§3) and a test list
(§4). The OTP flow itself is unchanged; see `docs/doc-1/07-app-otp-api-changes.md`.

**Server:** the endpoints keep their URLs, fields and answers, so current app builds keep working. One server change
matters to the app. Until now the server could only send a code to the 8 countries. A number from any other
country got `500 "Unable to send OTP"`. After the website release it gets the code. **Release the app change after
the website release**, or customers would pick a new country and get no code.

---

## 1. What the website does now (copy this)

| | Before | Now |
|---|---|---|
| Countries | 8: Syria, UAE, Saudi Arabia, Jordan, Lebanon, Turkey, USA, Palestine | All 243 (the standard libphonenumber / intl-tel-input list) |
| Default | Syria | Syria (unchanged) |
| Order | the 8 | The 8 usual countries first, in this order: **SY, AE, SA, JO, LB, TR, US, PS**, a thin divider, then every other country A–Z by English name |
| Country names | none | **Arabic in the Arabic app** (`ألمانيا`), English in the English app (`Germany`). The rest of the list is sorted by the name shown, so Arabic alphabetical order in Arabic |
| Row | flag, `SY +963` | flag, `SY +963`, the country name in grey (`سوريا` / `Syria`) |
| Search | none | A search box at the top of the list. In either language it matches the Arabic name, the English name, the country's own name (`Deutschland`), the ISO code (`DE`) or the dial code (`+49`, `49` or `0049`). Arabic is compared without hamza and diacritics, so `المانيا` finds `ألمانيا` and `الامارات` finds `الإمارات` (أ إ آ → ا, ة → ه, ى → ي) |
| No match | | the text "No country found" (ar: `لا توجد دولة بهذا الاسم`) |
| Search placeholder | | "Search country" (ar: `ابحث عن الدولة`). In the Arabic app the search box is right-to-left (placeholder and typing on the right) |
| Enter in the search box | | picks the first country shown (does not submit the form) |

The selected country is shown on the field as flag + `ISO +dial` (e.g. `DE +49`), as before.

---

## 2. What to change in the app

1. **Country picker: every country,** with the order, default and search of §1. If the app uses a package
   (`intl_phone_field`, `country_code_picker`, …), this usually means removing its "only these countries" option and
   setting its "favourites/preferred" option to the 8 countries above.
2. **Arabic country names in the Arabic app.** Most picker packages ship Arabic names (set the picker's locale /
   language to `ar`). Otherwise the standard CLDR Arabic names are the ones the website uses. The website shortens
   these to the names people use; please do the same:

   | ISO | CLDR name | Show |
   |---|---|---|
   | PS | الأراضي الفلسطينية | **فلسطين** |
   | SA | المملكة العربية السعودية | **السعودية** |
   | AE | الإمارات العربية المتحدة | **الإمارات** |
   | HK | هونغ كونغ الصينية (منطقة إدارية خاصة) | **هونغ كونغ** |
   | MO | منطقة ماكاو الإدارية الخاصة | **ماكاو** |
   | MM | ميانمار (بورما) | **ميانمار** |
   | CC | جزر كوكوس (كيلينغ) | **جزر كوكوس** |

   The full list (ISO, dial code, English, local and Arabic name) is in the backend file
   `app/Support/PhoneCountries.php` if you want to copy it as is.
3. **Send the number in clean E.164**, as libphonenumber formats it: `+` + dial code + national number, **without the
   national trunk `0`**:

   | Customer types | Country | Send `phone` |
   |---|---|---|
   | `0944 123 456` | Syria | `+963944123456` |
   | `0151 1234 5678` | Germany | `+4915112345678` |
   | `07911 123456` | United Kingdom | `+447911123456` |
   | `050 123 4567` | UAE | `+971501234567` |

   This matters more now. The server removes a trunk `0`, or a dial code typed twice, **only for the 8 usual
   countries**. For any other country it keeps the number exactly as sent. So `+49015112345678` would send the code
   to a wrong number and save the account with it.
4. **Send the chosen country's ISO code as `country_code`** (2 letters, e.g. `"DE"`) on `send-otp`. It is optional,
   but please send it. Without it the server works the country out from the dial code. For a dial code several
   countries share, it then assumes the main one:

   | Dial code | Without `country_code` the server assumes | Also used by |
   |---|---|---|
   | `+1` | US | Canada, Caribbean islands |
   | `+7` | RU | Kazakhstan |
   | `+44` | GB | Guernsey, Jersey, Isle of Man |
   | `+61` | AU | Christmas Island, Cocos Islands |
   | `+39` | IT | Vatican |

   A `country_code` that is not 2 letters (e.g. `"963"`) is ignored, and the dial code is used, as today.
5. **Check the number on the phone before sending**, for the chosen country (libphonenumber `isValidNumber`). If it
   is not valid, show "Please enter a valid phone number" and send nothing. The website does the same.

Nothing else changes: the code screen, `verify-otp`, registration, login and the error messages stay as they are.

---

## 3. The endpoints (same contract)

### `POST /api/v2/send-otp`

| Field | Required | Value |
|---|---|---|
| `phone` | yes | E.164, e.g. `+4915112345678` |
| `country_code` | no (please send it) | ISO alpha-2, e.g. `DE` |

The answers are unchanged:

- `200 { "success": true, "phone": "<canonical phone>", "message": "..." }`
- `422` for an invalid number
- `429` for too many sends
- `500` for "Unable to send OTP. Please try again."

**Length (unchanged):** after normalising, the phone must be **10 to 20 characters, the `+` included**. A few tiny
territories with very short numbers are still refused: Saint Helena, Niue, Tokelau and the Falkland Islands. Every
other country fits.

### `POST /api/v2/verify-otp` and `POST /api/v2/auth/register`

Unchanged. Send the same `phone` you sent to `send-otp` (or the canonical `phone` it answered with).

`auth/register` already accepts any international number (`^\+[1-9]\d{6,14}$`). Its error **text** for an invalid
phone still says "starting with +963 followed by 9 digits", but the rule itself accepts every country.

---

## 4. Test list

| # | Steps | Expected |
|---|---|---|
| 1 | Open sign-in in the English app | Syria selected. The list starts with the 8 usual countries, then a divider, then Afghanistan, Albania, … |
| 2 | Open sign-in in the Arabic app | Arabic names: سوريا، الإمارات، السعودية … فلسطين, then a divider, then إثيوبيا، أذربيجان، أرمينيا … (Arabic order) |
| 3 | Search `germ`, `DE`, `+49`, `0049` and `Deutschland` | Germany is found each time, in both languages |
| 4 | Search `ألمانيا`, `المانيا`, `الامارات` and `سوريا` | Germany, the UAE and Syria are found, in both languages |
| 5 | Search `zzzz` | "No country found" / `لا توجد دولة بهذا الاسم` |
| 6 | Pick Germany, type `0151 1234 5678`, send | Request carries `phone: +4915112345678` and `country_code: DE`. The answer is `200` and the WhatsApp code arrives |
| 7 | Verify the code, register | Account created with `+4915112345678`. Signing in again with the same number finds it |
| 8 | Pick Canada, send a Canadian number | `country_code: CA` is sent and the code arrives |
| 9 | A Syrian number as before (`0944 123 456`) | Unchanged: `+963944123456`, and the code arrives |
| 10 | Pick Germany, type a Syrian number | Refused on the phone as invalid for Germany. No request is sent |
