Is InTouchApp Phone Contacts & Data Saver safe?

High risk

InTouchApp is high risk. On WhatsApp Web, InTouchApp injects a script into WhatsApp's page context rather than the usual isolated sandbox. The script reads WhatsApp's internal data store, and AI Reply sends recent chat messages to InTouchApp's servers for a reply.…

Volare Tech. Pvt. Ltd.v4.56.0Chrome Web Store
77Risk
Who publishes it

VOLARE TECHNOLOGIES PRIVATE LIMITED - 1 other listing from the same operator, none carrying a finding

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Volare Tech. Pvt. Ltd.
Declared legal entity
VOLARE TECHNOLOGIES PRIVATE LIMITED
Registered address
7 Ganga Complex, Airport Road, Yerwada, Maharashtra 411006, IN
Registered contact
VOLARE TECHNOLOGIES PRIVATE LIMITED

Same store account

1 other listing published from this account, 6k+ users between them, none of them carrying a finding.

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

WhatsApp MAIN-world injection exposes chats, contacts, and messages

On WhatsApp Web, InTouchApp injects a script into WhatsApp's page context rather than the usual isolated sandbox.

The script reads WhatsApp's internal data store, and AI Reply sends recent chat messages to InTouchApp's servers for a reply.

Severity
High unwanted
Type
Unexpected
CWE
CWE-829
Source
Dynamic sandbox
What actually happens
You did this

You open WhatsApp Web with InTouchApp installed.

No explicit consent step precedes this injection.

The extension did this

The extension injects a script into WhatsApp's page context (world:'MAIN'), bypassing Chrome's normal isolated-world sandbox.

This gives the injected script direct access to WhatsApp's internal data store, contacts, chats, messages, groups, labels, statuses, and presences, without any user prompt.

The code that does this

Background triggers MAIN-world injection on WhatsApp tab load

Readable version

Injected script hooks WhatsApp webpack runtime (ita-wa-store-bridge.js:103–154)

// Captures WhatsApp's internal webpack require() functionfunction getWebpackRequire() {    const chunkKeys = Object.keys(window).filter(key => key.startsWith('webpackChunk'));    for (const key of chunkKeys) {        const chunk = window[key];        chunk.push([            ['ita_store_bridge_' + Math.random().toString(36).slice(2)],            {},            (req) => {                window.require = req;  // installs WhatsApp's require() on window            }        ]);    }}// Loads WhatsApp internal store modules via captured require()function ensureStore() {    const req = getWebpackRequire();    window.Store = window.Store || {};    window.Store.WidFactory    = req('WAWebWidFactory');    window.Store.LidUtils      = req('WAWebApiContact');    window.Store.ContactCollection = req('WAWebContactCollection').ContactCollection;    // + WAWebChatCollection, WAWebMsgCollection, WAWebGroupMetadataCollection,    //   WAWebLabelCollection, WAWebStatusCollection, WAWebPresenceCollection}

Debug dump helpers installed as global window functions (ita-wa-store-bridge.js:658–676)

// Exposed globally on WhatsApp's page context — accessible to any page scriptwindow.itaWARaidStore    = () => raidRequire();window.itaWASnapshotStore = () => snapshotStore(req);window.itaWADumpContacts  = (options) => dumpCollection(req, 'contacts', options);window.itaWADumpChats     = (options) => dumpCollection(req, 'chats', options);window.itaWADumpMessages  = (options) => dumpCollection(req, 'messages', options);window.itaWADumpLabels    = (options) => dumpCollection(req, 'labels', options);window.itaWADumpStatuses  = (options) => dumpCollection(req, 'statuses', options);window.itaWADumpPresences = (options) => dumpCollection(req, 'presences', options);
WhatsApp data exposed to the MAIN-world bridge (extension and any page-context script)
  • Contact details
    +1 415 555 0123 · "Alice Smith" · isMyContact: true

    Phone numbers, display names, push names, picture URLs, and whether each contact is a WhatsApp user, business, or saved contact.

  • Chat list
    Alice Smith · unread: 3 · lastMsg: "Can we talk tomorrow?"

    All open chats including contact identity, last message preview, unread count, mute status, and archive state.

  • Message content
    "Let me check with the team and get back to you" · from: Alice · t: 1749288432

    Text of recent messages in any open chat, with sender identity and timestamp. AI Reply reads and sends up to 10 messages per invocation.

  • Group membership
    "Project Alpha" · 14 members · owner: +44 7911 123456

    Group name, description, owner, creation date, and the full participant list including phone numbers and admin status for every member.

Captured request
POSThttps://api16.intouchapp.com/api/v1/chat-suggestions/replies/

200 OK, {"status":"success","suggestions":[{"text":"Sounds good, looking forward to hearing from you!"}]}

Headers
Accept
application/json
Content-Type
application/json; charset=utf-8
Authorization
Basic YXNOUExrZHZDQWVVUldNa3BtOjxhcGlfdG9rZW4+
X-Requested-With
XMLHttpRequest
Body
{  "chats": [    {      "sender_id": "me",      "sender_name": "Me",      "time": 1749288400123456,      "message": "Can we meet tomorrow?"    },    {      "sender_id": "external_contact_1",      "sender_name": "Alice",      "time": 1749288432000000,      "message": "Let me check with the team and get back to you"    },    {      "sender_id": "me",      "sender_name": "Me",      "time": 1749288460000000,      "message": "No rush, just ping me when you know"    }  ],  "instructions": "",  "max_suggestions": 1}
Recipient of WhatsApp message content
    • api16.intouchapp.com

    InTouchApp's primary API server. Receives chat transcripts (up to 10 messages per AI Reply call) with the account token. Operated by Datability Solutions Pvt Ltd, India.

Gmail Save Sends Sender Contact Details

Clicking InTouchApp's save button in Gmail reads the sender name, email address, and profile image URL from the message list item and posts them as a contact record to https://api16.intouchapp.com/api/v1/contacts/insync_single/.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You click the extension's save button while viewing a Gmail sender row.

The extension did this

The extension reads the sender contact details from Gmail and sends a contact record to InTouchApp.

Gmail fields assembled into the contact record
  • Sender name
    Alex Chen

    Identifies the person or mailbox shown as the Gmail message sender.

  • Sender email address
    alex.chen@example.com

    Adds a direct email address from the Gmail page to the saved contact.

  • Profile image URL
    https://lh3.googleusercontent.com/a/ACg8ocJ7Example=s96-c

    Adds the sender image URL when Gmail exposes one for the message row.

Captured request
POSThttps://api16.intouchapp.com/api/v1/contacts/insync_single/

The background code expects a JSON response and resolves success when the response is OK.

Headers
Accept
application/json
Content-Type
application/json; charset=utf-8
Authorization
Basic <redacted>
The code that does this

Gmail save path and contact POST

Readable version

Readable click handler

dist/contentScript.bundle.js
            }), e("body").off("click", ".gmail-save").on("click", ".gmail-save", function(t) {              var o = e(this).parents('[role="listitem"]'),                n = angular.element(o).scope();              n.$apply(function() {                n.contact.gmailFetch(o)              })

Readable Gmail DOM extraction

dist/contentScript.bundle.js
          key: "gmailInit",          value: function(t) {            var o = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : void 0,              n = arguments[2];            try {              var a = {};              if (o = o ? o : e('[role="list"]'), !o || !o.length) throw this.exceptionObj.description = "Type: DOM unavailable " + q().format("YYYY-MM-DD:H:mm:ss") + ', DOM: [role="list"], Platform: Gmail', this.exceptionObj.card_log["dom_unavailable_" + q().format("YYYY_MM_DD_H_mm_ss")] = 'DOM: [role="list"], Platform: Gmail', this.exceptionObj;              var M = e(o).find(".gD")[0],                c = e(o).find(".ajn")[0];              a.given = e(M).attr("name"), a.useremail = e(M).attr("email");              var p = e(c).attr("src");              p.includes("default-user") ? "" : a.profilePic = p.replace(/=s.*$/, ""), this.addContactModule.globalButtonVar = e(".nH.g.id"), this.setContactForm(this.addContactModule.globalButtonVar, t, void 0, a, function() {                n(a)              })            } catch (e) {              e.description || (e.description = "Type: JS Crash " + q().format("YYYY-MM-DD:H:mm:ss") + ", Function: gmailInit (service.js), Platform: Gmail", e.isFatal = !0, e.card_log["js_crash_" + q().format("YYYY_MM_DD_H_mm_ss")] = "Function: gmailInit (service.js), Platform: gmail"), this.reportException(e.description, e.isFatal, e.card_log)            }          }

Readable contact message

dist/contentScript.bundle.js
          key: "addContactV2",          value: function() {            var t = this;            e(".intouch-alert.server-error").addClass("ng-hide"), chrome.runtime.sendMessage(JSON.stringify({              api: "add_contact_v2",              contact: this.contactObj,              source: this.utm_source,              term: this.utm_term            }), function(o) {              if (o.success) {                try {                  t.contactObj.icontactId = o.data.icontact_id                } catch (e) {}                t.addContactCallback()              } else t.form.addContactForm.$submitted = !1, t.contactError = o.error, t.$scope.$apply(), e(".intouch-alert.server-error").removeClass("ng-hide")            })          }

Readable background POST

dist/background.bundle.js
  function C(e, t, r) {    return new Promise(function(n) {      var o = Z.getContactObject(e),        a = {};      a.data = o[0], a.source = t, a.term = r, chrome.storage.local.get("api_token", function(e) {        if (chrome.runtime.lastError) return console.error("Error retrieving stored data:", chrome.runtime.lastError.message), void n(chrome.runtime.lastError.message);        var t = G.default.CONSUMER_KEY + ":" + e.api_token;        fetch(G.default.APP_SERVER_URL + "/v1/contacts/insync_single/", {          method: "POST",          signal: AbortSignal.timeout(G.default.TIMEOUT),          headers: {            "Content-Type": "application/json; charset=utf-8",            Accept: "application/json",            Authorization: "Basic " + btoa(t)          },          body: JSON.stringify(a)        }).then(function(e) {          if (!e.ok) throw {            status: e.status,            statusText: e.statusText          };          return e.json()        }).then(function(e) {          n({            success: !0,            data: e          })        }).catch(function(e) {          console.error("API calling failed:", e);          var t = Z.setErrorMessage(e);          n({            success: !1,            error: t          })        })      })    })  }
The code that does this

Contact-object conversion before upload

Readable version
        key: "getJCFFormat",        value: function(e) {          var t = this.fetchName(e.given),            r = [{              name: {                prefix: t.prefix,                given: t.given,                middle: t.middle,                family: t.family,                suffix: t.suffix              },              avatars: [{                name: {                  prefix: t.prefix,                  given: t.given,                  middle: t.middle,                  family: t.family,                  suffix: t.suffix                },                phone: [{                  type: "mobile",                  number: e.ContactMobile,                  label: "Mobile"                }]              }],              context: e.context,              context_emoji: e.emoji ? e.emoji.selectedEmoji : "",              type: "person",              dirty: !0,              deleted: !1,              read_only: !1            }];          return r        }      }, {        key: "getContactObject",        value: function(e) {          var t = this.getJCFFormat(e);          return t = this.getEmail(e.useremail, t), t = this.getOrganization(e, t), t = this.getNotes(e.note, t), t = this.addPreformattedElements(e, t), t = this.getProfilePic(e.profilePic, t), t = this.getTagObj(e.selectedList, t)        }      }, {        key: "updateContactObject",        value: function(e) {          var t = this.fetchName(e.given),            r = [e.icontact];          return r[0] && r[0].avatars && r[0].avatars[0] && (r[0].name = t, r[0].avatars[0].name = t, r[0].context = e.context, r[0].context_emoji = e.emoji ? e.emoji.selectedEmoji : "", r = this.getPhone(e.ContactMobile, r), r = this.getEmail(e.useremail, r), r = this.getOrganization(e, r), r = this.getNotes(e.note, r), r = this.addPreformattedElements(e, r), r = this.getProfilePic(e.profilePic, r), r = this.getTagObj(e.selectedList, r)), r        }      }, {        key: "getPhone",        value: function(e, t) {          return e = e.toString(), e && (t[0].avatars[0].phone && t[0].avatars[0].phone.length ? t[0].avatars[0].phone[0].number = e : (e = [{            number: e,            label: "Personal"          }], t[0].avatars[0].phone = e)), t        }      }, {        key: "getEmail",        value: function(e, t) {          return null != e && (t[0].avatars[0].email && t[0].avatars[0].email.length ? t[0].avatars[0].email[0].address = e : (e = [{            address: e,            label: "Personal"          }], t[0].avatars[0].email = e)), t        }      }, {        key: "getOrganization",        value: function(e, t) {          return null == e.jobTitle && null == e.company || (t[0].avatars[0].organization && t[0].avatars[0].organization.length ? (t[0].avatars[0].organization[0].position = e.jobTitle, t[0].avatars[0].organization[0].company = e.company) : (e = [{            position: e.jobTitle,            company: e.company          }], t[0].avatars[0].organization = e)), t        }      }, {        key: "getNotes",        value: function(e, t) {          return null != e && (t[0].avatars[0].notes && t[0].avatars[0].notes.length ? t[0].avatars[0].notes[0].text = e : (e = [{            text: e          }], t[0].avatars[0].notes = e)), t        }      }, {        key: "getProfilePic",        value: function(e, t) {          return e && "undefined" != e && (t[0].avatars[0].photo && t[0].avatars[0].photo.length ? t[0].avatars[0].photo[0].url = e : (e = [{            url: e          }], t[0].avatars[0].photo = e)), t        }      }, {        key: "addPreformattedElements",        value: function(e, t) {          return e.social && (t[0].avatars[0].social = e.social), e.website && (t[0].avatars[0].website = e.website), e.address && (t[0].avatars[0].address = e.address), t        }
External service receiving the saved contact
    • api16.intouchapp.com

    Receives the contact record created from the Gmail save action.

LinkedIn Save Sends Profile Contact Details

Clicking InTouchApp's save on a LinkedIn profile posts page-read details to https://api16.intouchapp.com/api/v1/contacts/insync_single/: name, phone, email, job title, company, photo, location, website, social links when present.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You click the extension's save button on a LinkedIn profile.

The extension did this

The extension reads the LinkedIn profile fields and sends a contact record to InTouchApp.

LinkedIn fields assembled into the contact record
  • Profile name
    Maya Rao

    Identifies the LinkedIn member whose profile you saved.

  • Phone number
    +1 415 555 0148

    Adds a direct contact number from the profile contact panel when LinkedIn exposes one.

  • Email address
    maya.rao@example.com

    Adds an email address from the profile contact panel when one is visible.

  • Job and company
    Product Lead at Example Systems

    Ties the saved contact to a current role and employer shown on the profile.

  • Social and website links
    linkedin.com/in/mayarao, @mayarao

    Adds profile-linked identifiers such as LinkedIn, Twitter, Skype, and website fields when present.

  • Location and photo
    San Francisco, https://media.licdn.com/dms/image/C4D03AQHExample/profile-displayphoto-shrink_400_400/0/1700000000000

    Adds context from the profile location and profile image URL.

Captured request
POSThttps://api16.intouchapp.com/api/v1/contacts/insync_single/

The background code expects a JSON response and resolves success when the response is OK.

Headers
Accept
application/json
Content-Type
application/json; charset=utf-8
Authorization
Basic <redacted>
The code that does this

LinkedIn save path and contact POST

Readable version

Readable click handler

dist/contentScript.bundle.js
            }), e("body").off("click", ".linkedin-save").on("click", ".linkedin-save", function() {              var t = e(this).parent().parent().parent(),                o = angular.element(e("body")).scope();              o.$apply(function() {                o.contact.linkedinFetch(t)              })

Readable LinkedIn DOM extraction

dist/contentScript.bundle.js
          key: "linkedInit",          value: function(t, o, n) {            try {              var a = {},                M = e(o).find("#pv-contact-info")[0].innerText.trim(),                c = "",                p = "";              try {                c = e(o).find(".pv-contact-info__contact-type.ci-phone").find(".pv-contact-info__ci-container").children()[0].innerText.trim(), p = e(o).find(".pv-contact-info__contact-type.ci-phone").find(".pv-contact-info__ci-container").children()[1].innerText.trim()              } catch (e) {}              var b = "";              try {                b = e(o).find(".pv-contact-info__contact-type.ci-email").find(".pv-contact-info__contact-link")[0].innerText.trim()              } catch (e) {}              var i = "";              try {                i = e("body").children(".ember-view").find(".pv-top-card-section__photo").css("background-image").split('url("')[1].split('")')[0]              } catch (e) {}              var r = "";              try {                r = e(e(e(e("#experience-section").find(".section-info").children()[0]).find(".pv-entity__summary-info")[0]).children()[1]).find(".pv-entity__secondary-title")[0].innerText.trim()              } catch (e) {}              var z = "";              try {                z = e(e(e("#experience-section").find(".section-info").children()[0]).find(".pv-entity__summary-info")[0]).children()[0].innerText.trim()              } catch (e) {}              var s = "";              try {                s = e(".pv-top-card-section__location")[0].innerText.trim();                var d = s.split(",")[0].trim();                if ("" != d) {                  a.address = new Array;                  var O = {};                  O.label = "Office", O.city = d, a.address.push(O)                }              } catch (e) {}              var u = "",                l = "";              try {                var A = e(o).find(".pv-contact-info__contact-type.ci-websites").find(".pv-contact-info__contact-link")[0];                u = A.innerText.trim();                try {                  l = e(A).siblings()[0].innerText.trim().replace(/[()]/g, "")                } catch (e) {}              } catch (e) {}              try {                if ("" != u) {                  a.website = new Array;                  var f = {};                  f.label = l, f.url = u, a.website.push(f)                }              } catch (e) {}              var m = "";              try {                m = e(o).find(".pv-contact-info__contact-type.ci-birthday > .pv-contact-info__ci-container")[0].innerText.trim()              } catch (e) {}              var h = "";              try {                h = e(o).find(".pv-contact-info__contact-type.ci-twitter").find(".pv-contact-info__contact-link")[0].innerText              } catch (e) {}              a.given = M, a.ContactMobile = c, a.useremail = b, a.profilePic = i, a.jobTitle = z, a.company = r, a.addFrom = "li", a.social = [{                network_id: window.location.pathname.split("/")[2],                network: "li",                label: "LinkedIn"              }];              try {                if (h.length) {                  var W = {                    network_id: e.trim(h),                    network: "tw",                    label: "Twitter"                  };                  a.social.push(W)                }              } catch (e) {}              try {                e(o).find(".pv-contact-info__contact-type.ci-ims").each(function(t, o) {                  try {                    var n = e(o).find(".pv-contact-info__ci-container").children()[0].innerText.trim(),                      M = e(o).find(".pv-contact-info__ci-container").children()[1].innerText.trim().replace(/[()]/g, ""),                      c = {};                    0 == M.localeCompare("skype", void 0, {                      sensitivity: "base"                    }) && (c.network = "sk", c.network_id = n, c.label = M, a.social.push(c))                  } catch (e) {}                })              } catch (e) {}              this.addContactModule.globalButtonVar = e(o), this.setContactForm(this.addContactModule.globalButtonVar, t, void 0, a, function() {                n(a)              })            } catch (e) {              e.description || (e.description = "Type: JS Crash " + q().format("YYYY-MM-DD:H:mm:ss") + ", Function: linkedInit (service.js), Platform: Linkedin", e.isFatal = !0, e.card_log["js_crash_" + q().format("YYYY_MM_DD_H_mm_ss")] = "Function: linkedInit (service.js), Platform: Linkedin"), this.reportException(e.description, e.isFatal, e.card_log)            }          }

Readable contact message

dist/contentScript.bundle.js
          key: "addContactV2WithPhoto",          value: function() {            var t = this,              o = this.grabContactDetails.selectedContactNumber;            this.contactObj.selectedList = this.selectedTags(this.grabContactDetails.tagListInForm);            var n = !!this.contactObj.icontact_id,              a = this.contactObj.icontact_id ? this.contactObj.icontact_id : null;            e(".intouch-alert.server-error").addClass("ng-hide"), this.showAppropriateSingleSavedMessage();            var M = this.contactObj.profilePic;            this.contactObj.profilePic = null, chrome.runtime.sendMessage(JSON.stringify({              api: this.contactObj.icontact_id ? "update_contact_v2" : "add_contact_v2",              contact: this.contactObj,              source: this.utm_source,              term: this.utm_term            }), function(c) {              if (c.success) try {                "error" !== c.status ? (t.creditsExpire = !1, n ? t.grabContactDetails.updateCachedContacts(o, t.grabContactDetails.setContactObjInstance(c.data)) : (t.customService.updateCreditBalanceInStorage(-c.count || -1), t.getAccountInfo()), M ? t.getImageFromUrl(M, function(e) {                  e ? (e.imgUrl = M, t.fetchedList = [{                    ContactMobile: o ? o : t.contactObj.ContactMobile,                    profilePic: e,                    selected: !0,                    icontactId: a ? a : c.data.results[0].icontact_id                  }], t.syncSingleContact(0, event, !0, function() {                    t.addContactCallback()                  })) : t.addContactCallback()                }) : t.addContactCallback(), t.addContactCallback()) : "error" === c.status && "credits_over" === c.error_code && (t.form.addContactForm.$submitted = !1, t.creditsExpire = !0, t.$scope.$apply())              } catch (e) {                console.error("addContactV2WithPhoto:crashed: " + e)              } else t.form.addContactForm.$submitted = !1, t.contactError = c.error, t.$scope.$apply(), e(".intouch-alert.server-error").removeClass("ng-hide")            })          }

Readable background POST

dist/background.bundle.js
  function C(e, t, r) {    return new Promise(function(n) {      var o = Z.getContactObject(e),        a = {};      a.data = o[0], a.source = t, a.term = r, chrome.storage.local.get("api_token", function(e) {        if (chrome.runtime.lastError) return console.error("Error retrieving stored data:", chrome.runtime.lastError.message), void n(chrome.runtime.lastError.message);        var t = G.default.CONSUMER_KEY + ":" + e.api_token;        fetch(G.default.APP_SERVER_URL + "/v1/contacts/insync_single/", {          method: "POST",          signal: AbortSignal.timeout(G.default.TIMEOUT),          headers: {            "Content-Type": "application/json; charset=utf-8",            Accept: "application/json",            Authorization: "Basic " + btoa(t)          },          body: JSON.stringify(a)        }).then(function(e) {          if (!e.ok) throw {            status: e.status,            statusText: e.statusText          };          return e.json()        }).then(function(e) {          n({            success: !0,            data: e          })        }).catch(function(e) {          console.error("API calling failed:", e);          var t = Z.setErrorMessage(e);          n({            success: !1,            error: t          })        })      })    })  }
The code that does this

Contact-object conversion before upload

Readable version
        key: "getJCFFormat",        value: function(e) {          var t = this.fetchName(e.given),            r = [{              name: {                prefix: t.prefix,                given: t.given,                middle: t.middle,                family: t.family,                suffix: t.suffix              },              avatars: [{                name: {                  prefix: t.prefix,                  given: t.given,                  middle: t.middle,                  family: t.family,                  suffix: t.suffix                },                phone: [{                  type: "mobile",                  number: e.ContactMobile,                  label: "Mobile"                }]              }],              context: e.context,              context_emoji: e.emoji ? e.emoji.selectedEmoji : "",              type: "person",              dirty: !0,              deleted: !1,              read_only: !1            }];          return r        }      }, {        key: "getContactObject",        value: function(e) {          var t = this.getJCFFormat(e);          return t = this.getEmail(e.useremail, t), t = this.getOrganization(e, t), t = this.getNotes(e.note, t), t = this.addPreformattedElements(e, t), t = this.getProfilePic(e.profilePic, t), t = this.getTagObj(e.selectedList, t)        }      }, {        key: "updateContactObject",        value: function(e) {          var t = this.fetchName(e.given),            r = [e.icontact];          return r[0] && r[0].avatars && r[0].avatars[0] && (r[0].name = t, r[0].avatars[0].name = t, r[0].context = e.context, r[0].context_emoji = e.emoji ? e.emoji.selectedEmoji : "", r = this.getPhone(e.ContactMobile, r), r = this.getEmail(e.useremail, r), r = this.getOrganization(e, r), r = this.getNotes(e.note, r), r = this.addPreformattedElements(e, r), r = this.getProfilePic(e.profilePic, r), r = this.getTagObj(e.selectedList, r)), r        }      }, {        key: "getPhone",        value: function(e, t) {          return e = e.toString(), e && (t[0].avatars[0].phone && t[0].avatars[0].phone.length ? t[0].avatars[0].phone[0].number = e : (e = [{            number: e,            label: "Personal"          }], t[0].avatars[0].phone = e)), t        }      }, {        key: "getEmail",        value: function(e, t) {          return null != e && (t[0].avatars[0].email && t[0].avatars[0].email.length ? t[0].avatars[0].email[0].address = e : (e = [{            address: e,            label: "Personal"          }], t[0].avatars[0].email = e)), t        }      }, {        key: "getOrganization",        value: function(e, t) {          return null == e.jobTitle && null == e.company || (t[0].avatars[0].organization && t[0].avatars[0].organization.length ? (t[0].avatars[0].organization[0].position = e.jobTitle, t[0].avatars[0].organization[0].company = e.company) : (e = [{            position: e.jobTitle,            company: e.company          }], t[0].avatars[0].organization = e)), t        }      }, {        key: "getNotes",        value: function(e, t) {          return null != e && (t[0].avatars[0].notes && t[0].avatars[0].notes.length ? t[0].avatars[0].notes[0].text = e : (e = [{            text: e          }], t[0].avatars[0].notes = e)), t        }      }, {        key: "getProfilePic",        value: function(e, t) {          return e && "undefined" != e && (t[0].avatars[0].photo && t[0].avatars[0].photo.length ? t[0].avatars[0].photo[0].url = e : (e = [{            url: e          }], t[0].avatars[0].photo = e)), t        }      }, {        key: "addPreformattedElements",        value: function(e, t) {          return e.social && (t[0].avatars[0].social = e.social), e.website && (t[0].avatars[0].website = e.website), e.address && (t[0].avatars[0].address = e.address), t        }
External service receiving the saved contact
    • api16.intouchapp.com

    Receives the contact record created from the LinkedIn profile save action.

Updated 30 September 2026fmanjoeogdemcgapfmadpgcmigkefkkc