Notes & tasks
Write notes and log calls, emails and meetings on jobs, contacts and customers; read activity logs and customer history; create and complete follow-ups.
View as MarkdownThree kinds of records live here:
- Notes and logged interactions. A team note on a job, or a call / email / meeting / site visit that already happened. Calls, emails and meetings logged on a job also land on the customer's and the person's feed, exactly as when they are logged in the app. Logging records the conversation; nothing here sends an email or a text.
- Activity and history. A job's activity log (stage moves, notes, task lines, files) and a customer's or person's merged history (emails and texts, calls, notes, follow-ups, stage moves, proposals, signatures, invoices).
- Follow-ups (tasks). Job follow-ups (
/v1/tasks) and company follow-ups that need no job (/v1/account-tasks). They show in each person's My day queue and send the assignee a reminder.
API writes act as the user who created the API key: notes and completed follow-ups show that person as the author.
Note
Partner keys that act for several workspaces must also send firm_id (query string, or JSON body on writes).
Lists return {"data": [...], "pagination": {...}} (default 50, max 200). Timestamps are UTC ISO 8601 with Z.
Job notes and activity#
The activity object#
| Field | Type | Description |
|---|---|---|
id |
integer | TruTec id. |
job_id |
integer | The job. |
type |
string | note, call, email, meeting, site_visit, status_change, task, created, details_updated, assigned, ... |
content |
string or null | The text. |
is_team_note |
boolean | An authored team note (not a system line). |
user |
object or null | {id, name} of the author. |
details |
object | Extras when present: old_status, new_status, outcome (call outcome, or a lost reason's answers), phone, task_id, customer_response, ... |
created_at |
string | UTC. |
List job activity#
GET /v1/jobs/{job_id}/activity
Permission: Read jobs
Everything on the job's activity log, newest first.
| Name | Type | Required | Description |
|---|---|---|---|
type |
string | No | Comma-separated types to keep, e.g. status_change,call. |
created_after |
string | No | ISO 8601. |
limit, offset |
integer | No | Paging. |
{
"data": [
{
"id": 990211,
"job_id": 41872,
"type": "call",
"content": "Left voicemail · 512-555-0142\nWill try Thursday",
"is_team_note": false,
"user": {"id": 118, "name": "Dana Whitfield"},
"details": {"source": "click_to_call", "outcome": "left_voicemail", "phone": "512-555-0142"},
"created_at": "2026-10-12T15:10:44Z"
}
],
"pagination": {"total": 1, "limit": 50, "offset": 0}
}
List job notes#
GET /v1/jobs/{job_id}/notes
Permission: Read jobs
What people wrote: team notes plus logged calls, emails, meetings and site visits (no system lines). Same parameters as the activity list.
Add a job note or log a call#
POST /v1/jobs/{job_id}/notes
Permission: Write jobs
| Name | Type | Required | Description |
|---|---|---|---|
content |
string | Yes | Up to 8,000 characters. |
type |
string | No | note (default), call, email, meeting or site_visit. |
outcome |
string | No | Calls: e.g. connected, left_voicemail, no_answer. Shown before the text. |
phone |
string | No | Calls: the number dialed. |
customer_response |
boolean | No | The customer replied (calls, emails, meetings). Stops the job's automatic sales sequence, as in the app. |
task_id |
integer | No | A follow-up on this job: the entry becomes that follow-up's notes. |
complete_task |
boolean | No | With task_id: also complete it. Default true. |
curl -X POST "https://trutec.ai/api/v1/jobs/41872/notes" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"type": "call", "outcome": "left_voicemail", "phone": "512-555-0142", "content": "Will try Thursday"}'
Returns 201 with {"data": {activity}}, plus task_id / task_completed when filed against a follow-up and stopped_sequence_tasks with customer_response. Connected integrations hear about the note as they do for notes added in the app.
Tagging teammates in a note is not available through the API.
Errors: 400 content is required, type must be one of: ...; 404 Job not found, task_id is not a follow-up on this job.
Contact and customer notes#
A person's feed and a customer's feed (company notes plus its people's notes, calls, emails, meetings and texts).
The feed note object#
| Field | Type | Description |
|---|---|---|
id |
integer | TruTec id. |
type |
string | note, call, email, meeting or text. |
content |
string or null | The text. |
contact_id, client_account_id, job_id |
integer or null | What it is about. |
user |
object or null | {id, name} of the author. |
details |
object | Extras when present (call outcome, email subject, direction, ...). |
created_at |
string | UTC. |
List a contact's notes / a customer's notes#
GET /v1/contacts/{id}/notes
GET /v1/client-accounts/{id}/notes
Permission: Read jobs
Newest first. Filters: type (comma-separated), created_after, limit, offset.
Add a note to a contact / a customer#
POST /v1/contacts/{id}/notes
POST /v1/client-accounts/{id}/notes
Permission: Write jobs
| Name | Type | Required | Description |
|---|---|---|---|
content |
string | Yes | Up to 4,000 characters. |
type |
string | No | note (default), call, email or meeting. |
outcome, phone |
string | No | Calls only, as for job notes. |
contact_id |
integer | No | Customer notes only: one of the customer's people the note is about. |
A note on a person also shows on their company's feed.
curl -X POST "https://trutec.ai/api/v1/contacts/20417/notes" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"type": "meeting", "content": "Walked the lot with the board"}'
{
"data": {
"id": 55120,
"type": "meeting",
"content": "Walked the lot with the board",
"contact_id": 20417,
"client_account_id": 4812,
"job_id": null,
"user": {"id": 118, "name": "Dana Whitfield"},
"details": {"source": "api"},
"created_at": "2026-10-12T15:12:01Z"
}
}
Errors: 400 content is required, That contact belongs to another company; 404 for a record outside the workspace.
Customer history#
A contact's or customer's history#
GET /v1/contacts/{id}/timeline
GET /v1/client-accounts/{id}/timeline
Permission: Read jobs
One newest-first feed of everything that happened with the person or company, as on their page in the app: emails and texts in and out, calls and meetings, notes, follow-ups set and done, job stage moves, new jobs, proposals sent / viewed / signed, e-signatures and invoices. It covers every job the person or company is on.
| Name | Type | Required | Description |
|---|---|---|---|
limit |
integer | No | Default 50, maximum 100. |
before |
string | No | Cursor: the previous page's next_before. |
kinds |
string | No | Comma-separated groups: messages, calls, notes, tasks, deals, money. |
q |
string | No | Only entries mentioning this text (or on a job whose name, address or contact matches). |
{
"data": [
{
"key": "ca:email:55102",
"kind": "email",
"group": "messages",
"at": "2026-10-11T18:22:09Z",
"title": "Email to Jamie Rivera",
"subject": "Reseal proposal",
"body": "Attached is the proposal...",
"actor": "Dana Whitfield",
"chips": [],
"links": [{"kind": "job", "label": "Maple Ridge HOA reseal", "url": "/jobs/41872"}]
}
],
"has_more": true,
"next_before": "2026-10-11T18:22:09~ca:email:55102"
}
Page with before until has_more is false. Money entries (invoice amounts, deposits) appear only when the key's creator can see pricing.
Job follow-ups#
The follow-up object#
| Field | Type | Description |
|---|---|---|
id |
integer | TruTec id. |
job_id, job |
integer, object | The job ({id, name}). |
title, description |
string | What to do. |
task_type |
string | follow_up, call, email, meeting, appointment, site_visit or other. |
due_date |
string or null | UTC. |
timezone |
string | Time zone the reminder is shown in. |
reminder_minutes_before |
integer or null | Email reminder lead time. |
completed, completed_at, completion_notes |
Done state and what happened. | |
is_overdue |
boolean | Open and past due. |
assigned_to_user_id, assigned_to |
integer, object | Who does it. |
created_by_user_id, created_at |
Who added it and when. |
Due times. Send ISO 8601. With Z or an offset (2026-10-20T15:30:00Z) it is that exact time. Without one (2026-10-20T10:30) it is read in timezone (an IANA name such as America/Chicago), or the workspace's time zone. A bare date means 9:00 AM that day.
List job follow-ups#
GET /v1/tasks
Permission: Read jobs
Soonest due first; undated ones last.
| Name | Type | Required | Description |
|---|---|---|---|
status |
string | No | open (default), completed or all. |
job_id |
integer | No | One job. |
assigned_to_user_id |
integer | No | One assignee. |
due_before, due_after |
string | No | ISO 8601. |
limit, offset |
integer | No | Paging. |
Get a job follow-up#
GET /v1/tasks/{id}
Permission: Read jobs
Create a job follow-up#
POST /v1/tasks
Permission: Write jobs
| Name | Type | Required | Description |
|---|---|---|---|
job_id |
integer | Yes | The job. |
title |
string | Yes | What to do. |
task_type |
string | No | Default follow_up. |
description |
string | No | Details. |
due_date |
string | No | See Due times. |
timezone |
string | No | For a due time without an offset, and for the reminder. |
assigned_to_user_id |
integer | No | Default: the key's creator. |
reminder_minutes_before |
integer | No | Default 30 (60 for meetings and site visits) when there is a due time. |
curl -X POST "https://trutec.ai/api/v1/tasks" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"job_id": 41872, "title": "Call Jamie back", "task_type": "call", "due_date": "2026-10-20T15:30:00Z"}'
{
"data": {
"id": 7731,
"job_id": 41872,
"job": {"id": 41872, "name": "Maple Ridge HOA reseal"},
"title": "Call Jamie back",
"description": null,
"task_type": "call",
"due_date": "2026-10-20T15:30:00Z",
"timezone": "America/Chicago",
"reminder_minutes_before": 30,
"completed": false,
"completed_at": null,
"completion_notes": null,
"is_overdue": false,
"assigned_to_user_id": 118,
"assigned_to": {"id": 118, "name": "Dana Whitfield"},
"created_by_user_id": 118,
"created_at": "2026-10-12T14:05:00Z"
}
}
A "Task created" line is added to the job's activity.
Errors: 400 job_id is required, title is required, task_type must be one of: ..., due_date must be an ISO 8601 date or date-time; 404 for a job or user outside the workspace.
Update a job follow-up#
PATCH /v1/tasks/{id}
Permission: Write jobs
Send any of title, description, task_type, due_date (null clears it), timezone, assigned_to_user_id, reminder_minutes_before, completion_notes and completed. Rescheduling sends the reminder again. completed: true completes it the way the task window does: with completion_notes, they post to the job (a call task logs a call, a meeting task a meeting) and to the customer's feed; without notes a "Task completed" line is added. completed: false reopens it.
Complete a job follow-up#
POST /v1/tasks/{id}/complete
Permission: Write jobs
Shortcut for completing with notes (optional) as the completion notes. A follow-up that is already done is returned unchanged.
curl -X POST "https://trutec.ai/api/v1/tasks/7731/complete" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"notes": "Booked a walk-through for Friday"}'
Delete a job follow-up#
DELETE /v1/tasks/{id}
Permission: Write jobs and Delete records
Returns 204.
Company follow-ups#
Follow-ups on a customer when there is no job ("call the board back after their meeting"). They can repeat: completing one opens the next on schedule.
The company follow-up object#
Like the job follow-up, with client_account_id / client_account instead of the job, plus:
| Field | Type | Description |
|---|---|---|
contact_id |
integer or null | The person to reach. |
repeat |
object or null | {every, unit, label}, e.g. {"every": 3, "unit": "month", "label": "Every 3 months"}. |
completed_by_user_id |
integer or null | Who completed it. |
source |
string | manual, my_day, repeat, crm_intake:<lead id> (a lead's "Call new lead"), automation:<rule id>, ... |
task_type is one of follow_up, call, email, meeting, site_visit, other.
List company follow-ups#
GET /v1/account-tasks
Permission: Read jobs
Filters: status (open default, completed, all), client_account_id, contact_id, assigned_to_user_id, due_before, due_after, limit, offset.
Get a company follow-up#
GET /v1/account-tasks/{id}
Permission: Read jobs
Create a company follow-up#
POST /v1/account-tasks
Permission: Write jobs
| Name | Type | Required | Description |
|---|---|---|---|
client_account_id |
integer | Yes | The customer (not archived). |
title |
string | No | Default: "Follow up · Maple Ridge HOA". |
task_type |
string | No | Default follow_up. |
description |
string | No | Details. |
due_date, timezone |
string | No | See Due times. |
contact_id |
integer | No | One of the customer's people. |
assigned_to_user_id |
integer | No | An office user. Default: the key's creator. |
repeat_every, repeat_unit |
integer, string | No | Repeat every N days, weeks or months (1-365). |
curl -X POST "https://trutec.ai/api/v1/account-tasks" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"client_account_id": 4812, "title": "Quarterly check-in", "task_type": "call", "due_date": "2026-11-02T16:00:00Z", "repeat_every": 3, "repeat_unit": "month"}'
Returns 201 with {"data": {company follow-up}}.
Update a company follow-up#
PATCH /v1/account-tasks/{id}
Permission: Write jobs
Send any of title, task_type, description, due_date, timezone, contact_id, assigned_to_user_id (null unassigns), repeat_every / repeat_unit (null stops repeating). Errors: 409 already_completed.
Complete a company follow-up#
POST /v1/account-tasks/{id}/complete
Permission: Write jobs
Marks it done, as on My day: a call, email, meeting or site visit is logged on the company feed (with notes) and counts as a touch; another kind with notes adds a company note. A repeating follow-up opens the next one, returned as next_task.
{
"data": {"id": 3305, "completed": true, "completion_notes": "Happy with the work", "...": "..."},
"next_task": {"id": 3340, "title": "Quarterly check-in", "due_date": "2027-02-02T16:00:00Z", "repeat": {"every": 3, "unit": "month", "label": "Every 3 months"}, "...": "..."}
}
Delete a company follow-up#
DELETE /v1/account-tasks/{id}
Permission: Write jobs and Delete records
Deletes the follow-up, open or done, for good (a repeating one stops repeating), as its delete button in the app does. Returns 204. Workspaces where the app has no delete for company follow-ups get 403 with code: not_available; complete the follow-up instead.
Changing or removing notes#
Notes, logged calls, emails, meetings and site visits can't be edited or deleted, in the app or through the API: they are the record of what happened. To correct one, add another note.