Skip to content

Loading a contact record

The developer framework is currently in BETA

This framework is in beta. Please submit a Github issue if you encounter any problems or have a question.

A critical function performed by the server is looking up a contact record in the target CRM given a phone number, and returning a list of matches for that phone number. In addition, the framework will transmit a list of alternative phone number formats to search for.

Alternative phone number formats

Some CRMs expose a contact search API that is very strict with regards to phone number lookup. For example, if a CRM only supports an EXACT MATCH then searching for an E.164 phone number may not yield any results if the phone number is stored in any other format.

As a workaround, the CRM framework allows users to specify additional phone number formats that they typically store phone numbers in. This list of phone numbers is transmitted to the adapter's server, so that the associated adapter can search for a contact using multiple phone number formats until one is found.

Endpoint

  • HTTP method: GET
  • HTTP endpoint: <server base URL>/contact

Request parameters

Name Description
jwtToken An encrypted string that includes the current user's ID and the associated CRM.
phoneNumber The phone number in E.164 format that should be searched for in the associated CRM.
overridingFormat A comma-delimitted list of phone number formats that should be used when searching the associated CRM.

Response

The server should return an ARRAY of possible matches for the given phone number.

Name Description
id The unique ID of the contact in the target CRM.
name The full name of the contact in the target CRM.
phone The phone number of the contact as stored in the CRM.
organization The company name or affiliation of the contact in the target CRM.
additionalInfo TODO

Additional info

TODO

Example

[
  {
    'id': 80723490120943,
    'name': 'Luke Skywalker',
    'phone': '+16505551212',
    'organization': 'Rebel Alliance',
    'additionalInfo': {
        'associations': [
           {
              'id': 1837202932,
              'label': 'Jedi Order' 
           }
        ]
    }
  }
]

Sample code

async function getContact({ user, authHeader, phoneNumber, overridingFormat }) {
    // ----------------------------------------
    // ---TODO.3: Implement contact matching---
    // ----------------------------------------

    const numberToQueryArray = [];
    numberToQueryArray.push(phoneNumber.replace(' ', '+'));
    // You can use parsePhoneNumber functions to further parse the phone number
    const foundContacts = [];
    // for (var numberToQuery of numberToQueryArray) {
    //     const personInfo = await axios.get(
    //         `https://api.crm.com/contacts?query=number:${numberToQuery}`,
    //         {
    //             headers: { 'Authorization': authHeader }
    //         });
    //     if (personInfo.data.length > 0) {
    //         for (var result of personInfo.data) {
    //             foundContacts.push({
    //                 id: result.id,
    //                 name: result.name,
    //                 phone: numberToQuery,
    //                 additionalInfo: null
    //             })
    //         }
    //     }
    // }
    if (mockContact != null) {
        foundContacts.push(mockContact);
    }
    console.log(`found contacts... \n\n${JSON.stringify(foundContacts, null, 2)}`);
    //-----------------------------------------------------
    //---CHECK.3: In console, if contact info is printed---
    //-----------------------------------------------------
    return foundContacts;  //[{id, name, phone, additionalInfo}]
}
async function getContact({ user, authHeader, phoneNumber, overridingFormat }) {
    phoneNumber = phoneNumber.replace(' ', '+')
    // without + is an extension, we don't want to search for that
    if (!phoneNumber.includes('+')) {
        return null;
    }
    const phoneNumberObj = parsePhoneNumber(phoneNumber);
    let phoneNumberWithoutCountryCode = phoneNumber;
    if (phoneNumberObj.valid) {
        phoneNumberWithoutCountryCode = phoneNumberObj.number.significant;
    }
    const personInfo = await axios.get(
        `https://${user.hostname}/v1/persons/search?term=${phoneNumberWithoutCountryCode}&fields=phone`,
        {
            headers: { 'Authorization': authHeader }
        });
    const matchedContacts = [];
    if (personInfo.data.data.items.length === 0) {
        return matchedContacts;
    }
    else {
        for (const person of personInfo.data.data.items) {
            const dealsResponse = await axios.get(
                `https://${user.hostname}/v1/persons/${person.item.id}/deals?status=open`,
                {
                    headers: { 'Authorization': authHeader }
                });
            const relatedDeals = dealsResponse.data.data ?
                dealsResponse.data.data.map(d => { return { const: d.id, title: d.title } })
                : null;
            matchedContacts.push(formatContact(person.item, relatedDeals));
        }
    }
    return matchedContacts;
}