REST API reference

Contractor Foreman API

15 endpoints for Contractor Foreman. Each one is a POST with a JSON body, called with your API key.

Base URL
https://cotlet.dev/api/v1/contractor-foreman
Connects with
Your own Contractor Foreman account (the role needs access to the modules you use)
Integration page
Contractor Foreman
Contractor Foreman Endpoints
Endpoint Access Description
list_projects read Projects with customer, address, stage, contract amount and percent complete.
get_project read One project: customer, address, stage, original and revised contract amount, dates.
get_job_costing read Estimated and actual cost per cost code for one project, with the difference.
list_estimates read Estimates with status, total, and whether the client opened or signed them.
list_change_orders read Change orders and change order requests on a project, with status and amount.
list_daily_logs read Daily logs on a project: date, people on site, weather, materials and notes.
list_schedule_tasks read Gantt schedule tasks with start and end dates, dependencies and percent complete.
list_invoices read Invoices with project, customer, total, amount paid, balance due and retainage held.
create_daily_log write New daily log on a project. Weather is recorded by Contractor Foreman for the date.
create_estimate write Draft estimate with line items and markup. Nothing goes to the client until you send it.
send_estimate write Email an estimate to the client for online approval and e-signature.
create_change_order write Draft change order on a project, itemized or lump sum. Not sent until you send it.
send_change_order write Email a change order to the client for online approval and e-signature.
update_schedule_task write Change dates or percent complete of a task on the project schedule.
add_punchlist_item write New punchlist item on a project, assigned to an employee or subcontractor.

POST https://cotlet.dev/api/v1/contractor-foreman/list_projects

Returns projects newest first. Completed projects are left out unless you ask for them. Search matches the project name, number or customer. Pages hold up to 100 projects; pass next_cursor back as cursor for the next page.

Parameters

Parameters: list_projects
NameTypeDescription
search string Match on project name, number or customer.
include_completed boolean Include completed projects. Default: false.
limit integer 1 to 100. Default: 25.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/list_projects \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("contractor-foreman", "list_projects")
Node.js
const result = await cotlet.call('contractor-foreman', 'list_projects');
CLI
cotlet call contractor-foreman list_projects

Example response

{
  "projects": [
    {
      "project_id": "84213",
      "name": "Maple St Remodel",
      "number": "P-0142",
      "customer": "Dana Whitfield",
      "address": "218 Maple St, Asheville, NC",
      "stage": "In progress",
      "contract_amount": 86500,
      "percent_complete": 42
    }
  ],
  "next_cursor": null
}

POST https://cotlet.dev/api/v1/contractor-foreman/get_project

Returns one project. The revised contract amount is the original amount plus approved change orders, as the project shows it. Use the project_id from list_projects.

Parameters

Parameters: get_project
NameTypeDescription
project_id required string Project ID from list_projects.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/get_project \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"project_8c41d2"}'
Python
result = client.call("contractor-foreman", "get_project", {"project_id":"project_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'get_project', {"project_id":"project_8c41d2"});
CLI
cotlet call contractor-foreman get_project --data '{"project_id":"project_8c41d2"}'

Example response

{
  "project_id": "84213",
  "name": "Maple St Remodel",
  "customer": "Dana Whitfield",
  "address": "218 Maple St, Asheville, NC",
  "stage": "In progress",
  "original_contract_amount": 86500,
  "revised_contract_amount": 86500,
  "start_date": "2026-08-17",
  "end_date": "2026-12-11"
}

POST https://cotlet.dev/api/v1/contractor-foreman/get_job_costing

Returns the figures of the project's job costing: estimated cost, actual cost and the difference for each cost code, plus totals. Labor from time cards counts toward actual cost. Read only.

Parameters

Parameters: get_job_costing
NameTypeDescription
project_id required string Project ID from list_projects.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/get_job_costing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"84213"}'
Python
result = client.call("contractor-foreman", "get_job_costing", {"project_id":"84213"})
Node.js
const result = await cotlet.call('contractor-foreman', 'get_job_costing', {"project_id":"84213"});
CLI
cotlet call contractor-foreman get_job_costing --data '{"project_id":"84213"}'

Example response

{
  "project_id": "84213",
  "cost_codes": [
    {
      "code": "Labor",
      "estimated": 18000,
      "actual": 19250,
      "difference": -1250
    },
    {
      "code": "Materials",
      "estimated": 22000,
      "actual": 20100,
      "difference": 1900
    },
    {
      "code": "Subcontractors",
      "estimated": 9000,
      "actual": 9000,
      "difference": 0
    }
  ],
  "totals": {
    "estimated": 49000,
    "actual": 48350,
    "difference": 650
  },
  "currency": "USD"
}

POST https://cotlet.dev/api/v1/contractor-foreman/list_estimates

Returns estimates newest first, optionally for one project. Status is the label Contractor Foreman shows, for example draft or approved. Pages hold up to 100 estimates.

Parameters

Parameters: list_estimates
NameTypeDescription
project_id string Only estimates for this project.
status string Filter by status as shown in Contractor Foreman, e.g. draft or approved.
limit integer 1 to 100. Default: 25.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/list_estimates \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("contractor-foreman", "list_estimates")
Node.js
const result = await cotlet.call('contractor-foreman', 'list_estimates');
CLI
cotlet call contractor-foreman list_estimates

Example response

{
  "estimates": [
    {
      "estimate_id": "E-2291",
      "project_id": "84213",
      "title": "Bathroom remodel",
      "status": "draft",
      "total": 1589,
      "opened_by_client": false,
      "signed": false
    }
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/list_change_orders

Returns the change orders of one project with status and amount. Change order requests that are not yet in a change order are included unless you turn them off.

Parameters

Parameters: list_change_orders
NameTypeDescription
project_id required string Project ID from list_projects.
include_requests boolean Include change order requests not yet in a change order. Default: true.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/list_change_orders \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"project_8c41d2"}'
Python
result = client.call("contractor-foreman", "list_change_orders", {"project_id":"project_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'list_change_orders', {"project_id":"project_8c41d2"});
CLI
cotlet call contractor-foreman list_change_orders --data '{"project_id":"project_8c41d2"}'

Example response

{
  "change_orders": [
    {
      "change_order_id": "CO-17",
      "title": "Second kitchen window",
      "status": "draft",
      "amount": 1368
    }
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/list_daily_logs

Returns the daily logs of one project, newest first, optionally between two dates. Each log carries the notes, the people on site, deliveries and the weather Contractor Foreman recorded.

Parameters

Parameters: list_daily_logs
NameTypeDescription
project_id required string Project ID from list_projects.
from date First log date.
to date Last log date.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/list_daily_logs \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"project_8c41d2"}'
Python
result = client.call("contractor-foreman", "list_daily_logs", {"project_id":"project_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'list_daily_logs', {"project_id":"project_8c41d2"});
CLI
cotlet call contractor-foreman list_daily_logs --data '{"project_id":"project_8c41d2"}'

Example response

{
  "daily_logs": [
    {
      "daily_log_id": "557190",
      "date": "2026-10-09",
      "notes": "Framing second floor east wall.",
      "people": {
        "Framing crew": 4
      },
      "weather": {
        "condition": "Rain",
        "high_f": 61,
        "low_f": 48
      }
    }
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/list_schedule_tasks

Returns the tasks of the project schedule in the order of the Gantt chart. Each task has start and end dates, the tasks it depends on and percent complete. Use the task_id with update_schedule_task.

Parameters

Parameters: list_schedule_tasks
NameTypeDescription
project_id required string Project ID from list_projects.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/list_schedule_tasks \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"project_8c41d2"}'
Python
result = client.call("contractor-foreman", "list_schedule_tasks", {"project_id":"project_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'list_schedule_tasks', {"project_id":"project_8c41d2"});
CLI
cotlet call contractor-foreman list_schedule_tasks --data '{"project_id":"project_8c41d2"}'

Example response

{
  "tasks": [
    {
      "task_id": "T-5530",
      "name": "Rough-in inspection",
      "start_date": "2026-10-14",
      "end_date": "2026-10-14",
      "depends_on": [
        "T-5521"
      ],
      "percent_complete": 0
    }
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/list_invoices

Returns invoices newest first. Balance due is the total minus the amount paid. Retainage held is listed apart from it. Filter to invoices with a balance or due before a date. Pages hold up to 100 invoices.

Parameters

Parameters: list_invoices
NameTypeDescription
project_id string Only invoices for this project.
unpaid_only boolean Only invoices with a balance due. Default: false.
due_before date Only invoices due before this date.
limit integer 1 to 100. Default: 25.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/list_invoices \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("contractor-foreman", "list_invoices")
Node.js
const result = await cotlet.call('contractor-foreman', 'list_invoices');
CLI
cotlet call contractor-foreman list_invoices

Example response

{
  "invoices": [
    {
      "invoice_id": "INV-1048",
      "project_id": "84213",
      "customer": "Dana Whitfield",
      "total": 12000,
      "paid": 7000,
      "balance_due": 5000,
      "retainage_held": 600,
      "due_date": "2026-09-05"
    }
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/create_daily_log

Adds a daily log to the project for the date you give. Contractor Foreman records the weather itself; weather_notes sits next to it. The log reaches no client or crew and can be edited in the app, so this tool runs without asking.

Parameters

Parameters: create_daily_log
NameTypeDescription
project_id required string Project ID from list_projects.
date required date Log date.
notes required string Work done and site notes.
people object Crews, subcontractors and visitors on site, with headcount or names.
materials_delivered string[] Materials delivered to the site.
weather_notes string Your own notes next to the recorded weather.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/create_daily_log \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"84213","date":"2026-10-09","notes":"Framing second floor east wall. Window rough openings checked.","people":{"Framing crew":4,"Electrical sub":1},"materials_delivered":["48 sheets 1/2\" drywall","20 2x6x12 studs"],"weather_notes":"Rain after 2 pm, crew stopped at 2:30."}'
Python
result = client.call("contractor-foreman", "create_daily_log", {"project_id":"84213","date":"2026-10-09","notes":"Framing second floor east wall. Window rough openings checked.","people":{"Framing crew":4,"Electrical sub":1},"materials_delivered":["48 sheets 1/2\" drywall","20 2x6x12 studs"],"weather_notes":"Rain after 2 pm, crew stopped at 2:30."})
Node.js
const result = await cotlet.call('contractor-foreman', 'create_daily_log', {"project_id":"84213","date":"2026-10-09","notes":"Framing second floor east wall. Window rough openings checked.","people":{"Framing crew":4,"Electrical sub":1},"materials_delivered":["48 sheets 1/2\" drywall","20 2x6x12 studs"],"weather_notes":"Rain after 2 pm, crew stopped at 2:30."});
CLI
cotlet call contractor-foreman create_daily_log --data '{"project_id":"84213","date":"2026-10-09","notes":"Framing second floor east wall. Window rough openings checked.","people":{"Framing crew":4,"Electrical sub":1},"materials_delivered":["48 sheets 1/2\" drywall","20 2x6x12 studs"],"weather_notes":"Rain after 2 pm, crew stopped at 2:30."}'

Example response

{
  "daily_log_id": "557190",
  "project_id": "84213",
  "date": "2026-10-09",
  "weather": {
    "condition": "Rain",
    "high_f": 61,
    "low_f": 48
  }
}

POST https://cotlet.dev/api/v1/contractor-foreman/create_estimate

Saves a draft estimate on the project. Each line total is quantity times unit cost plus its markup, and the estimate total is the sum of the lines. The client sees nothing until send_estimate, so this tool runs without asking.

Parameters

Parameters: create_estimate
NameTypeDescription
project_id required string Project ID from list_projects.
title required string Estimate title.
items required object Line items: name, item type (e.g. material or labor), quantity, unit cost, markup percent.
notes string Scope notes shown on the estimate.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/create_estimate \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"84557","title":"Johnson bathroom remodel","items":[{"name":"Demolition labor","type":"labor","quantity":16,"unit_cost":55,"markup_percent":0},{"name":"Porcelain floor tile","type":"material","quantity":60,"unit_cost":8.5,"markup_percent":20}],"notes":"Includes removal of existing tub surround. Excludes permit fees."}'
Python
result = client.call("contractor-foreman", "create_estimate", {"project_id":"84557","title":"Johnson bathroom remodel","items":[{"name":"Demolition labor","type":"labor","quantity":16,"unit_cost":55,"markup_percent":0},{"name":"Porcelain floor tile","type":"material","quantity":60,"unit_cost":8.5,"markup_percent":20}],"notes":"Includes removal of existing tub surround. Excludes permit fees."})
Node.js
const result = await cotlet.call('contractor-foreman', 'create_estimate', {"project_id":"84557","title":"Johnson bathroom remodel","items":[{"name":"Demolition labor","type":"labor","quantity":16,"unit_cost":55,"markup_percent":0},{"name":"Porcelain floor tile","type":"material","quantity":60,"unit_cost":8.5,"markup_percent":20}],"notes":"Includes removal of existing tub surround. Excludes permit fees."});
CLI
cotlet call contractor-foreman create_estimate --data '{"project_id":"84557","title":"Johnson bathroom remodel","items":[{"name":"Demolition labor","type":"labor","quantity":16,"unit_cost":55,"markup_percent":0},{"name":"Porcelain floor tile","type":"material","quantity":60,"unit_cost":8.5,"markup_percent":20}],"notes":"Includes removal of existing tub surround. Excludes permit fees."}'

Example response

{
  "estimate_id": "E-2291",
  "project_id": "84213",
  "title": "Johnson bathroom",
  "status": "draft",
  "lines": [
    {
      "name": "Demolition labor",
      "total": 968
    },
    {
      "name": "Tile",
      "total": 621
    }
  ],
  "total": 1589
}

Send estimate

write Confirm

POST https://cotlet.dev/api/v1/contractor-foreman/send_estimate

Emails the estimate to the recipients for online approval and e-signature. Without recipients it goes to the project customer. The client can approve it from the email. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: send_estimate
NameTypeDescription
estimate_id required string Estimate ID from create_estimate or list_estimates.
to string[] Recipient emails. Default: the project customer.
message string Email body.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/send_estimate \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"estimate_id":"estimate_8c41d2"}'
Python
result = client.call("contractor-foreman", "send_estimate", {"estimate_id":"estimate_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'send_estimate', {"estimate_id":"estimate_8c41d2"});
CLI
cotlet call contractor-foreman send_estimate --data '{"estimate_id":"estimate_8c41d2"}'

Example response

{
  "estimate_id": "E-2291",
  "status": "sent",
  "sent_to": [
    "client@example.com"
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/create_change_order

Saves a draft change order. Each line total is quantity times unit cost plus its markup, and the total is the sum of the lines. With lump_sum the client sees one total instead of the lines. Nothing reaches the client until send_change_order, so this tool runs without asking.

Parameters

Parameters: create_change_order
NameTypeDescription
project_id required string Project ID from list_projects.
title required string Change order title.
items required object Line items: name, quantity, unit cost, markup percent.
lump_sum boolean Show the client one total instead of items. Default: false.
description string Reason for the change.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/create_change_order \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"84213","title":"Second kitchen window","items":[{"name":"Window unit","quantity":1,"unit_cost":780,"markup_percent":20},{"name":"Install labor","quantity":6,"unit_cost":60,"markup_percent":20}],"lump_sum":false,"description":"Client request on 9 Oct: add a second window on the kitchen east wall."}'
Python
result = client.call("contractor-foreman", "create_change_order", {"project_id":"84213","title":"Second kitchen window","items":[{"name":"Window unit","quantity":1,"unit_cost":780,"markup_percent":20},{"name":"Install labor","quantity":6,"unit_cost":60,"markup_percent":20}],"lump_sum":False,"description":"Client request on 9 Oct: add a second window on the kitchen east wall."})
Node.js
const result = await cotlet.call('contractor-foreman', 'create_change_order', {"project_id":"84213","title":"Second kitchen window","items":[{"name":"Window unit","quantity":1,"unit_cost":780,"markup_percent":20},{"name":"Install labor","quantity":6,"unit_cost":60,"markup_percent":20}],"lump_sum":false,"description":"Client request on 9 Oct: add a second window on the kitchen east wall."});
CLI
cotlet call contractor-foreman create_change_order --data '{"project_id":"84213","title":"Second kitchen window","items":[{"name":"Window unit","quantity":1,"unit_cost":780,"markup_percent":20},{"name":"Install labor","quantity":6,"unit_cost":60,"markup_percent":20}],"lump_sum":false,"description":"Client request on 9 Oct: add a second window on the kitchen east wall."}'

Example response

{
  "change_order_id": "CO-17",
  "project_id": "84213",
  "title": "Second kitchen window",
  "status": "draft",
  "lump_sum": false,
  "lines": [
    {
      "name": "Window unit",
      "total": 936
    },
    {
      "name": "Install labor",
      "total": 432
    }
  ],
  "total": 1368
}

Send change order

write Confirm

POST https://cotlet.dev/api/v1/contractor-foreman/send_change_order

Emails the change order to the project customer for online approval and e-signature. Approval is up to the client; the revised contract amount changes only after that. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: send_change_order
NameTypeDescription
change_order_id required string Change order ID from create_change_order.
message string Email body.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/send_change_order \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"change_order_id":"change_order_8c41d2"}'
Python
result = client.call("contractor-foreman", "send_change_order", {"change_order_id":"change_order_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'send_change_order', {"change_order_id":"change_order_8c41d2"});
CLI
cotlet call contractor-foreman send_change_order --data '{"change_order_id":"change_order_8c41d2"}'

Example response

{
  "change_order_id": "CO-17",
  "status": "sent",
  "sent_to": [
    "client@example.com"
  ]
}

POST https://cotlet.dev/api/v1/contractor-foreman/update_schedule_task

Changes the start date, end date or percent complete of one task and returns the task as the schedule shows it afterwards. Call list_schedule_tasks again to see tasks that depend on it. A schedule edit reaches no client, and one more call undoes it, so this tool runs without asking.

Parameters

Parameters: update_schedule_task
NameTypeDescription
task_id required string Task ID from list_schedule_tasks.
start_date date New start date.
end_date date New end date.
percent_complete integer 0 to 100.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/update_schedule_task \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task_id":"task_8c41d2"}'
Python
result = client.call("contractor-foreman", "update_schedule_task", {"task_id":"task_8c41d2"})
Node.js
const result = await cotlet.call('contractor-foreman', 'update_schedule_task', {"task_id":"task_8c41d2"});
CLI
cotlet call contractor-foreman update_schedule_task --data '{"task_id":"task_8c41d2"}'

Example response

{
  "task_id": "T-5530",
  "name": "Rough-in inspection",
  "start_date": "2026-10-16",
  "end_date": "2026-10-16",
  "percent_complete": 0
}

Add punchlist item

write Confirm

POST https://cotlet.dev/api/v1/contractor-foreman/add_punchlist_item

Adds a punchlist item to the project and assigns it to someone from your Directory. A due date is added to the calendar. The item is assigned to another person, so you confirm it. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: add_punchlist_item
NameTypeDescription
project_id required string Project ID from list_projects.
title required string What needs fixing.
assignee string Name or email from your Directory.
due_date date Due date, added to the calendar.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/contractor-foreman/add_punchlist_item \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"project_8c41d2","title":"title"}'
Python
result = client.call("contractor-foreman", "add_punchlist_item", {"project_id":"project_8c41d2","title":"title"})
Node.js
const result = await cotlet.call('contractor-foreman', 'add_punchlist_item', {"project_id":"project_8c41d2","title":"title"});
CLI
cotlet call contractor-foreman add_punchlist_item --data '{"project_id":"project_8c41d2","title":"title"}'

Example response

{
  "punchlist_item_id": "PL-311",
  "project_id": "84213",
  "title": "Touch up paint, hallway",
  "assignee": "Sam Rivera",
  "due_date": "2026-10-20",
  "status": "open"
}