How to integrate salesforce with teamup

January 13, 2025

banner image

After completing this unit, you will be able to:

1. Introduction

2. Steps to Integrate Teamup with Salesforce:

  • Generate a Teamup API Key

  • Get a Bearer Token in Salesforce

  • Create Named Credential

  • Insert Collection of Sub-Calendars in Salesforce

Insert Collection of Events in Salesforce

3. How our integration works.

Introduction:

In this blog, we will learn how to integrate Salesforce with Teamup. Teamup is a cloud-based calendar and scheduling app that helps teams organize and share events, availability, and work. Salesforce is a tool that businesses use to keep track of their customers, improve how they work, and grow faster. It’s a cloud-based platform, meaning you can access it from anywhere with an internet connection. Companies use Salesforce to manage sales, support customers, run marketing campaigns, and organize their work better. It's popular because it helps businesses stay organized, save time, and build stronger relationships with their customers. There's no direct built-in connection between Salesforce and Teamup. But there are ways to link them and share information. So in this blog, we will learn how to link them and schedule the retrieval of sub-calendars and events every 5 minutes using Salesforce Apex and a scheduled job.

Steps to Integrate Teamup with Salesforce:

Step 1: Generate a Teamup API Key:

  1. Firstly, go to this https://teamup.com/login then in Email fill your email address and in Organization fill your organization name.

  2. Click on the Create API Key button.

  3. Then your API Key is generated and copy it.

image1

Step 2: Get a Bearer Token in Salesforce:

Base URL: https://api.teamup.com

EndPoint: https://api.teamup.com/auth/tokens

Method: POST

HeaderValue
Acceptapplication/json
Content-Typeapplication/json
Teamup-TokenYour Teamup API Key

Body: {"app_name":"My awesome app", "device_id":"My Device", "email":"Teamup account email", "password":"Teamup account password"}

Response
{ "auth_token": "123456", "email": "doe@example.com", "name": "Jane", "avatar_type": "gravatar", "avatar_url": "https://gravatar.com/avatar/de21b8c123847c80205e93b301437b45?s=400&d=robohash&r=x", "language": "en", "is_sso": true }

Create Remote Site Settings:

  1. Go to Setup search Remote Site Settings in the quick find box and select it.

  2. Click on the New Remote Site button and fill in these fields:

FieldValue
Remote Site NameTeamup
Remote Site URLhttps://teamup.com

Click Save.

image2

Now, we need to create an apex class named TeamUpIntegration.

Modify the TeamUpIntegration file with the following code:

TeamUpIntegration.apxc
public class TeamUpIntegration { public static void bearerToken() { Http http = new Http(); HttpRequest request = new HttpRequest(); request.setMethod('POST'); request.setEndpoint('https://api.teamup.com/auth/tokens'); request.setHeader('Accept', 'application/json'); request.setHeader('Content-Type', 'application/json'); request.setHeader('Teamup-Token', 'Your Teamup API Key'); request.setBody('{"app_name":"My awesome app", "device_id":"My Device", "email":"Teamup account email", "password":"Teamup account password"}'); HttpResponse response = http.send(request); Map<String, Object> resultMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody()); String authToken = (String) resultMap.get('auth_token'); System.debug('authToken: '+authToken); } }

Enter your detail at the places of bolded text and Save.

Now execute "TeamUpIntegration.bearerToken();" from an anonymous window, then open the log and copy authToken.

Step 3: Create Named Credential:

1. Go to Setup and search Named in the quick find box, then select Named Credentials.

2. In the External Credentials tab, click on the New button.

3. Fill in the below fields:

FieldValue
LabelTeamUpExternalCredential
NameTeamUpExternalCredential
Authentication ProtocolNo Authentication

Click Save.

4. Inside principals click on the New button.

5. Fill in the below fields:

FieldValue
Parameter NamePermission
Sequence Number1

Click Save

image3

6. Search Named in the quick find box, then select Named Credentials.

7. In the Named Credentials tab, click on the New button.

8. Fill in the below fields:

FieldValue
LabelTeamUpNamedCredential
NameTeamUpNamedCredential
URLhttps://api.teamup.com
External CredentialTeamUpExternalCredential

Click Save.

image4

9. Now, create three custom headers. Click the New button inside the Custom Headers section and fill in the details as shown below.

NameAcceptAuthorizationTeamup-Token
Valueapplication/json, text/htmlBearer {Your authToken}{Your API Key}
Sequence Number123

image5

Now, we will assign permissions for external credentials to the user. Follow the steps below.

10. From Setup, in the Quick Find box, enter Permission Sets, and then select Permission Sets or enter Profiles, and then select Profiles.

11. Click the permission set or profile for which you want to enable user external credentials.

12. Take one of these steps.

For a permission set, under Apps, click Object Settings, and then click User External Credentials. For a profile, scroll to Standard Object Permissions and then select User External Credentials.

13. Select the user external credential access that you want to give this permission set or user profile.

14. Save the settings.

Step 4: Get a collection of sub-calendars:

Now, we will insert all sub-calendars from Teamup into Salesforce and schedule it to run every 5 minutes, automatically inserting new sub-calendars in the future.

Base URL: https://api.teamup.com

EndPoint: https://api.teamup.com/{calendarKeyOrId}/subcalendars

Note:- To get the Teamup calendar ID, first open your Teamup calendar and find the ID in the URL: https://teamup.com/c/{calendarId}/{calendar-name}.

Method: GET

Header Params:

HeaderValue
Acceptapplication/json, text/html
AuthorizationBearer Your_Auth_Token
Teamup-TokenYour_Teamup_API_Key
Response
{ "subcalendars": [ { "id": 12345, "name": "Peter's Schedule", "active": true, "color": 17, "overlap": true, "type": 0, "attributes": { "hash": "db94293af096df7a7106ba9c9579e428", "status": "", "feed_url": "https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics", "failure_count": "0", "next_fetch_dt": "1/5/2022, 8:12 am", "last_fetched_dt": "12/6/2021, 8:12 am", "polling_interval": 43200 }, "remote_id": "remote-id-1234-5678-90", "creation_dt": "2021-02-23T12:03:07+00:00", "update_dt": null, "readonly": false, "feed_active": true, "link_permissions": { "5809896": { "share_type": "all_subcalendars", "permission": "admin", "user_id": null }, "9015686": { "share_type": "all_subcalendars", "permission": "read_only", "user_id": null } } } ] }

Firstly, we need to create a custom object in Salesforce to store the Teamup sub-calendar data.

1. Go to Setup and inside the Object Manager tab click on Create | Custom Object.

2. Fill below data:

FieldValue
LabelTeam Calendar
Plural LabelTeam Calendars
Object NameTeam_Calendar
Record NameTeam Calendar Name

3. Check the box for Launch New Custom Tab Wizard after saving this custom object.

4. Click Save.

5. On the New Custom Object Tab page, click the Tab Style field and select a style you like. The style sets the icon to display in the UI for the object.

6. Click Next, Next, and Save.

image6

Now we can create a field on the team calendar object.

1. Go to Setup > Object Manager > Team Calendar object > Fields & Relationships > New button.

2. Select Text as the data type.

3. Fill below data:

Field LabelTeam Calendar Id
Length255
Field NameTeam_Calendar_Id
Uniquecheck
External IDcheck

click Next, Next, and Save.

image7

Now, we create a new method inside TeamUpIntegration class name insertSubCalendars.

Modify insertSubCalendars method with the following code:

TeamUpIntegration.apxc
public static void insertSubCalendars() { Http http = new Http(); HttpRequest request = new HttpRequest(); request.setMethod('GET'); request.setEndpoint('callout:TeamUpNamedCredential/{calendarId}/subcalendars'); HttpResponse response = http.send(request); Map<String, Object> deserializeResultMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody()); List<Object> deserializeResults = (List<Object>) deserializeResultMap.get('subcalendars'); List<Map<String, Object>> deserializeResultsMaps = new List<Map<String, Object>>(); for(Object obj : deserializeResults) { deserializeResultsMaps.add((Map<String, Object>) obj); } System.debug(deserializeResultsMaps); List<Team_Calendar__c> teamCalendars = new List<Team_Calendar__c>(); for(Map<String, Object> subcalendar : deserializeResultsMaps) { Team_Calendar__c teamCalendar = new Team_Calendar__c(); teamCalendar.Team_Calendar_Id__c = String.valueOf(subcalendar.get('id')); teamCalendar.Name = (String) subcalendar.get('name'); teamCalendars.add(teamCalendar); } if(!teamCalendars.isEmpty()) Upsert teamCalendars Team_Calendar_Id__c; }

Enter your detail at the places of bolded text and Save.

Now create a new queueable class name TeamUpSubCalendarsQueueable.

Modify the TeamUpSubCalendarsQueueable file with the following code:

TeamUpSubCalendarsQueueable.apxc
public class TeamUpSubCalendarsQueueable implements Queueable, Database.AllowsCallouts { public void execute(QueueableContext context) { TeamUpIntegration.insertSubCalendars(); } }

Now create a new schedulable class name TeamUpSubCalendarsSchedulable.

Modify the TeamUpSubCalendarsSchedulable file with the following code:

TeamUpSubCalendarsSchedulable.apxc
global class TeamUpSubCalendarsSchedulable implements Schedulable{ global void execute(SchedulableContext SC) { String jobID = System.enqueueJob(new TeamUpSubCalendarsQueueable()); } }

To schedule the TeamUpSubCalendarsSchedulable class to run every 5 minutes, execute the following code in the Anonymous Window:

for(Integer i = 0; i < 60; i = i+5){ String cronString = '0 ' + i + ' * * * ?'; String scheduledJobName = 'Team Up Subcalendar Integration ' + ' - '+ 'Every ' + i + ' minute'; System.schedule(scheduledJobName, cronString, new TeamUpSubCalendarsSchedulable()); }

Step 5: Insert Collection of Events in Salesforce:

Now, we will insert events of two days from Teamup into Salesforce and schedule it to run every 5 minutes, automatically inserting new events in the future.

Base URL: https://api.teamup.com

EndPoint: https://api.teamup.com/{calendarKeyOrId}/events?startDate={startDate}&endDate={endDate}

EndPoint Parameters:

startDate: string<date> (Optional) The start of the date range to list events from, in YYYY-MM-DD format. If not specified this defaults to today

endDate: string<date> (Optional) The end of the date range to list events from (inclusive), in YYYY-MM-DD format. If not specified this defaults to tomorrow

calendarKeyOrId: string (Required) To get the Teamup calendar ID, first open your Teamup calendar and find the ID in the URL: https://teamup.com/c/{calendarId}/{calendar-name}.

Method: GET

Header Params:

HeaderValue
Acceptapplication/json, text/html
AuthorizationBearer Your_Auth_Token
Teamup-TokenYour_Teamup_API_Key
{ "events": [ { "id": "string", "subcalendar_ids": [], "subcalendar_remote_ids": null, "start_dt": "string", "end_dt": "string", "all_day": false, "rrule": "", "creation_dt": "string", "update_dt": "string", "delete_dt": "2019-08-24T14:15:22Z", "tz": "string", "version": "string", "remote_id": "string", "series_id": 0, "ristart_dt": "string", "rsstart_dt": "string", "attachments": [ { "id": "string", "name": "string", "size": 0, "mimetype": "string", "upload_date": "2019-08-24T14:15:22Z", "thumbnail": "https://example.com/{keyId}/attachments/{attachmentId}}/thumbnail/file.jpg?hash={hash}", "link": "https://example.com/{keyId}/attachments/{attachmentId}}/file.jpg?hash={hash}", "preview": "https://example.com/{keyId}/attachments/{attachmentId}}/preview/file.jpg?hash={hash}&size={size}" } ], "title": "string", "location": "string", "who": "string", "readonly": true, "signup_enabled": true, "signup_deadline": "2019-08-24T14:15:22Z", "signup_visibility": "all_users", "signup_limit": 0, "comments_enabled": true, "comments_visibility": "all_users", "custom": { "field1": "value", "choicefield": [ "a", "b" ] }, "comments": [ { "id": 35081, "event_id": "53809 or 53809-rid-1728574025", "name": "Peter", "email": "peter@example.org", "message": "\\u003Cp\\u003EHi Mark, I need a projector for my presentation. Thanks\\u003C\\/p\\u003E", "remote_id": "string", "creation_dt": "2019-08-24T14:15:22Z", "update_dt": "2019-08-24T14:15:22Z", "updater": "Peter" } ], "signups": [ { "id": 4930, "event_id": 53809, "name": "Mark", "email": "mark@example.org", "remote_id": "string", "creation_dt": "2019-08-24T14:15:22Z", "update_dt": "2019-08-24T14:15:22Z", "email_hash": "eb88aebd18089396d068a498a66dd7fe" } ] } ], "timestamp": 0 }

First, we create new fields on the Task object where we can store our data. To create these fields, follow the steps below:

1. Go to Setup > Object Manager > Activity Object > Fields & Relationships > New button.

2. Create below five fields:

FieldEnd DateLocationStart DateTeam CalendarTeamup Event
Data TypeTextTextTextLookup(Team Calendar)Text
Field LabelEnd DateLocationStart DateTeam CalendarTeamup Event
Length255255255NONE255
Field NameEnd_Date__cLocation__cStart_Date__cTeam_Calendar__cTeamup_Event__c
External IDFalseFalseFalseFalseTrue
UniqueFalseFalseFalseFalseTrue

click Next, Next, and Save.

image8

Now, we create new methods inside TeamUpIntegration class. These methods are as follows:

TeamUpIntegration.apxc
public static void insertEventsCollection() { List<Contact> contacts = new List<Contact>(); List<Task> tasks = new List<Task>(); Date startDate = System.Today(); Date endDate = System.Today().addDays(1); String formatedStartDate = startDate.year()+'-'+startDate.month()+'-'+startDate.day(); String formatedEndDate = endDate.year()+'-'+endDate.month()+'-'+endDate.day(); Http http = new Http(); HttpRequest request = new HttpRequest(); request.setMethod('GET'); request.setEndpoint('callout:TeamUpNamedCredential/{calendarId}/events?startDate='+formatedStartDate+'&endDate='+formatedEndDate); HttpResponse response = http.send(request); System.debug(response.getBody()); Map<String, Object> deserializeResultMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody()); List<Object> deserializeResults = (List<Object>) deserializeResultMap.get('events'); List<Map<String, Object>> deserializeResultsMap = new List<Map<String, Object>>(); for(Object obj : deserializeResults) { deserializeResultsMap.add((Map<String, Object>) obj); } tasks = createTask(deserializeResultsMap); } private static Contact searchContact(String dataToSearch) { if(dataToSearch == null || dataToSearch == '') return null; List<Contact> conRec = new List<Contact>(); conRec = [Select id, Email, Phone, MobilePhone,Name From Contact where Email=:dataToSearch]; if(conRec.size() == 0) { String lastTenNumbers; String onlyNumbers = dataToSearch.replaceAll('[^0-9]', ''); if (onlyNumbers.length() >= 10) lastTenNumbers = onlyNumbers.substring(onlyNumbers.length() - 10); System.debug('lastTenNumbers: '+lastTenNumbers); String searchQuery = 'FIND \'' + lastTenNumbers + '\' IN PHONE FIELDS RETURNING Contact(Id, Phone, MobilePhone, email, Name)'; List<List<Contact>> searchList = search.query(searchQuery); if(searchList.size() > 0 && searchList[0].size() > 0) conRec = searchList[0]; System.debug('searchList: '+searchList); } if(!conRec.isEmpty()) { return conRec[0]; } else return null; } public static List<Task> createTask(List<Map<String, Object>> deserializeResultsMap) { List<Task> tasks = new List<Task>(); List<Contact> getUpdatedContacts = [SELECT Id, FirstName, LastName FROM Contact ORDER BY createdDate desc]; List<Team_Calendar__c> teamCalendars = [SELECT Id, Name, Team_Calendar_Id__c FROM Team_Calendar__c]; for(Map<String, Object> obj : deserializeResultsMap) { String name = (String) obj.get('who'); Contact contact = searchContact(name); for(Team_Calendar__c teamCalendar : teamCalendars) { if(Integer.valueOf(teamCalendar.Team_Calendar_Id__c) == obj.get('subcalendar_id')) { Task task = new Task(); task.Subject = (String) obj.get('title'); task.Start_Date__c = (String) obj.get('start_dt'); task.End_Date__c = (String) obj.get('end_dt'); task.Location__c = (String) obj.get('location'); task.Description = ((String)obj.get('notes')).stripHtmlTags(); task.Status = 'Completed'; if(contact != null) task.WhoId = contact.Id; else task.WhoId = null; task.Teamup_Event__c = (String)obj.get('id'); task.Team_Calendar__c = teamCalendar.id; createAttachment(obj.get('attachments'), task); } } } return tasks; } public static void createAttachment(Object allAttachmentsObj, Task taskRecord) { upsert taskRecord Teamup_Event__c; List<Map<String, Object>> attachmentsMap = new List<Map<String, Object>>(); if(allAttachmentsObj != null) { List<Object> allAttachments = (List<Object>)allAttachmentsObj; for(Object att : allAttachments) { attachmentsMap.add((Map<String, Object>) att); } } for(Map<String, Object> att : attachmentsMap) { Map<String, String> attachmentDataMap = new Map<String, String>(); attachmentDataMap.put('Link', (String) att.get('link')); attachmentDataMap.put('ParentId', taskRecord.Id); attachmentDataMap.put('Name', (String) att.get('name')); attachmentDataMap.put('ContentType', (String) att.get('mimetype')); attachmentDataMap.put('Description', (String) att.get('id')); attachmentCallout(attachmentDataMap); } } @future(callout = true) public static void attachmentCallout(Map<String, String> attachmentDataMap) { Http h = new Http(); HttpRequest req = new HttpRequest(); req.setMethod('GET'); req.setEndpoint(attachmentDataMap.get('Link')); HttpResponse res = h.send(req); Attachment attachment = new Attachment(); attachment.ParentId = attachmentDataMap.get('ParentId'); attachment.Name = attachmentDataMap.get('Name'); attachment.Body = res.getBodyAsBlob(); attachment.ContentType = attachmentDataMap.get('ContentType'); attachment.Description = attachmentDataMap.get('Description'); Boolean insertAttachment = True; List<Attachment> attachments = [SELECT Id, ParentId, Description FROM Attachment WHERE ParentId = :attachment.ParentId]; for(Attachment att : attachments) { if(attachment.Description == att.Description) insertAttachment = False; } if(insertAttachment) insert attachment; }

Enter your detail at the places of bolded text and Save.

Now create a new queueable class name TeamUpEventsQueueable.

Modify the TeamUpEventsQueueable file with the following code:

TeamUpEventsQueueable.apxc
public class TeamUpEventsQueueable implements Queueable, Database.AllowsCallouts { public void execute(QueueableContext context) { TeamUpIntegration.insertEventsCollection(); } }

Now create a new schedulable class name TeamUpEventsSchedulable.

Modify the TeamUpEventsSchedulable file with the following code:

TeamUpEventsSchedulable.apxc
global class TeamUpEventsSchedulable implements Schedulable { global void execute(SchedulableContext SC) { String jobID = System.enqueueJob(new TeamUpEventsQueueable()); } }

To schedule the TeamUpEventsSchedulable class to run every 5 minutes, execute the following code in the Anonymous Window:

for(Integer i = 0; i < 60; i = i+5){ String cronString = '0 ' + i + ' * * * ?'; String scheduledJobName = 'Team Up Event Integration ' + ' - '+ 'Every ' + i + ' minute'; System.schedule(scheduledJobName, cronString, new TeamUpEventsSchedulable()); }

How our integration works:

1. To link a Teamup event with a contact in Salesforce:

First, create the contact in Salesforce and fill in the Email or Phone field.

2. Next, create an event in Teamup and enter all the necessary details.

In the Who field, provide either the Email or Phone of the contact.

3. For example, if you enter an Email in the Who field in Teamup, and a contact with that email exists in Salesforce, our automation will create a task linked to that contact.

4. If no contact is found with the specified email or phone, our automation will still create the task, but it will not be linked to any contact.

Output:

gif

Free Consultation