Introduction
© 2006 - 2025 LEKAB Communication Systems AB. Version 5.1.201, 2025-04-28.
The messaging platform includes many features for keeping the address book up to date and in sync with external systems or directories. It is possible to import users and groups from Microsoft Azure Entra ID using the Graph API or import lists of contacts from .CSV or Excel files regularly from a shared folder via SFTP.
This API provides complete control of how the address book is kept up to date from an
external system by providing a Restful API with full access to the contacts.
The Web Service accepts HTTP GET
, HTTP POST
, HTTP PUT
or HTTP DELETE
requests when working with contacts and address books in the messaging platform.
Both the GET
and the POST
versions return responses in the HTTP
response body as
a json document. Deleting contacts use the DELETE verb and updating expects PUT.
Some endpoints supports the same function with GET
and POST
, but
in the GET
case, parameters are given in the calling URL
(after a ?
sign, separated by &
signs) , while in the POST
case the parameters are
given in a json document in the HTTP POST
request body. UTF-8
encoding
is assumed in all HTTP
bodies.
The format of the input and output json documents and the input url parameters are described in this manual.
Metadata and contact properties
The endpoint /listtags
can be used to present metadata used in the address
book to users of the custom application you are building. These tags can later
be used when sending messages by calling the REST SMS API. For example, if
users see that there is a tag type called Group and values A, B and C, they
can choose to send messages to all contacts that belong to group A.
If another tag type is called City, the user can select one of multiple
values and send messages to the matching contacts. It is possible to combine
multiple tags to offer powerful and flexible addressing.
Address book name and ID
The endpoint /listaddressbooks
will show which address books the API user
has access to. The unique id of the address book is later used in other API
calls to make sure that the correct address book is being modified. The name
of an address book might be changed at any time by a user in the web portal.
It is important to use the ID which is static and remains the same over time.
Not all address books visible to a user have proper names, and may instead be identified only as a certain user’s or organizational unit’s or company’s address book. The endpoint for listing addressbooks is intended to allow presentation of the available addressbooks to a human user for selecting the corresponding numeric id of the addressbook. The numeric id is then used with the other endpoints to specify which addressbook to operate on. The endpoint for listing tags gives a comprehensive list of all tag types and tag values in the address book, with counts for the number of occurrences.
Different authentication methods available for GET requests
The POST
requests all use authentication by giving username and password
in the corresponding fields in the JSON
document which is sent in the
(automatically HTTPS = SSL/TLS
encoded) HTTP
request body.
For GET
requests we offer three different ways of supplying these
credentials:
-
Username and password can be sent in the
U
andP
url parameters -
Username and password can be given in the HTTP headers,
X-Lekab-Userid
andX-Lekab-Password
, respectively. The values have to be theBase64
encoding of (aUTF-8
byte array representation of) the username or password to allow non-US-ASCII characters. Here testuser will be encoded asdGVzdHVzZXI=
and testpass asdGVzdHBhc3M=
-
Username and password can be given as Basic authentication, i.e, the header
Authorization
should have the valueBasic token
, where the token is theBase64
encoding of (aUTF-8
byte array representation of)username:password
. Heretestuser:testpass
will be encoded asdGVzdHVzZXI6dGVzdHBhc3M=
and theAuthorization
header will have the valueBasic dGVzdHVzZXI6dGVzdHBhc3M=
1. Modifying contacts in the address book
It is possible to List, Add, Delete and Update contacts in the address book.
When the external application is the master data source, it usually keeps a unique ID for each contact. This ID is used when saving a contact in the address book for the first time and later, to find, update or delete it.
A complete contact object with all properties should be provided by the calling
application when using endpoints /addcontact
and /updatecontact
. It is not
possible to update only specific parts of a contact, for example one of the
addresses or one tag value. Applications should retrieve the whole contact,
change whatever is needed and send it back to update. The complete contact object
is returned in the JSON body when using /getcontact
and /findcontactbyaddress
.
This makes it easy to modify the existing object before sending it back.
The process is simple:
-
Get a contact using the unique id (or by iterating through a search result).
-
Compare the content against your master data and change whatever is needed in the JSON structure.
-
Call
/updatecontact
and pass the modified JSON in the body. The same external id is used to find and update the existing contact.
2. Use cases for the address book API
One scenario could be that the security policy prevents granting read access to users and groups in Azure which is required by the Graph API. That means the polling for changes in Entra ID initiated from the messaging platform cannot be used. Instead, the address book API can be used to push changes initiated from the other directory. The customer builds their own integration and updates the address book in the messaging platform without sharing any access tokens or privileges to their Azure tenant.
The call to Address Book API can be added in a custom authentication flow where users request access to the Azure Groups used to subscribe to messages from the messaging platform. The Office 365 Groups connector for Power Platform and Azure Logic Apps has the OnGroupMembershipChange event that could be used to trigger events that update the address book.
Any SQL database or directory source can be integrated using the API in a similar way.
2.1. Opt-in to a group in Azure
-
A user request to join "Group A" in Azure and a flow is triggered.
-
A manager grants access for the user. The unique Azure user object id and group name are known (if only group id is known, lookup the group name so it can be used as tag value later).
-
The Address Book API is called:
-
Check if a contact already exist with the Azure user object id using
/getcontact
. -
If the object id exists in the address book:
-
Update the tag type "Groups" and add the value "Group A".
-
Optionally, update the name and the mobile number in the SMS address, as well as the EMAIL address type.
-
Optionally, update other tag types such as City, Country, Street, etc. This could be useful when filtering and addressing.
-
Save the contact with a call to
/updatecontact
. It will overwrite the existing becaues it has the same contactid.
-
-
Else, if the object id does not exist in the address book:
-
Create a new contact with a contact id equal to the Azure user object id.
-
Add the name and the mobile phone as SMS address (also add the EMAIL address type if needed).
-
Add "Group A" as the value to the "Groups" tag type.
-
Optionally, add other tag types such as City, Country, Street, etc. This could be useful when filtering and addressing.
-
Save the contact with a call to
/addcontact
.
-
2.2. Opt-out from a group in Azure
-
Someone is removed from "Group A" and a flow is triggered. The unique Azure user object id and group name are known (if only group id is known, lookup the group name so it can be used as tag value later).
-
The Address Book API is called:
-
Check if a contact already exist with this object id using
/getcontact
. -
If the contact with the id exists it is returned as a JSON object in the response:
-
Locate and update the tag type "Groups" and remove the value "Group A".
-
If other values remain in the "Groups" tag, keep them.
-
Save the changes to the existing contact using
/updatecontact
. It will overwrite the existing becaues it has the same contactid.
-
-
if "Group A" was the only value in "Groups":
-
Delete the whole contact using
/deletecontact
(unless the address book is used also for other use cases).
-
-
3. The /listaddressbooks
endpoint
Not all address books, to which a user has reading rights, have proper names. They may instead be identified only as a certain user’s or organizational unit’s or company’s address book. This endpoint is intended to allow the presentation of available address books to a human user, who can thereby find the numeric id of the requisite address book. The numeric id is then used with the other endpoints to specify which address book to operate on. If no numeric id is given in the other endpoints, the default address book of the user calling the web service is assumed.
3.1. GET request example e.g. from web browser
GET https://secure.lekab.com/addressbook/api/listaddressbooks?U=doggykennel&P=testpass
3.2. POST request example, probably from an application
https://secure.lekab.com/addressbook/api/listaddressbooks
With the contents of the HTTP body:
{"username":"doggykennel","password":"testpass"}
3.2.1. Explanation of parameters
POST json key | GET query param | json value (strings quoted) | query param value (strings without quotes) | |
---|---|---|---|---|
username |
U |
string |
string |
username of the API account in the service |
password |
P |
string |
string |
password of the API account in the service |
3.2.2. HTTP response
A successful request will return 200 OK and a json document of the following format. If the user does not present proper login credentials or cannot read any address books, a 401 Unauthorized will be returned, with no json document.
{ "addressbooks" : [
{ "id" : 576978287400472577,
"name" : "Kennel Company - Shared address book" },
{ "id" : 646802963557457921,
"name" : "Doggy Kennel - Private address book" },
{ "id" : 646802966493470722,
"name" : "Kennel Club Members" }]
}
while the alphanumeric recipient number was rejected.
3.2.3. Explanation of response
POST json key | json value (strings quoted) | |
---|---|---|
addressbooks |
json list of json documents |
list of address book items never empty because no accessible address books gives HTTP 401 |
id |
json long integer |
numeric id of this address book item |
name |
string |
name of this address book item |
3.2.4. Example Python 3 code for the /listaddressbooks
endpoint
import json
import requests
bookreq = {"username" : "doggykennel", "password": "testpass"}
bookreq_json = json.dumps(bookreq)
bookurl = 'https://secure.lekab.com/addressbook/api/listaddressbooks'
response = requests.post(bookurl, data=bookreq_json)
bookresp = response.json()
for a in bookresp["addressbooks"]:
print(a["name"] + " has numeric id " + a["id"])
will output
Kennel Company - Shared address book has numeric id 576978287400472577
Doggy Kennel - Private address book has numeric id 646802963557457921
Kennel Club Members has numeric id 646802966493470722
4. The /listtags
endpoint
A user, team or a company, can have an address book in the messaging
platform, with contacts that each has a phonenumber that can
receive SMS messages. These contacts can be marked with tags
consisting of a tag type and a tag value, here often written separated
by a colon character. For instance, a contact can be
marked with the tag Base:STO
if the person is based in Stockholm.
Here Base
is the tag type and STO
is the tag value.
The same contact can have many tags, for instance Group:Management
or On call:Yes
. Which tags types and tag values are used is up to
the user/company, but they should preferably consist of letters and
numbers, and can especially not contain the characters ;
, |
or
:
. The tags are used in several parts of the service to
select addressees for messages using, so called, tag filters.
The /listtags
endpoint is used to retrieve a comprehensive listing
of all tags in a given address book, with counts for the number of
occurrences.
4.1. GET request example e.g. from web browser
GET https://secure.lekab.com/addressbook/api/listtags?U=doggykennel&P=testpass&A=646802966493470722
4.2. POST request example, probably from an application
https://secure.lekab.com/addressbook/api/listtags
with the contents of the HTTP body:
{
"username" : "doggykennel",
"password" : "testpass",
"addressbookid" : 646802966493470722
}
4.2.1. Explanation of parameters
POST json key | GET query param | json value (strings quoted) | query param value (strings without quotes) | |
---|---|---|---|---|
username |
U |
string |
string |
username of the API account in the service |
password |
P |
string |
string |
password of the API account in the service |
addressbookid |
A |
json long integer |
number |
id of the addressbook where tags are counted (optional, defaults to user’s default address book) |
4.2.2. HTTP response
A successful request will return 200 OK and a json document of the following format.
{ "tags" : [ { "type" : "Breed",
"typecount" : 250,
"values" : [ { "value" : "German shepherd", "count" : 150 },
{ "value" : "Labrador retriever", "count" : 57 },
{ "value" : "Mutt", "count" : 43 } ] },
{ "type" : "Dog show newsletter",
"typecount" : 104,
"values" : [ { "value" : "Yes", "count" : 104 } ] } ],
"addressbookid" : 646802966493470722,
"addressbookname" : "Kennel Club Members" }
4.2.3. Explanation of response
POST json key | json value (strings quoted) | |
---|---|---|
addressbookid |
json long integer |
the id of the address book searched |
addressbookname |
string |
name of the address book searched |
tags |
json list of json documents |
one type item per tag type |
type |
string |
tag type in this type item |
typecount |
integer |
number of tags with this tag type in the addressbook |
values |
json list of json documents |
one value item per tag value |
value |
string |
tag value in this value item |
count |
integer |
number of tags with this tag value and tag type in the addressbook |
4.2.4. Example Python 3 code for the /listtags
endpoint
import json
import requests
tagsreq = {"username" : "doggykennel", "password" : "testpass", "addressbookid" : 646802966493470722}
tagsreq_json = json.dumps(tagsreq)
tagsurl = 'https://secure.lekab.com/addressbook/api/listtags'
response = requests.post(tagsurl, data=tagsreq_json)
tagsresp = response.json()
print("Listing tags in " + tagsresp["addressbookname"])
for a in tagsresp["tags"]:
print(a["type"] + " occurs " + str(a["typecount"]) + " times, with " + str(len(a["values"])) + " different values")
will output
Listing tags in Kennel Club Members
Breed occurs 250 times, with 3 different values
Dog show newsletter occurs 104 times, with 1 different values
5. Finding existing contacts with filters
5.1. The /getcontact
endpoint
Find a contact with a specific external id, for example Azure Object ID:
GET https://secure.lekab.com/addressbook/api/getcontact?contactid=f32ca8c1-63ed-4a1e-ad2c-e88157c7e991
5.2. The /findcontactbyaddress
endpoint
Find contacts with a specific mobile number in the SMS address (usually only one but there could be duplicates):
GET https://secure.lekab.com/addressbook/api/findcontactbyaddress?addresstype=SMS&address=46701234567
Find all contacts that can receive SMS messages because they have that address type:
GET https://secure.lekab.com/addressbook/api/findcontactbyaddress?addresstype=SMS
Find all contacts that can receive VOICE calls with Text-to-speech conversion or using MP3 playback:
GET https://secure.lekab.com/addressbook/api/findcontactbyaddress?addresstype=VOICE
Find all contacts that can receive E-mails:
GET https://secure.lekab.com/addressbook/api/findcontactbyaddress?addresstype=EMAIL
Find all contacts that are configured with a custom iOS or Android app address for push notifications:
GET https://secure.lekab.com/addressbook/api/findcontactbyaddress?addresstype=APP
Find contacts with a specific address, regardless of type. For example, check if a phone number exist either as SMS or VOICE type
GET https://secure.lekab.com/addressbook/api/findcontactbyaddress?address=46701234567
6. List all contacts created or modified after a specific time
Sometimes it is useful to keep track of modifications since the last time a scheduled task was performed. Contacts in the address book have properties for created time and updated time. Note that a contact can be updated by a user in the web portal. This will change the updated timestamp. There is also a field with the information about who made the update.
The time format used in GET is YYYY-MM-DDTHH:MM:SS+0100 and must be URL-encoded. A time zone can be added, for example: YYYY-MM-DDTHH:MM:SS+0100
It is possible to specify the specific address book to search, by adding the id
to the request. The /listaddressbooks
endpoint is used to find the id.
Find all contacts created after a specific date/time. Search in all address books the api user has access to (no address book id appended to the uri path):
GET https://secure.lekab.com/addressbook/api/contacts/createdafter/2025-03-30T00%3A00%3A00%2B0100/
Find all contacts created after 2025-03-30 in a specific address book. The addressbook id 1086241428642066431 is added at the end:
GET https://secure.lekab.com/addressbook/api/contacts/createdafter/2025-03-30T00%3A00%3A00%2B0100/1086241428642066431
Find all contacts modified after 2025-03-30, in all address books the api user has access to:
GET https://secure.lekab.com/addressbook/api/contacts/modifiedafter/2025-03-30T00%3A00%3A00%2B0100/
Find all contacts modified after 2025-03-30 in a specific address book. The addressbook id 1086241428642066431 is added at the end:
GET https://secure.lekab.com/addressbook/api/contacts/modifiedafter/2025-03-30T00%3A00%3A00%2B0100/1086241428642066431
7. The /addcontact
endpoint
Adding a contact uses the POST verb. The contact object is sent in the body as a JSON document. The contact has some general properties such as Name and Company. The unique contactid is important when you plan to search for and update the contact at later time. The Addresses and Tags are lists.
The address types can be SMS, EMAIL, VOICE or APP. When using SMS and VOICE, make sure that the phone number in the address field is a complete number including international prefix. Do not use a plus "+". Please refer to the E.164 standard for more information about phone number format.
To add a contact with a specific external Azure Object ID:
POST https://secure.lekab.com/addressbook/api/addcontact
{
"addressbookid": "925406391282233345",
"contactid": "f32ca8c1-63ed-4a1e-ad2c-e88157c7e991",
"contactname": "Eva Nilsson",
"companyname": "Test company",
"addresses": [
{
"addresstype": "SMS",
"address": "46701234567"
},
{
"addresstype": "VOICE",
"address": "46701234567"
},
{
"addresstype": "EMAIL",
"address": "eva.nilsson@test.company.xyz"
}
],
"tags": [
{
"tagtype": "Groups",
"tag": "Group A"
},
{
"tagtype": "City",
"tag": "Stockholm"
}
]
}
8. The /updatecontact
endpoint
Updating a contact uses the PUT verb. The contact object is sent in the body as a JSON document.
For information about the JSON body, please refer to /addcontact
.
To update a contact with a specific external Azure Object ID:
PUT https://secure.lekab.com/addressbook/api/updatecontact
{
"addressbookid": "925406391282233345",
"contactid": "f32ca8c1-63ed-4a1e-ad2c-e88157c7e991",
"contactname": "Eva Nilsson",
"companyname": "Test company",
"addresses": [
{
"addresstype": "SMS",
"address": "46701234567"
},
{
"addresstype": "VOICE",
"address": "46701234567"
},
{
"addresstype": "EMAIL",
"address": "eva.nilsson@test.company.xyz"
}
],
"tags": [
{
"tagtype": "Groups",
"tag": "Group A"
},
{
"tagtype": "City",
"tag": "Stockholm"
}
]
}
9. The /deletecontact
endpoint
Deleting a contact uses the DELETE verb. The contactid is sent in the body as a JSON document.
To delete a contact with a specific external Azure Object ID:
DELETE https://secure.lekab.com/addressbook/api/deletecontact
{
"addressbookid": "925406391282233345",
"contactid": "f32ca8c1-63ed-4a1e-ad2c-e88157c7e991"
}
Note: The address Book ID is optional but recommended. The default address book of the
API user is used if the parameter is missing. To list all address books the api user has
access to, please refer to the /listaddressbooks
endpoint.
10. The /deleteallcontacts
endpoint
Warning – use with caution. This request will empty the address book by deleting all contacts. In many scenarios, the application using the API is keeping track of changes and updates only specific contacts based on their id or date/time last modified. However, in some cases the application might just want to empty the address book and add all contacts at once. For this purpose, the delete all endpoint was added.
Note that tag filters in the address book remain after deleting all contacts.
For example, if users in the web portal have prepared addressing filters for contacts
matching tag type City=Stockholm and Department=Sales, these filters remain and will
become useful again when the new contacts are added. Usually the deleteallcontacts call is
followed by calls to /addcontact
within a few seconds and will not interfer with users who
are logged in and sending messages. However, if the process is adding thousands of conects
and takes some time, it should be scheduled at night-time. Updating individual contacts
instead of "delete all - add all" always cause less disturbance if users are expecteds to be
active 24/7.
To delete all contacts in the address book with id 925406391282233345:
DELETE https://secure.lekab.com/addressbook/api/deleteallcontacts?addressbookid=925406391282233345
Note: The address Book ID is mandatory when deleting all contacts.
To list all address books the api user has access to, please refer
to the /listaddressbooks
endpoint.