Address Book
A device can give the server its address book, so that the people in it who use the service appear among the contacts — at once, and whenever one of them signs up later. Only numbers that belong to accounts ever come back; the rest wait on the server, unseen, to be matched when their owners join.
An address book belongs to the device, that is, to the session that uploaded it. Two phones of one account keep a book each, and the people found are those of both. A book is deleted when its session ends.
Upload Changes
The client sends what changed since it last synchronized:
{"id":"book-1","type":"phonebook.update","data":{"add":[{"phone":"+79161234567","name":"Ivan Petrov"},{"phone":"+79031234567","name":"Mom"}],"remove":["+79261234567"]}}
{"id":"book-1","type":"phonebook.update","ok":true,"data":{"hash":"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08","count":212,"matches":[{"phone":"+79161234567","added":true,"user":{"user_id":67890,"nick":"Johnny","first_name":"John","last_name":"Doe","about":"Hello!","gender":"male","avatar_hash":"a1b2c3d4"}}]}}
| Field | Type | Description |
|---|---|---|
reset |
boolean | Optional: empty the device's book before the rest is applied |
add |
array | Entries to add, or to update when the number is there already: phone in E.164 form and the name the book shows for it |
remove |
array of strings | Numbers to take out |
hash |
string | Digest of the device's book after the change, see Keeping in Step |
count |
number | Entries in the device's book |
matches |
array | Entries of add whose numbers belong to accounts the caller may find: the phone, the account's public card in user — the fields of a user.search result — and added when this request put the person in the contact list |
A request carries at most 500 entries, add and remove together; a larger book
is uploaded in several requests, the first of them with reset. A request with a
number not in E.164 form, with a number twice, or with a name longer than 128
characters or holding control characters returns invalid_format.
A person found is added to the contact list under the entry's name — or their
own nick when the entry has none — the first time any of the account's books
finds them, and the account's devices receive contact.added, with the
phone that found them, in their account stream.
Someone already in the list keeps the name they have there. Someone the user
removes from the list is not brought back by an address book; adding them by
hand still works.
A number is not matched when its account does not want to be found by the
caller (its phone_discovery setting), when the two are separated by a block,
and when it is the caller's own. A response never contains a number the request
did not.
Keeping in Step
hash lets the client check that the server holds the book the client thinks
it uploaded. It is the lowercase hex SHA-256 of the entries sorted by phone,
each written in UTF-8 as the number, a line feed, the name and a line feed; an
empty book hashes the empty string. The client computes the same over what it
believes it uploaded:
- while the two agree, it sends only what changes in the address book;
- when they differ — the app was reinstalled, a request was lost — it uploads
the whole book again, starting with
reset.
phonebook.get returns the same hash and count without changing anything,
for a check at startup:
{"id":"book-2","type":"phonebook.get"}
{"id":"book-2","type":"phonebook.get","ok":true,"data":{"hash":"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08","count":212}}
The client normalizes numbers to E.164 before hashing or sending them, leaves out those it cannot, and keeps one entry per number.
Clear
{"id":"book-3","type":"phonebook.clear"}
{"id":"book-3","type":"phonebook.clear","ok":true}
Deletes the device's book, as when the person withdraws the app's access to it. Contacts the book added stay in the list.
People Who Join Later
When a number in a book comes to belong to an account — its owner signs up, or
sets it with phone.set — and that account lets the book's owner find it, the
person is added to the book owner's contact list as above. The book owner's
devices receive contact.added with the phone that matched, and sessions
without an active connection get a joined push.
Storage and Limits
The server keeps book entries — numbers and names — including those of people who have no account, because finding them when they join is what the book is for. Entries are used for nothing else and are deleted with the entry, the book or its session.
A device's book holds at most 5000 entries; adding past that returns
invalid_state. An account adds at most 10000 entries a day across its devices,
so a reinstall or two do not run out, while trying numbers at random would take
very long; past the limit phonebook.update returns rate_limited with
retry_after. Numbers are sent as they are: there are few enough phone numbers
to hash every one of them, so hashing would hide nothing, and the protection
lies in these limits.