Skip to content

findContact

Looks up CRM contacts by phone number. This powers call pop, call logging, SMS/fax logging, and manual refresh.

Signature

async function findContact({
  user,
  authHeader,
  phoneNumber,
  overridingFormat,
  isExtension,
  proxyConfig,
  tracer,
  isForceRefreshAccountData
}) {
  return {
    successful: true,
    matchedContactInfo: [],
    returnMessage: null,
    extraDataTracking: {}
  };
}

Input

Field Description
user Connected CRM user.
authHeader Prepared CRM auth header.
phoneNumber Phone number to search, usually in E.164 format.
overridingFormat Comma-separated phone formats from advanced user settings. Convert and search these if the CRM requires exact formatting.
isExtension Indicates an internal extension-number lookup when extension-number logging is enabled.
proxyConfig Proxy configuration when applicable.
tracer Debug tracer when the request has is-debug: true.
isForceRefreshAccountData True when the caller wants to bypass cached contact data.

Return

Field Description
successful true when lookup completed, even if no contact was found.
matchedContactInfo Array of contacts. Return [] for no matches.
returnMessage Optional UI message. If omitted and no contact is found, core supplies a default warning.
extraDataTracking Optional analytics/tracing data, such as rate-limit state or { isCached: true }.

Each contact can include:

Field Description
id CRM contact ID.
name Contact display name.
phone Matched phone number.
type Contact type used by contactPageUrl and CRM-specific logic.
title, company, email, createdDate, mostRecentActivityDate Optional display/search metadata.
additionalInfo Object keyed by manifest additionalFields[].const values. Use this for contact-dependent options such as matters, deals, or opportunities.
isNewContact Use only for the special "Create new contact..." option. Core does not cache contacts marked this way.

Created-Date Resolver Support

Auto logging can resolve multiple matched contacts by selecting the earliest created CRM record. To support that option, every real contact returned by findContact SHOULD include createdDate.

Rules:

Rule Verification
createdDate MUST be the CRM record creation timestamp for that contact, not the last activity or last update timestamp. Compare with the CRM API response field used in the connector, such as created_at, DATE_CREATED_UTC, dateAdded, or add_time.
createdDate SHOULD be returned for every matched real contact when more than one contact may be returned. Exercise findContact with a phone number shared by multiple contacts.
Do not add createdDate to the isNewContact placeholder. The placeholder is not a CRM record and is ignored by the resolver.

Use an ISO 8601 date-time with a timezone when possible, such as 2024-01-01T00:00:00Z. The client also accepts Unix timestamps in seconds, milliseconds, microseconds, or nanoseconds; numeric timestamp strings; YYYY-MM-DD HH:mm:ss; YYYY-MM-DD; YYYYMMDD; YYYYMMDDHHmmss; RFC-style named dates; and .NET /Date(1704067200000)/ values. Ambiguous slash formats such as 01/02/2024 are not accepted.

If any matched real contact does not include a valid createdDate, the client will not use the earliest-created resolver for that log. It will show a warning asking the user to contact the connector developer to add support.

Caching

Core caches non-new contact matches by RingCentral account, platform, and phone number. A forced refresh bypasses the cache and removes stale cached data when the CRM returns no contacts.

Create-Contact Option

If you want the UI to offer contact creation, append:

matchedContactInfo.push({
  id: 'createNewContact',
  name: 'Create new contact...',
  isNewContact: true,
  additionalInfo: null
});

Do not create contacts inside findContact just because no match was found. Return an empty list and let the user or auto-logging rules trigger createContact.

Reference

const axios = require('axios');

async function findContact({ user, authHeader, phoneNumber, overridingFormat, isExtension }) {

    console.log(`phone number: ${phoneNumber}`)
    console.log(`is extesnion number? ${isExtension}`)
    const numberToQueryArray = [];
    if (isExtension) {
        numberToQueryArray.push(phoneNumber);
    }
    else {
        numberToQueryArray.push(phoneNumber.replace(' ', '+'));
    }

    const storedContacts = require('../mockContacts.json');
    const matchedContactInfo = [];
    const matchedContacts = storedContacts.filter(contact => contact.phone === phoneNumber);
    if (matchedContacts?.length > 0) {
        console.log(`found contacts... \n\n${JSON.stringify(matchedContacts, null, 2)}`);
        matchedContactInfo.push(...matchedContacts);
    }
    //------------------------------------------------------
    //--- CHECK: In console, if contact info is printed ----
    //------------------------------------------------------

    //--------------------------------------
    //--- TODO: Add CRM API call here ------
    //--- TODO: Delete above mock JSON -----
    //--------------------------------------
    // 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,
    //                 type: result.type,
    //                 phone: numberToQuery,
    //                 createdDate: result.created_at,
    //                 mostRecentActivityDate: result.updated_at,
    //                 additionalInfo: null
    //             })
    //         }
    //     }
    // }

    // If you want to support creating a new contact from the extension, below placeholder contact should be used
    matchedContactInfo.push({
        id: 'createNewContact',
        name: 'Create new contact...',
        additionalInfo: null,
        isNewContact: true
    });
    return {
        successful: true,
        matchedContactInfo,
        returnMessage: {
            messageType: 'success',
            message: 'Successfully found contact.',
            detaisl: [
                {
                    title: 'Details',
                    items: [
                        {
                            id: '1',
                            type: 'text',
                            text: `Found ${matchedContactInfo.length} contacts`
                        }
                    ]
                }
            ],
            ttl: 3000
        }
    };  //[{id, name, phone, additionalInfo}]
}

module.exports = findContact;