Copy, don't retype
How might a form get your PAN in one tap?
Indian IDs and bank cards as copyable text, on iPhone, iPad and Mac.


Demo Bank•••• 1111
Forms ask for the same numbers every time: PAN, Aadhaar, passport, IFSC. Identité keeps them as text you copy in one tap, behind Face ID. It holds Aadhaar, PAN, passport, voter ID, driving licence, UAN, bank accounts, and credit and debit cards, grouped by person.
How might a form get your PAN in one tap?
How might IDs sync without a server of mine?
How might any card colour still show the bank name and last four?
Forms want the number as text, and scans can't be copied.
Each CVV reveal or copy asks for Face ID again.
A wrong digit in a form costs a trip back to the card.
A past expiry or a number that doesn't fit its format gets a warning; it doesn't block the save.
Your card should look like your card, and still be readable.
Cardy's originals are grey templates, so there's no 'original colours' option.
Tap one to bring it forward and copy any field. Aadhaar, card and account numbers stay masked until you show them.



Aadhaar and VID numbers are checked with the Verhoeff check digit, card numbers with Luhn. PAN, IFSC, passport, voter ID and licence numbers are checked against their formats, and you're warned before saving a card whose expiry has passed. Passports can be scanned, and the scan's check digits are checked too.
case .aadhaarNumber: valid = matches(value, "[2-9][0-9]{11}") && verhoeffIsValid(value)public static func verhoeffIsValid(_ digits: String) -> Bool { verhoeff(digits, offset: 0) == 0 }private static func verhoeff(_ digits: String, offset: Int) -> Int? { guard !digits.isEmpty, digits.allSatisfy({ $0.isASCII && $0.isNumber }) else { return nil } var checksum = 0 for (index, digit) in digits.reversed().enumerated() { checksum = multiplication[checksum][permutation[(index + offset) % 8][digit.wholeNumberValue!]] } return checksum}case .panNumber: valid = matches(value, "[A-Z]{5}[0-9]{4}[A-Z]")private static func matches(_ value: String, _ pattern: String) -> Bool { value.range(of: "\\A(?:" + pattern + ")\\z", options: .regularExpression) != nil}case .cardNumber: valid = matches(value, "[0-9]{12,19}") && luhnIsValid(value)public static func luhnIsValid(_ digits: String) -> Bool { guard !digits.isEmpty, digits.allSatisfy({ $0.isASCII && $0.isNumber }) else { return false } var sum = 0 for (index, digit) in digits.reversed().enumerated() { var number = digit.wholeNumberValue! if index % 2 == 1 { number *= 2; if number > 9 { number -= 9 } } sum += number } return sum % 10 == 0}
Demo Bank•••• 1111

Bank cards come in 37 designs: 30 from Cardy and 7 made for Identité. Each one takes its colours from the scanned card, a preset, or colours you pick.








































Card designs adapted from Cardy by Piqo Design, used under CC BY 4.0.
IDs stay on your devices and sync through your private iCloud, where ID values, names and notes are stored as encrypted fields.