Salesforce Cti | Integration Guide | SalesforceTutorial

Written by Prasanth Kumar Published on Updated on

Salesforce cti connects a phone system with Salesforce so agents can click a phone number, receive inbound screen pops, and record call activity against CRM records. In 2026, the design question is no longer only how to build a softphone; it is whether an existing Open CTI implementation should remain in place until retirement or move to Salesforce Voice with Telephony Providers.

For new work, treat salesforce cti as a contact-center architecture decision. Existing Open CTI orgs can continue until the stated retirement date, but Salesforce says Open CTI is in maintenance mode, has no new enhancements, is unavailable for newly created Agentforce Service orgs, and reaches end of life on February 28, 2028. See the official Salesforce notice at Salesforce Open CTI Retirement.

What is Salesforce CTI?

Salesforce CTI means computer-telephony integration inside the Salesforce agent workspace. The agent does not leave the Service Console to dial a number, identify a caller, or open a matching Contact, Account, Lead, Case, or custom record.

The term can mean different products depending on the org:

Term What it means Use in 2026
Open CTI A browser-based JavaScript API for integrating third-party telephony with Salesforce Call Center. Existing implementations only. Plan retirement before February 28, 2028.
Salesforce Call Center Setup metadata that connects users, softphone configuration, and a call center definition file. Still relevant for existing Open CTI deployments.
Salesforce Voice with Telephony Providers The current Salesforce voice model, formerly Service Cloud Voice, for bringing telephony into the service workspace. Preferred path for new voice-channel planning and Open CTI migration.
Contact Center Salesforce’s broader service-channel approach for voice and digital work in one agent experience. Evaluate when the project includes routing, messaging, AI assistance, and supervisor needs.

In enterprise orgs, salesforce cti usually sits near case routing, identity verification, call recording policy, data retention, and compliance controls. Do not let a telephony vendor package decide those choices without Salesforce architecture review. A Salesforce CTI design review should confirm who owns routing, logging, and support after go-live.

How does Salesforce CTI work in a service console?

A typical salesforce cti flow has four moving parts: the telephony platform, a softphone web app, Salesforce Call Center or Salesforce Voice configuration, and CRM records such as Case, Contact, Lead, Task, and Voice Call. The correct design depends on whether you use legacy Open CTI or a Salesforce Voice model. Salesforce CTI architecture also needs a rollback plan because phone support is usually a critical service channel.

Cti salesforce integration architecture

A legacy cti salesforce integration with Open CTI often works like this:

  1. The user opens a Lightning console app that has the Open CTI Softphone in the utility bar.
  2. The softphone loads a web page from the adapter URL in the call center definition file.
  3. The softphone includes the Lightning Open CTI script, for example /support/api/66.0/lightning/opencti_min.js. Salesforce documentation shows separate API paths for Classic and Lightning; examples here use API v66.0, while the Lightning Open CTI methods discussed below are available from API v38.0.
  4. The softphone registers event handlers such as click-to-dial and inbound screen pop.
  5. The telephony provider handles the call media and returns call state to the softphone.
  6. The softphone or an integration service writes CRM activity, links the call to records, or opens the right record page.

Salesforce documents Open CTI as a JavaScript API for integrating third-party CTI systems with Salesforce Call Center. The current developer guide is at Open CTI Developer Guide.

Cti for salesforce versus Salesforce Voice

Use cti for salesforce as a broad search term, not as a product name. Salesforce CTI decisions should name the actual product, adapter, and telephony provider in the design document. Open CTI focuses on custom softphone behavior. Salesforce Voice with Telephony Providers focuses on a managed voice experience that can work with Omni-Channel, transcripts, and voice-specific setup. Salesforce describes Salesforce Voice with Telephony Providers, formerly Service Cloud Voice, in the official help topic Get to Know Salesforce Voice.

If your roadmap includes real-time transcription, supervisor visibility, AI assistance, Omni-Channel routing, or Agentforce Service planning, evaluate Salesforce Voice before adding more custom Open CTI code. For related service-channel setup, see Service Cloud Voice setup concepts and Omni-Channel in Salesforce.

How to plan cti implementation in salesforce

A safe cti implementation in salesforce starts with inventory, not code. Confirm the telephony provider, current adapter, call center definition files, assigned users, console apps, softphone layouts, Apex entry points, external services, and reporting dependencies. Salesforce CTI projects fail when teams skip this inventory and discover hidden call logging logic during cutover.

Cti implementation in salesforce checklist for existing Open CTI orgs

  • Confirm the product path. Do not start a net-new Open CTI build for a new Agentforce Service org. Use Salesforce Voice planning unless Salesforce documentation and your account team confirm another supported path.
  • Find every call center. In Setup, review Call Centers or Contact Centers, exported definition files, adapter URLs, and user assignments.
  • Check Lightning compatibility. Open CTI for Lightning requires a Lightning app with the Open CTI Softphone in the utility bar. The call center definition file must set reqSalesforceCompatibilityMode to Lightning or Classic_and_Lightning.
  • Review browser and security controls. Use HTTPS for adapter URLs, validate postMessage origins, and keep telephony tokens out of client-side storage where possible.
  • Document screen pop rules. Map inbound call types to Contact, Account, Lead, Case, Flow, or search behavior.
  • Decide how calls are logged. Existing Open CTI implementations often create Tasks; Salesforce Voice commonly uses voice-specific records and components. Do not mix reporting models without a migration plan. Salesforce CTI reports should have a named owner before the target voice channel goes live.
  • Test permission boundaries. A screen pop does not bypass object permissions, sharing, CRUD, or field-level security. Agents still need access to the records and fields they open.

The call center definition file is the metadata entry point for Open CTI. Salesforce documents required and optional elements in Call Center Definition Files.

Sample call center definition file for an existing Lightning CTI adapter

This sample is for an existing salesforce cti org that still runs Open CTI. Do not use it as the starting point for a new 2026 voice project without checking the retirement guidance. Salesforce CTI build work should now be limited to existing org support and migration-safe changes.

<?xml version="1.0" encoding="UTF-8"?>
<callCenter>
  <section sortOrder="0" name="reqGeneralInfo" label="General Information">
    <item sortOrder="0" name="reqInternalName" label="Internal Name">ExistingLightningCTI</item>
    <item sortOrder="1" name="reqDisplayName" label="Display Name">Existing Lightning CTI</item>
    <item sortOrder="2" name="reqAdapterUrl" label="CTI Adapter URL">https://telephony.example.com/softphone</item>
    <item sortOrder="3" name="reqUseApi" label="Use Open CTI API">true</item>
    <item sortOrder="4" name="reqSoftphoneHeight" label="Softphone Height">480</item>
    <item sortOrder="5" name="reqSoftphoneWidth" label="Softphone Width">360</item>
    <item sortOrder="6" name="reqSalesforceCompatibilityMode" label="Compatibility Mode">Lightning</item>
  </section>
</callCenter>

Important setup notes from the official Open CTI documentation: reqInternalName must be unique and contain no spaces or punctuation, Lightning adapter URLs should use HTTPS, and Lightning softphone size values must stay within documented pixel ranges. For Lightning Experience, Salesforce states that Open CTI works only in Lightning apps, not Classic apps shown inside Lightning Experience.

How to build core Salesforce CTI behavior in existing Open CTI

The following examples show patterns that often appear in an existing salesforce cti adapter. Keep custom code small. Salesforce CTI code is easier to replace when it handles only UI events and delegates telephony work to the provider. Push telephony authentication, call control, recording, and compliance decisions into the provider platform or a server-side integration layer.

Click-to-dial JavaScript for Lightning Open CTI

The Lightning Open CTI enableClickToDial and onClickToDial methods are available from API v38.0. The listener payload can include the clicked phone number, record ID, record name, object type, and person account information when it applies. Salesforce documents these methods in enableClickToDial and onClickToDial.

<!-- Example softphone page for an existing Open CTI implementation in Lightning Experience -->
<script src="/support/api/66.0/lightning/opencti_min.js"></script>
<script>
(function () {
  function logCtiError(action, response) {
    if (!response || response.success) {
      return;
    }
    console.error(action + ' failed', response.errors);
  }

  sforce.opencti.enableClickToDial({
    callback: function (response) {
      logCtiError('enableClickToDial', response);
    }
  });

  sforce.opencti.onClickToDial({
    listener: function (payload) {
      // Payload includes number, recordId, recordName, objectType, and
      // person account fields when Person Accounts apply.
      const dialRequest = {
        phoneNumber: String(payload.number),
        salesforceRecordId: payload.recordId,
        objectType: payload.objectType
      };

      // Send this request to your telephony web app or provider SDK.
      // Validate origin and authentication before accepting messages.
      window.parent.postMessage(
        { type: 'DIAL_REQUEST', data: dialRequest },
        'https://telephony.example.com'
      );
    }
  });
})();
</script>

This Salesforce CTI code does not place a real call by itself. It captures the Salesforce click event and passes a dial request to the telephony web app. In production, validate the message origin, authenticate the user, check outbound dialing policy, and log errors without exposing call tokens in the browser console.

Screen pop and deferred search behavior

For inbound calls, salesforce cti often searches first and opens the most useful record after the agent accepts the call. In Lightning Experience, screenPop can navigate to record, URL, object home, list, search, new record modal, or flow targets. searchAndScreenPop can use the deferred parameter so the softphone controls when navigation happens. Salesforce documents these methods in screenPop for Lightning Experience and searchAndScreenPop for Lightning Experience.

// Use this only in existing Open CTI orgs. screenPop is available from API v38.0.
function openCaseFromInboundCall(caseId) {
  sforce.opencti.screenPop({
    type: sforce.opencti.SCREENPOP_TYPE.SOBJECT,
    params: { recordId: caseId },
    callback: function (response) {
      if (!response.success) {
        console.error('screenPop failed', response.errors);
      }
    }
  });
}

// Search first, then defer the navigation until the agent accepts the call.
function prepareInboundScreenPop(phoneNumber) {
  sforce.opencti.searchAndScreenPop({
    searchParams: phoneNumber,
    callType: sforce.opencti.CALL_TYPE.INBOUND,
    deferred: true,
    callback: function (response) {
      if (!response.success) {
        console.error('searchAndScreenPop failed', response.errors);
        return;
      }
      const popData = response.returnValue && response.returnValue.SCREEN_POP_DATA;
      if (popData) {
        sforce.opencti.screenPop(popData);
      }
    }
  });
}

Two details matter in support orgs. First, phone search depends on the softphone layout and the fields selected there. Second, phone matching is only as good as your phone data. Standardize on E.164 or another agreed format before blaming the CTI adapter for missed matches.

Apex logging endpoint for telephony events

Some Salesforce CTI teams add an Apex endpoint so a telephony middleware service can write call tasks after the call ends. This is not a replacement for Salesforce Voice records, and it is not a reason to extend Open CTI past retirement. It is a pattern for existing systems that still need controlled CRM logging during migration.

@RestResource(urlMapping='/telephony/v1/call-events')
global with sharing class TelephonyCallEventApi {
    global class CallEvent {
        public String callId;
        public String direction;
        public String phone;
        public String outcome;
        public Integer durationSeconds;
        public Datetime startedAt;
    }

    @HttpPost
    global static List<Id> createCallTasks() {
        if (!Schema.sObjectType.Task.isCreateable()) {
            RestContext.response.statusCode = 403;
            return new List<Id>();
        }

        String body = RestContext.request.requestBody == null
            ? '[]'
            : RestContext.request.requestBody.toString();

        List<CallEvent> events = (List<CallEvent>) JSON.deserialize(body, List<CallEvent>.class);
        if (events == null || events.isEmpty()) {
            RestContext.response.statusCode = 400;
            return new List<Id>();
        }

        Set<String> phones = new Set<String>();
        for (CallEvent eventRow : events) {
            if (String.isNotBlank(eventRow.phone)) {
                phones.add(eventRow.phone.trim());
            }
        }

        Map<String, Id> contactByPhone = new Map<String, Id>();
        if (!phones.isEmpty()) {
            for (Contact c : [
                SELECT Id, Phone, MobilePhone
                FROM Contact
                WHERE Phone IN :phones OR MobilePhone IN :phones
                LIMIT 2000
            ]) {
                if (String.isNotBlank(c.Phone)) {
                    contactByPhone.put(c.Phone, c.Id);
                }
                if (String.isNotBlank(c.MobilePhone)) {
                    contactByPhone.put(c.MobilePhone, c.Id);
                }
            }
        }

        List<Task> tasksToInsert = new List<Task>();
        Date todayDate = Date.today();

        for (CallEvent eventRow : events) {
            Task t = new Task();
            t.Subject = 'Phone call - ' + (String.isBlank(eventRow.direction) ? 'unknown' : eventRow.direction);
            t.Status = 'Completed';
            t.Priority = 'Normal';
            t.ActivityDate = todayDate;
            t.Description =
                'Call ID: ' + eventRow.callId +
                '\nOutcome: ' + eventRow.outcome +
                '\nDuration seconds: ' + String.valueOf(eventRow.durationSeconds) +
                '\nStarted at: ' + String.valueOf(eventRow.startedAt);

            if (String.isNotBlank(eventRow.phone) && contactByPhone.containsKey(eventRow.phone.trim())) {
                t.WhoId = contactByPhone.get(eventRow.phone.trim());
            }
            tasksToInsert.add(t);
        }

        SObjectAccessDecision decision =
            Security.stripInaccessible(AccessType.CREATABLE, tasksToInsert);

        List<SObject> safeTasks = decision.getRecords();
        insert safeTasks;

        List<Id> createdIds = new List<Id>();
        for (SObject taskRecord : safeTasks) {
            createdIds.add((Id) taskRecord.get('Id'));
        }

        RestContext.response.statusCode = 201;
        return createdIds;
    }
}

The Apex code uses one SOQL query for the whole request, inserts records in bulk, checks create access on Task, and calls Security.stripInaccessible before DML. In a production cti salesforce integration, add authentication with a Connected App or integration user, store external call IDs in a custom field with a unique index, normalize phone numbers before matching, and write tests for empty payloads, duplicate calls, and users without Task create access. See Salesforce API integration patterns and Connected App setup for related security planning.

How should teams migrate Salesforce CTI before Open CTI retirement?

Salesforce has given a clear date: Open CTI reaches end of life on February 28, 2028. Salesforce CTI owners should track that date as a dependency in the service roadmap. After that date, Open CTI implementations will no longer function according to the Salesforce retirement notice. A migration plan for salesforce cti should start while there is time to test routing, call recording, reporting, and agent adoption.

Migration decision matrix

Current state Risk Recommended next action
Open CTI only does click-to-dial and basic Task logging. Medium. Functional replacement may be straightforward, but reporting still needs mapping. Compare Salesforce Voice with the current telephony provider and map Task reports to the new model.
Open CTI has custom screen pop rules, Apex services, and provider-specific JavaScript. High. Custom behavior may not move one-for-one. Create a capability inventory, identify must-keep flows, and prototype the target voice model.
Multiple business units use different telephony vendors. High. Routing, compliance, and reporting may vary by region. Define a global voice architecture with local provider constraints documented.
New Agentforce Service org being created. Open CTI is not available for this path. Plan Salesforce Voice or another currently supported contact-center option from the start.

Migration workstream for cti implementation in salesforce

  1. Inventory. Export call center files, list users, note softphone layouts, identify all adapter URLs, and trace every Apex or external endpoint used by the current adapter.
  2. Process mapping. Document inbound call, outbound call, transfer, voicemail, missed call, after-call work, and call disposition behavior.
  3. Data model mapping. Decide how existing Task-based call history maps to the target model. Keep historical records queryable for service teams. Salesforce CTI migration is not complete until supervisors can still answer historical reporting questions.
  4. Security review. Validate object access, field access, sharing, session handling, CSP, named credentials, and integration-user scope.
  5. Pilot. Move one queue or region first. Compare handle time, call logging accuracy, screen pop success, and supervisor reporting.
  6. Cutover. Freeze Open CTI changes except break-fix work, train agents, update support runbooks, and remove retired call center assignments after the new path is stable.

For Salesforce Voice setup, review the official setup entry point Set Up Salesforce Voice, Trailhead planning guidance at Service Cloud Voice Implementation Guide, partner telephony guidance at Set Up Salesforce Voice with Partner Telephony, and Omni-Channel voice routing guidance at Configure Omni-Channel for Salesforce Voice.

Best practices for Salesforce CTI security and performance

Security and performance issues in salesforce cti usually appear at the boundary between the browser, telephony provider, and CRM data. Review these Salesforce CTI points before go-live:

  • Do not trust browser events. Treat click-to-dial and inbound-call messages as requests that still need server-side validation.
  • Use HTTPS and validate origins. Open CTI adapter URLs for Lightning should use HTTPS. If the softphone uses postMessage, hard-code allowed origins rather than using *.
  • Use one integration user per integration boundary where possible. This makes audit trails clearer and limits token scope.
  • Bulkify CRM writes. Telephony systems can send retries or batched call events. Use one SOQL query outside loops and one DML operation per batch where possible.
  • Enforce CRUD and FLS. Apex runs in system context for many operations. Use object checks and Security.stripInaccessible when writing records from integration code.
  • Plan for governor limits. Do not create one synchronous Apex request per call-state heartbeat. Log final call outcomes or meaningful state transitions.
  • Keep screen pops predictable. Agents lose time when the same phone number opens different record types in different queues. Define matching rules and test duplicates.
  • Design reporting before migration. Supervisors need consistent definitions for offered calls, answered calls, abandoned calls, transfer rate, and after-call work.

Common errors with CTI Salesforce integration

Symptom Likely cause Fix
Softphone does not appear in Lightning. The app is not a Lightning app, the utility item is missing, or reqSalesforceCompatibilityMode is not set for Lightning. Check App Manager, add Open CTI Softphone to the utility bar, and update the call center definition.
Click-to-dial icon appears but does nothing. enableClickToDial did not complete, the listener was not registered, or the telephony app rejected the request. Log the Open CTI callback response, verify browser console errors, and test the provider SDK outside Salesforce.
Inbound call opens the wrong record. Duplicate phone numbers, inconsistent formatting, or softphone layout search settings. Normalize phone numbers, adjust softphone layout search fields, and define duplicate-handling rules.
Apex logging fails for some agents. Missing object permission, required field, validation rule, record type, or field-level access. Use debug logs, capture DML errors, and test with the same profile and permission sets as agents.

Why salesforce social studio retirement 2024 end of life is not a CTI topic

The query salesforce social studio retirement 2024 end of life can appear near CTI searches because both involve Salesforce product retirements. They are separate products. Social Studio retirement does not change Open CTI behavior, Call Center setup, Salesforce Voice setup, or salesforce cti migration steps.

Salesforce retired the Social Studio family of products on November 18, 2024, or at the end of the customer’s contract if that came first. Salesforce documents that retirement in Marketing Cloud Social Studio Retirement and in Salesforce Past Product and Feature Retirements. Keep that issue separate from any cti for salesforce project plan.

Related SalesforceTutorial resources

Frequently Asked Questions

What is Salesforce CTI used for?

Salesforce CTI is used to connect phone activity with CRM work. Agents can click phone numbers, receive inbound screen pops, and log call details without switching between separate phone and case-management tools.

Is Open CTI retired in Salesforce?

Open CTI is in maintenance mode and is scheduled for retirement on February 28, 2028. Salesforce says no new features or enhancements are being added, and Open CTI is unavailable for newly created Agentforce Service orgs.

What replaces Open CTI for Salesforce?

Salesforce recommends moving telephony integration to Salesforce Voice with Telephony Providers, formerly Service Cloud Voice. The right replacement depends on your telephony provider, routing requirements, reporting model, and whether you need Omni-Channel, transcription, or Agentforce Service capabilities.

How do I start cti implementation in salesforce?

Start cti implementation in salesforce by identifying whether the project is new or an existing Open CTI migration. For an existing org, inventory call centers, adapter URLs, user assignments, softphone layouts, Apex services, screen pop rules, and reports before choosing the Salesforce Voice migration path.

Does salesforce social studio retirement 2024 end of life affect CTI?

No. salesforce social studio retirement 2024 end of life refers to Marketing Cloud Social Studio retirement, not Salesforce CTI. It does not affect Open CTI, Salesforce Call Center, or Salesforce Voice configuration.

Can Apex be used in a CTI Salesforce integration?

Yes, Apex can support a cti salesforce integration when server-side CRM work is needed, such as controlled call logging or matching calls to records. Keep Apex bulkified, enforce CRUD and field-level security, and avoid writing one record for every low-value telephony heartbeat.