Description
This guide walks through building a record-triggered Salesforce Flow that automatically enriches every newly created Lead using the Lusha v3 API. When a Lead is created, the Flow sends whatever identifiers are available to Lusha, receives the matching contact profile, and writes the returned data back onto the Lead record. The integration is entirely declarative. No Apex is written or deployed at any point.Prerequisites
1. Get your Lusha API Key
Visit dashboard.lusha.com → API Hub → Manage API Keys → + Create new Key. Copy it - you’ll paste it once below. Auth is via anapi_key HTTP header (not Bearer).
2. Salesforce Named and External Credential Setup
Access to the Principal is granted from the Permission Set side only: the External Credential page itself has no working “grant access” control, despite appearing to.
3. Create Permission Sets
Creating the credential is not sufficient on its own. Salesforce requires an explicit grant before any user can invoke it.1. Create a Permission Set
- Label: Lusha API Access
- Open the permission set and click External Credential Principal Access
- Click Edit, move your Lusha external credential principal from Available to Enabled, and click Save
2. Assign the Permission Set
Assign it to every user who will create Leads - not only to yourself.Flow Configuration
There are 4 core sets of elements to configure within your new Flow. They are organized below to help you visualize the complete structure:
To build this flow, you must begin with a Record-Triggered Flow, and the HTTP Callout Action element, otherwise you will encounter inconsistencies when configuring your Apex Defined Variables items. Once created, you will build and connect all remaining steps around the Callout Action.

1. Begin by creating a new Flow
- Within the Salesforce Setup menu, search for Flows.
- Click the New Flow button.
- Choose your automation type. We recommend Record-Triggered Flow for automatic enrichment on creation, or Screen Flow if you would prefer to trigger enrichment manually via a button.
2. Configure the start of your Flow
- Select an Object: Lead
- Trigger the flow when: A record is created
- Set Entry Conditions:
- Condition Requirements: none [see Appendix C if you’d like requirements]
- Optimize the Flow for: Actions and Related Records
- Enable Add Asynchronous Path
Scheduled Paths will always read “2”. This is expected. The count includes the built-in Run Immediately path plus your asynchronous path. Run Immediately cannot be deleted, so simply leave it unconnected.
3. Configure the Action Element (HTTP Callout)
Add an Action element
- Click the Create HTTP Callout button
- Name: Lushav3
- Named Credential: Lusha v3
- Click Next
- Label: Enrich
- Method: POST
- Path:
/v3/contacts/search-and-enrich
- Click Next
- Sample JSON Request: [see Appendix A]
- Click Review, then click Next
- Choose Use Example Response
- Sample JSON Response: [see Appendix B]
- Click Review
- Within the Data Structure section, change the following elements to String type:
jobTitle.startDateemails.updateDatephones.updateDateresults.updateDate
- Click Save
- New Action Label: “Enrich Contact via Lusha Action”
- API Name: “Lusha”
- Set the Request Body:
- Click + New Resource
- API Name:
varRequestBody - Click Done
- Click Done, then connect Build Request Body to Lusha Enrich
4. Create the Build Request Step
Add an Assignment element ABOVE the Action Step
- Label: Build Contact
- Map the following:
Where did the
varRequestBody and varRequestItem variables come from? The varRequestBody variable was created during your configuration of the HTTP Callout step. It is an Apex-defined variable which contains the API request structure you’ll be sending to Lusha. The varRequestItem variable will need to be created now: Click + New Resource → Resource Type: Variable → API Name: varRequestItem → Data Type: Apex-Defined → Apex Class: you must search for your external service classes containing “Lushav3” and select the one ending in _IN_body_contacts → Click Done.5. Loop through the API Response from Lusha (For Each)
Add a Loop element BELOW the Action Step
- Label: “For Each”
- Collection Variable:
{!Lusha.2XX.results} - Specify Direction: First item to last item
6. Capture any Error Code
Add an Assignment element BELOW the Loop Step
- Label: “Error Code Capture Attempt”
- Map Variable/Value Pair:
varAttemptTitleEQUALS{!For_Each.jobTitle.title} - Map Variable/Value Pair:
varAttemptErrorCodeEQUALS{!For_Each.error.code}
Where did the
varAttemptTitle and varAttemptErrorCode variables come from? Both of these variables will need to be created now, but thankfully they will be simple Text variables. For both, do the following: Click + New Resource → Resource Type: Variable → API Name: varAttemptTitle or varAttemptErrorCode → Data Type: Text → Default Value: leave this field blank → Click Done. If you would like to map any additional data coming from Lusha’s API response, simply follow this same logic to create more text variables.7. Loop through the Emails (Emails Loop Attempt)
Add a Loop element BELOW the Capture Step
- Label: “Emails Loop Attempt”
- Collection Variable:
{!For_Each.emails} - Specify Direction: First item to last item
8. Capture any Email
Add an Assignment element BELOW the Loop Step
- Label: “Emails Capture”
- Map Variable/Value Pair:
varAttemptEmailEQUALS{!Loop_Attempt_Emails.email}[create this text variable]
9. Loop through the Phones (Phones Loop Attempt)
Add a Loop element BELOW the Capture Step
- Label: “Phones Loop Attempt”
- Collection Variable:
{!For_Each.phones} - Specify Direction: First item to last item
10. Capture any Phone
Add an Assignment element BELOW the Loop Step
- Label: “Phones Capture”
- Map Variable/Value Pair:
varAttemptPhoneEQUALS{!Loop_Attempt_Phones.z0number}[create this text variable]
11. Map your Variables to the Lead (Map to Lead)
Add an Assignment element on the “After Last” path of the Phone Loop Attempt
- Label: “Map to Lead”
- Map Variable/Value Pair:
{!$Record.Title}EQUALS{!varAttemptTitle} - Map Variable/Value Pair:
{!$Record.Email}EQUALS{!varAttemptEmail} - Map Variable/Value Pair:
{!$Record.Phone}EQUALS{!varAttemptPhone}
12. Confirm Any Matches (Match Found)
Add a Decision element on the “After Last” path of the For Each Loop element
- Label: “Found a Match?”
- Add a new Outcome:
- Outcome Label: “Success?”
- Condition Requirements: All Conditions Are Met (AND)
- Map Resource/Value Pair:
{!varAttemptErrorCode}Is Null{!$GlobalConstant.True}
13. Update the Lead (Update Records)
- Label: “Update Records”
- How to Find Records: Use the IDs and all field values from a record or record collection
- Record or Record Collection:
{!$Record}
Testing and Activation
Debug
Save the Flow, click Debug, and tick Run Asynchronous Paths. Without this option the entire branch you have just built is skipped and it will appear that nothing happened.Debug runs in rollback mode. Field values shown in the debug output will not persist to the record. A message reading “ready to be updated when the interview finishes” is expected and does not indicate a problem. Only a real trigger proves the write.
Activate and test
Activate the Flow, then create a Lead manually. The asynchronous path runs a few seconds after the insert commits, so fields will not populate instantly.Appendix and Reference Information
Appendix A - Sample JSON Request
Paste this as the Sample JSON Request when configuring the HTTP Callout. Flow generates Apex properties only for keys present in this sample, so it must include every identifier you might ever send.The
reveal field is deliberately omitted. The API accepts an optional reveal array to control whether emails, phones, or both are unlocked. It is an array of primitive strings, which Flow’s schema generator cannot type - including it prevents the callout from saving. Omitting it returns both emails and phones, which is the desired behaviour here.Appendix B - Sample JSON Response
Paste this as the Sample JSON Response. Select Use Example Response rather than Connect.Appendix C - Add an Entry Condition Formula
Set Condition Requirements to Formula Evaluates to True and paste the following. [See Appendix E for Suggested Custom Fields]Appendix D - Clean Up Input Domains/Websites
If your organization frequently captures inconsistent websites and domains, you can create a formula variable to automatically clean up URLs before adding them to your Lusha HTTP request. Create the following Variable Formula: formCompanyDomainwww. prefix from the Lead’s Website field so it can be sent as companyDomain.