-
-
Notifications
You must be signed in to change notification settings - Fork 0
Email Tracking
List and create email tracking records in Teamleader Focus.
The Email Tracking resource lets you log outbound emails against Teamleader entities, maintaining a complete communication history alongside deals, contacts, companies, and other records. Records can be listed per subject and created with optional file attachments.
update() and delete() are not supported β there are no API endpoints for them.
emailTracking
| Capability | Supported |
|---|---|
| Pagination | β Supported |
| Filtering | β Supported (subject filter) |
| Sorting | β Not supported |
| Sideloading | β Not supported |
| Creation | β Supported |
| Update | β Not supported |
| Deletion | β Not supported |
API filter requirement:
list()always sends afilterobject in the request body, even when no filters are provided. When called without filters it sends an empty object β this is required by the Teamleader API.
Returns email tracking records for a subject. Accepts the subject filter in two formats β nested object or flat underscore keys.
use McoreServices\TeamleaderSDK\Facades\Teamleader;
// Nested object form (recommended)
$emails = Teamleader::emailTracking()->list([
'subject' => [
'type' => 'contact',
'id' => 'contact-uuid',
],
]);
// Flat underscore form (also accepted)
$emails = Teamleader::emailTracking()->list([
'subject_type' => 'company',
'subject_id' => 'company-uuid',
]);
// With pagination
$emails = Teamleader::emailTracking()->list(
['subject' => ['type' => 'deal', 'id' => 'deal-uuid']],
['page_size' => 50, 'page_number' => 1]
);
// Without filters β returns all accessible records
$emails = Teamleader::emailTracking()->list();Creates an email tracking record. Validates all fields before sending the request. Subject ID and attachment IDs are format-validated as UUIDs.
Required fields:
| Field | Type | Description |
|---|---|---|
subject |
array | Object with type and id
|
subject.type |
string | Subject type β see Subject Types |
subject.id |
string | Subject UUID β validated as UUID format |
title |
string | Email subject line |
content |
string | Email body |
Optional fields:
| Field | Type | Description |
|---|---|---|
attachments |
array | Array of file UUIDs β each validated as UUID format |
// Basic record
$email = Teamleader::emailTracking()->create([
'subject' => ['type' => 'contact', 'id' => 'contact-uuid'],
'title' => 'Follow-up on our meeting',
'content' => 'Hi Sarah, great to meet you today...',
]);
// With attachments
$email = Teamleader::emailTracking()->create([
'subject' => ['type' => 'deal', 'id' => 'deal-uuid'],
'title' => 'Proposal attached',
'content' => 'Please find our proposal document below.',
'attachments' => ['file-uuid-1', 'file-uuid-2'],
]);forSubject() is the generic list helper. Note that it does not validate the subject type β an invalid type will reach the API and return an error there rather than being caught locally.
// Generic β any valid subject type
$emails = Teamleader::emailTracking()->forSubject('contact', 'contact-uuid');
// With pagination
$emails = Teamleader::emailTracking()->forSubject('deal', 'deal-uuid', [
'page_size' => 50,
'page_number' => 1,
]);Subject type is validated before the request for all create helpers.
| Method | Subject type |
|---|---|
createForContact(string $id, string $title, string $content, array $attachments = []) |
contact |
createForCompany(string $id, string $title, string $content, array $attachments = []) |
company |
createForDeal(string $id, string $title, string $content, array $attachments = []) |
deal |
Teamleader::emailTracking()->createForContact(
'contact-uuid',
'Introductory email',
'Hi, thanks for connecting...'
);
Teamleader::emailTracking()->createForDeal(
'deal-uuid',
'Revised proposal',
'Please find the updated figures attached.',
['file-uuid']
);$types = Teamleader::emailTracking()->getAvailableSubjectTypes();| Type | Description |
|---|---|
contact |
Contact |
company |
Company |
deal |
Deal |
invoice |
Invoice |
creditNote |
Credit note |
subscription |
Subscription |
product |
Product |
quotation |
Quotation |
nextgenProject |
Project (v2) |
Subject type is validated on create() calls. An InvalidArgumentException is thrown for any value not in this list.
forSubject()does not validate the type β only creation methods do. Pass an invalid type toforSubject()and the error will come from the API, not the SDK.
[
'data' => [
[
'id' => 'email-tracking-uuid',
'subject' => ['type' => 'contact', 'id' => 'contact-uuid'],
'title' => 'Follow-up on our meeting',
'content' => 'Hi Sarah, great to meet you today...',
'created_at' => '2025-03-10T09:15:00+00:00',
],
],
'meta' => [
'page' => ['size' => 20, 'number' => 1],
'matches' => 6,
],
][
'data' => [
'type' => 'emailTracking',
'id' => 'email-tracking-uuid',
],
]// Send via your mail service, then log in Teamleader
Mail::to($recipient)->send(new ProposalMail($deal));
Teamleader::emailTracking()->createForDeal(
$deal->teamleader_id,
'Proposal: ' . $deal->name,
$emailBody
);// Upload the file first via the Files resource
$upload = Teamleader::files()->upload('proposal.pdf', 'deal', 'deal-uuid');
// PUT file to $upload['data']['location'] ...
// Then create the tracking record with the file UUID
Teamleader::emailTracking()->createForDeal(
'deal-uuid',
'Proposal attached',
'Please find our proposal below.',
[$fileId]
);$all = [];
$page = 1;
do {
$response = Teamleader::emailTracking()->forSubject('company', 'company-uuid', [
'page_size' => 100,
'page_number' => $page,
]);
$all = array_merge($all, $response['data']);
$page++;
} while (count($response['data']) === 100);$emails = Teamleader::emailTracking()->forSubject('deal', 'deal-uuid');
$notes = Teamleader::notes()->forDeal('deal-uuid');
$timeline = array_merge($emails['data'], $notes['data']);
usort($timeline, fn($a, $b) => strcmp($a['created_at'], $b['created_at']));use InvalidArgumentException;
use McoreServices\TeamleaderSDK\Exceptions\TeamleaderException;
// Invalid subject type β thrown before the request on create
try {
Teamleader::emailTracking()->create([
'subject' => ['type' => 'meeting', 'id' => 'uuid'], // invalid
'title' => 'Subject',
'content' => 'Body',
]);
} catch (InvalidArgumentException $e) {
// "Invalid subject type 'meeting'. Must be one of: contact, company, ..."
Log::error($e->getMessage());
}
// Invalid UUID format β thrown before the request
try {
Teamleader::emailTracking()->create([
'subject' => ['type' => 'contact', 'id' => 'not-a-uuid'],
'title' => 'Subject',
'content' => 'Body',
'attachments' => ['also-not-a-uuid'],
]);
} catch (InvalidArgumentException $e) {
// 'Subject ID must be a valid UUID' or 'All attachment IDs must be valid UUIDs'
Log::error($e->getMessage());
}
// API-level errors
try {
$emails = Teamleader::emailTracking()->forSubject('contact', 'contact-uuid');
} catch (TeamleaderException $e) {
Log::error('Teamleader error', ['message' => $e->getMessage()]);
}- Notes β Text notes on entities (similar pattern, different data)
- Files β Upload attachments before referencing them here
- Companies β Email tracking can be attached to companies
- Contacts β Email tracking can be attached to contacts
- Deals β Email tracking can be attached to deals
- Filtering β Filter and pagination reference
Last Updated: August 2026 β’ SDK Version: 2.2.2 β’ Made with β€οΈ by MCore Services
- Departments
- Users
- Teams
- Custom Fields
- Work Types
- Document Templates
- Currencies
- Notes
- Email Tracking
- Closing Days
- Day Off Types
- Days Off
- User Schedules
- Invoices
- Credit Notes
- Subscriptions
- Payment Methods
- Payment Terms
- Tax Rates
- Withholding Tax Rates
- Commercial Discounts
Next Gen Projects
Legacy Projects