---
title: "Configuring an integration with TeamLeader"
canonical: "https://help.fieldbuddy.com/space/FBDOCS/2078310848/Configuring%20an%20integration%20with%20TeamLeader"
format: markdown
---
> ❌ Raw instructions for configuring TeamLeader V2.

### General remarks

- TeamLeader currently has 2 active API's: V1 & V2.
- V1 uses ID's that are auto-number formatted per object. V2 uses UID's. (A "migration service" is available in the V2 documentation, which can used to convert V1 ID's to V2 Ids ([https://developer.teamleader.eu/#/reference/other/migrating/migrate.id](https://developer.teamleader.eu/#/reference/other/migrating/migrate.id)).)
- Supported TeamLeader integration in FlexConnect: TeamLeader API V2. Documentation: [https://developer.teamleader.eu/](https://developer.teamleader.eu/)
- API V2 works via requests to the API with URI format "<object_name>.<method_name>" (for example "companies.list").
- In contrary to many other integrations, you cannot make requests for certain fields only. API V2 returned records contain all fields made available for that method.
- API V2 returned data does not (always) contain information about pagination. When requesting a list of records, integration will keep requesting the next page for as long as that page returns records.
- Currently supported and tested inbound sync methods: "list" & "info". See chapter "Inbound Synchronization" for more information.
- Currently supported and tested outbound sync methods: "add", "update" & "delete". See  chapter "Outbound Synchronization" for more information.

# Configuring Service Provider & Service User

1. Create Service Provider as per example:
  
  1. Note difference between Auth and API endpoints: APP.teamleader vs API.teamleader.
  2. Provide Client ID and Client Secret as given in TeamLeader account.
2. Create Service User by pressing "Authorize User" and following the steps shown.

# Configuring Object Mappings

## <span style="color: #000000">Inbound synchronization</span>

Currently supported and tested inbound sync methods: "list" & "info".

- Method "list" returns JSON with key data which contains a list: { "data": [ {"id":"x", etc. }, {"id":"y", etc. }, {"id":"z", etc. } ]. No information about amount of results/pagination is given. See examples below.
- Method "info" returns JSON with key data which contains 1 single record: { "data": {"id":"x", etc. } ]. See examples below.
- Records retrieved with method "list" do not contain all available fields & child records that method "info" has to offer.
- To retrieve all available data, following structure is implemented for inbound operations:
  - Parent Object Mapping: "list" method. All available records (with limited fields) are synced in batch start.
  - Sub Object Mapping(s): "info" method. Records that were synced in batch start have an id. Based on that id, individual ".info" requests are made to get all available data of each record. These requests are made in each batch execute.
  - Child mappings for both Parent and Sub Object Mappings: Used to parse child records that are returned as part of the main synced records by TeamLeader.
  - Both Sub Object and Child Object Mappings are technically mappings under Parent Object Mapping. In Sub Object Mapping it is possible to reference extra fields with .info request, which are not available in .list request, so it is optional. In Child Object Mapping it is possible to retrieve (array) fields that have multiple lines/data within that field. For example addresses, which can contain multiple addresses or Emails which can contain multiple emails.

Example responses for companies and contacts:

<details>
<summary>Example response for "companies.list"</summary>

```javascript
{
  "data": [
    {
      "id": "39d82796-4461-0e15-aa79-0dd5917cd6e4",
      "name": "Teamleader",
      "business_type": null,
      "vat_number": "BE 0899.623.035",
      "emails": [
        {
          "type": "primary",
          "email": "info@teamleader.eu"
        }
      ],
      "telephones": [
        {
          "type": "phone",
          "number": "+31 85 888 1677"
        }
      ],
      "website": "http://www.teamleader.eu",
      "iban": null,
      "bic": null,
      "language": "en",
      "payment_term": null,
      "preferred_currency": null,
      "invoicing_preferences": {
        "electronic_invoicing_address": null
      },
      "added_at": "2019-01-08T09:46:16+00:00",
      "updated_at": "2019-01-08T09:46:16+00:00",
      "web_url": "https://app.teamleader.eu/company_detail.php?id=39d82796-4461-0e15-aa79-0dd5917cd6e4",
      "primary_address": {
        "line_1": "Dok Noord 3A/101",
        "postal_code": "9000",
        "city": "Gent",
        "country": "BE"
      },
      "responsible_user": null,
      "tags": [],
      "local_business_number": null
    },
    {
      "id": "c3f9921f-04f2-00d9-b479-0d78317cd6e9",
      "name": "Sodafizz",
      "business_type": {
        "type": "businessType",
        "id": "5ac47928-4ca7-0cba-9427-e060accc9a3b"
      },
      "vat_number": null,
      "emails": [
        {
          "type": "primary",
          "email": "e.frankenberger@Sodafizz.com"
        }
      ],
      "telephones": [
        {
          "type": "phone",
          "number": "+1 202-555-0188"
        }
      ],
      "website": "www.sodafizz.com",
      "iban": null,
      "bic": null,
      "language": "nl",
      "payment_term": {
        "type": "after_invoice_date",
        "days": 14
      },
      "preferred_currency": null,
      "invoicing_preferences": {
        "electronic_invoicing_address": null
      },
      "added_at": "2019-01-08T09:46:19+00:00",
      "updated_at": "2019-01-08T09:46:19+00:00",
      "web_url": "https://app.teamleader.eu/company_detail.php?id=c3f9921f-04f2-00d9-b479-0d78317cd6e9",
      "primary_address": {
        "line_1": "11 North Walcott Ave",
        "postal_code": "60612",
        "city": "Chicago",
        "country": "US"
      },
      "responsible_user": {
        "type": "user",
        "id": "0cae60aa-963e-036a-8c5e-ff844353782b"
      },
      "tags": [
        "client",
        "lead"
      ],
      "local_business_number": null
    }
  ]
}
```
</details>

<details>
<summary>Example response for "companies.info"</summary>

```javascript
{
  "data": {
    "id": "99c3b258-58fe-0246-8f77-c09cd17cd6ea",
    "name": "Peterson Paper",
    "business_type": {
      "type": "businessType",
      "id": "5ac47928-4ca7-0cba-9427-e060accc9a3b"
    },
    "vat_number": null,
    "emails": [
      {
        "type": "primary",
        "email": "hpeterson@petersonpaper.co.uk"
      }
    ],
    "telephones": [
      {
        "type": "phone",
        "number": "+1 202-555-0134"
      }
    ],
    "website": "http://www.petersonpaper.co.uk/",
    "iban": null,
    "bic": null,
    "language": "nl",
    "payment_term": {
      "type": "after_invoice_date",
      "days": 14
    },
    "preferred_currency": null,
    "invoicing_preferences": {
      "electronic_invoicing_address": null
    },
    "added_at": "2019-01-08T09:46:20+00:00",
    "updated_at": "2019-01-08T09:46:20+00:00",
    "web_url": "https://app.teamleader.eu/company_detail.php?id=99c3b258-58fe-0246-8f77-c09cd17cd6ea",
    "remarks": "Peterson Paper is a family-owned paper company located in Charlton, greater London, with 20 employees. Some financial difficulties in 2010, now back on track and expanding.",
    "marketing_mails_consent": false,
    "addresses": [
      {
        "type": "primary",
        "address": {
          "line_1": "Nettleton Road 201",
          "postal_code": "8620",
          "city": "Charlton",
          "country": "ZZ"
        }
      }
    ],
    "responsible_user": {
      "type": "user",
      "id": "0cae60aa-963e-036a-8c5e-ff844353782b"
    },
    "tags": [
      "client",
      "lead"
    ],
    "custom_fields": [],
    "local_business_number": null
  }
}
```
</details>

<details>
<summary>Example response for "contacts.list"</summary>

```javascript
{
  "data": [
    {
      "id": "10263516-4e96-0b21-917a-a35011bc98e2",
      "first_name": "Albert",
      "last_name": "Johnson",
      "emails": [
        {
          "type": "primary",
          "email": "a.johnson@verizon.com"
        }
      ],
      "salutation": null,
      "telephones": [
        {
          "type": "mobile",
          "number": "+1 202-585-0157"
        }
      ],
      "website": null,
      "gender": "male",
      "birthdate": "1959-09-07",
      "iban": null,
      "bic": null,
      "language": "en",
      "payment_term": null,
      "invoicing_preferences": {
        "electronic_invoicing_address": null
      },
      "added_at": "2019-01-08T09:46:16+00:00",
      "updated_at": "2019-01-08T09:46:16+00:00",
      "web_url": "https://app.teamleader.eu/contact_detail.php?id=10263516-4e96-0b21-917a-a35011bc98e2",
      "primary_address": {
        "line_1": "308 Elliott Fitzgerald Lane",
        "postal_code": "87111",
        "city": "Albuquerque",
        "country": "US"
      },
      "tags": [
        "lead",
        "reseller"
      ]
    },
    {
      "id": "5138616c-5fc7-0803-9878-b603a1bc98e1",
      "first_name": "Jeroen",
      "last_name": "De Wit",
      "emails": [
        {
          "type": "primary",
          "email": "sales@teamleader.nl"
        }
      ],
      "salutation": null,
      "telephones": [
        {
          "type": "mobile",
          "number": "+31 85 888 2980"
        }
      ],
      "website": null,
      "gender": "male",
      "birthdate": null,
      "iban": null,
      "bic": null,
      "language": "en",
      "payment_term": null,
      "invoicing_preferences": {
        "electronic_invoicing_address": null
      },
      "added_at": "2019-01-08T09:46:16+00:00",
      "updated_at": "2019-01-08T09:46:16+00:00",
      "web_url": "https://app.teamleader.eu/contact_detail.php?id=5138616c-5fc7-0803-9878-b603a1bc98e1",
      "primary_address": {
        "line_1": null,
        "postal_code": null,
        "city": null,
        "country": "BE"
      },
      "tags": []
    }
  ]
}
```
</details>

<details>
<summary>Example response for "contacts.info"</summary>

```javascript
{
  "data": {
    "id": "10263516-4e96-0b21-917a-a35011bc98e2",
    "first_name": "Albert",
    "last_name": "Johnson",
    "emails": [
      {
        "type": "primary",
        "email": "a.johnson@verizon.com"
      }
    ],
    "salutation": null,
    "telephones": [
      {
        "type": "mobile",
        "number": "+1 202-585-0157"
      }
    ],
    "website": null,
    "gender": "male",
    "birthdate": "1959-09-07",
    "iban": null,
    "bic": null,
    "language": "en",
    "payment_term": null,
    "invoicing_preferences": {
      "electronic_invoicing_address": null
    },
    "added_at": "2019-01-08T09:46:16+00:00",
    "updated_at": "2019-01-08T09:46:16+00:00",
    "web_url": "https://app.teamleader.eu/contact_detail.php?id=10263516-4e96-0b21-917a-a35011bc98e2",
    "remarks": "CMO of Johnson's Cigar Shoppe. Interested in new website plus webshop. Decision maker.",
    "marketing_mails_consent": false,
    "addresses": [
      {
        "type": "primary",
        "address": {
          "line_1": "308 Elliott Fitzgerald Lane",
          "postal_code": "87111",
          "city": "Albuquerque",
          "country": "US"
        }
      }
    ],
    "companies": [
      {
        "position": "CMO",
        "decision_maker": false,
        "company": {
          "type": "company",
          "id": "e643bf03-e49f-08e6-ad7f-ab88a17cd6e6"
        }
      }
    ],
    "tags": [
      "lead",
      "reseller"
    ],
    "custom_fields": []
  }
}
```
</details>

Below are examples of configuring object mappings for companies (SF: accounts) & contacts (SF: contacts).

### Parent object mapping

- Requests for parent object mappings are made in batch start.
- Objects Per Page Request sets the amount of companies to retrieve per request. Default: 20.
- Maximum page requests sets the maximum amount of pages to retrieve. Default: 9999.
- Batch size: sets the amount of records that are handled in each batch (execute). Please take note that if sub mappings are created, like for URI "companies.info", the batch size actually sets the amount of requests that are done in that batch as well. Take care not to set the number to high or batch execute time limit may be exceeded.
- Response of ".list" requests will return a list of records in key "data". To compare: ".info" returns a single record only in "data" key.
- Example for Companies / Accounts:
- Example for Contacts / Contacts:

### Child object mapping

- If one of the keys of a record contains a list, create a child mapping to parse these child records.
- Received child records seem to lack id's as far as tested in this integration so far.
- Child mappings are defined as such by:
  - Setting a Parent Object Mapping.
  - Setting the exact same Endpoint URI as the Parent Object Mapping.
  - Defining a relationship name in "Internal Object".
- Child mappings that not fully fit these criteria, will be seen as "Sub Object Mappings".
- Child records will be automatically linked to the parent record, based on the Internal Objects specified Relationship Name.
- Example for Account - Emails (see example TL response above).

### Sub Object Mappings

- For each record retrieved in the batch start (based on parent mapping), a new request will be made in batch (execute) based on this sub object mapping(s).
- Request body of these requests is specified in "Filter Criteria". Standard request body for ".info" requests is as in example below. "{!PARENT_EXT_ID}" will be replaced by the actual record external id of each record retrieved in batch start.
- Sub mappings are defined as such by:
  - Setting a Parent Object Mapping.
  - Setting a different Endpoint URI in comparison to the Parent Object Mapping.
- Child mappings that not fully fit these criteria, will be seen as "Child Mapping" for the Parent Object Mapping.
- Response of requests will return a single record only. In this case "data" key contains an object which is the actual record. To compare: ".list" returns a list in "data" key.
- Max Page requests, objects per page request and batch size fields are <u>not</u> used and do not affect the way of performing requests in any way.
- Example Sub Object Mapping for Account Info:
- Example Sub Object Mapping for Contact Info:
  
- For **V1** objects it's possible to create/update not all retrieved records, but only records that meet the criteria.  
Criteria should be entered in field **Filter criteria** as a key/value pair. If this field is empty, then all records are processed.  
**Key** can be defined both as single field and "deep" field in case of arrays.  
Example: "some_record": { "name": "CompanyName", "address": { "street": "Dijkstraat", "city": "Amsterdam" } }. Keys: "name", "address.city" and "address.street".  
**Value** - the value contained in the field (defined by the key) with which records will be created. All records with a different value in the corresponding field (defined by the key) will be skipped.  
The separator can be the symbol **=** - exact correspondence of the value to the given and **~** - the received value contains the given value.  
Examples:
  - <span style="color: #000000">custom_fields.147292=331430</span>
  - <span style="color: #000000">name~John</span>

### Sub Child Object Mappings

- Defined just like normal child object mappings, but parent object mapping references a sub object mapping (like "Contact Info").

### Field Mappings for Inbound Object Mappings

- External fields can be defined both as single field and "deep" field in case of arrays. Example: "some_record": { "name": "CompanyName", "address": { "street": "Dijkstraat", "city": "Amsterdam" } }
  - Mappings can be made with external fields set to "name", "address.city" and "address.street".
- Standard field mapping:
- Field mapping that can be used as external mapping field:
  
  - All tested child records that are returned by TeamLeader do not have an Id. They, however, sometimes contain a field which makes them unique for that record. For example: for emails of contacts, a type is given. This type is unique per contact: there is only 1 email with type "primary". If this is the case, "Is External Mapping Field" can be ticked. During sync, although not having an Id set, existing SF email record with type "primary" for the respective contact will be overwritten by the just synced one. If more fields have "Is External Mapping Field" set, a combination of these fields makes the unique combination on which upserts are executed.
- Reference field mapping (lookups):
  
  - Set internal, external fields, parent reference external id field and parent reference object name, tick Is Parent Referenced.

## Outbound synchronization

Currently supported and tested outbound sync methods: "add", "update" and "delete".

- In case an outbound operation fails, Last Sync Datetime API will not be set and Sync Check API checkbox will be set to false.
- Outbound sync does not make use of "sub mappings" like in inbound synchronization. It is just parent and child mappings like any other integration.

### Insert operation

- Example mapping for insert of account records.

### Update operation

- Example mapping for update of account records:
- Example field mappings for parent mapping:
  - Notice that outbound arrays can be created as well with dot separated fields/keys in external field. "address.city" will create an object like { "id", "address": { "city": "Amsterdam" } }.
- Example child mapping:
  
  - Set parent mapping & internal object to relationship name.

### Delete operation

- Example mapping for account delete:
  
  - No field mappings are required.