Adding IoT Devices by Serial Number in Mobile Applications
Adding by serial number — a fallback method for cases when the QR sticker is damaged or missing. The user enters or scans the serial number manually, the system finds the device and binds it to the account. The task is simple in essence but requires careful validation and good UX for the input form.
Serial Number Formats
Serial number — not an arbitrary string. Each manufacturer has its own format:
-
SN-XXXXXXXX— 8 hex characters after prefix -
AAAA-BBBB-CCCC-DDDD— groups of 4 characters (like activation keys) - MAC address as serial number —
AA:BB:CC:DD:EE:FF - Numeric code —
12345678901
The format must be known beforehand — it determines the input mask and validator. If the serial number is always 12 characters, the user shouldn't guess — the field should show the mask and accept only the needed format.
Input Form UI
Key requirements for the serial number field:
Disable autocaps and autocorrect. inputType="textNoSuggestions|textCapCharacters" on Android. On iOS: autocorrectionType = .no, autocapitalizationType = .allCharacters. Autocorrect turns ABC123 into Abc123 — device won't be found.
Input mask. For format XXXX-XXXX-XXXX — insert hyphens automatically as you type. On Android: TextWatcher with cursor position handling:
editText.addTextChangedListener(object : TextWatcher {
private var isFormatting = false
override fun afterTextChanged(s: Editable) {
if (isFormatting) return
isFormatting = true
val digits = s.toString().filter { it.isLetterOrDigit() }.uppercase()
val formatted = digits.chunked(4).joinToString("-").take(14)
s.replace(0, s.length, formatted)
isFormatting = false
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
Camera scanning as alternative to entry. Serial number is often printed as a barcode on the device's back panel. A "Scan" button next to the field. ML Kit or ZXing for Code 128 / Code 39.
Validation Before API Request
Local validation before sending the request:
fun validateSerialNumber(input: String): ValidationResult {
val clean = input.filter { it.isLetterOrDigit() }.uppercase()
return when {
clean.length < 8 -> ValidationResult.TooShort
clean.length > 16 -> ValidationResult.TooLong
!clean.matches(Regex("[A-Z0-9]+")) -> ValidationResult.InvalidChars
else -> ValidationResult.Valid(clean)
}
}
Show validation error inline — under the field, not in an alert. User sees the problem immediately and fixes it without losing entered data.
API: Device Lookup and Binding
Two-step process:
Step 1 — device lookup:
GET /api/devices/lookup?serial=ABC12345678
Response: device type, model, status (available / already bound to another account / doesn't exist). Show the user exactly what was found — "Temperature Sensor model T200" — before confirming binding.
Step 2 — binding:
POST /api/devices/claim
{ "serial": "ABC12345678", "name": "Balcony Sensor" }
Serial number is not a claim token — these are different things. Serial number is public, used to find the device. Binding requires user authentication (JWT in header), otherwise anyone could steal a device.
Error Handling
| Status | Show |
|---|---|
| 404 Not Found | "Device with this serial number not found. Check entry" |
| 409 Conflict | "This device is already bound to another account" |
| 422 Unprocessable | "Invalid serial number format" |
| 503 | "Service temporarily unavailable. Try again later" |
For 409 — offer "Is this your device?" with a support contact button. Otherwise used device buyers will be stuck.
Implementing serial number adding with validation and two-step binding: 1 week. Pricing calculated individually.







