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
| 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. |
List projects
readPOST 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
| Name | Type | Description |
|---|---|---|
| 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 -X POST https://cotlet.dev/api/v1/contractor-foreman/list_projects \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("contractor-foreman", "list_projects") const result = await cotlet.call('contractor-foreman', 'list_projects'); 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
} Get project
readPOST 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
| Name | Type | Description |
|---|---|---|
| project_id required | string | Project ID from list_projects. |
Request
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"}' result = client.call("contractor-foreman", "get_project", {"project_id":"project_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'get_project', {"project_id":"project_8c41d2"}); 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"
} Get job costing
readPOST 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
| Name | Type | Description |
|---|---|---|
| project_id required | string | Project ID from list_projects. |
Request
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"}' result = client.call("contractor-foreman", "get_job_costing", {"project_id":"84213"}) const result = await cotlet.call('contractor-foreman', 'get_job_costing', {"project_id":"84213"}); 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"
} List estimates
readPOST 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
| Name | Type | Description |
|---|---|---|
| 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 -X POST https://cotlet.dev/api/v1/contractor-foreman/list_estimates \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("contractor-foreman", "list_estimates") const result = await cotlet.call('contractor-foreman', 'list_estimates'); 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
}
]
} List change orders
readPOST 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
| Name | Type | Description |
|---|---|---|
| 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 -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"}' result = client.call("contractor-foreman", "list_change_orders", {"project_id":"project_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'list_change_orders', {"project_id":"project_8c41d2"}); 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
}
]
} List daily logs
readPOST 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
| Name | Type | Description |
|---|---|---|
| project_id required | string | Project ID from list_projects. |
| from | date | First log date. |
| to | date | Last log date. |
Request
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"}' result = client.call("contractor-foreman", "list_daily_logs", {"project_id":"project_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'list_daily_logs', {"project_id":"project_8c41d2"}); 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
}
}
]
} List schedule tasks
readPOST 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
| Name | Type | Description |
|---|---|---|
| project_id required | string | Project ID from list_projects. |
Request
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"}' result = client.call("contractor-foreman", "list_schedule_tasks", {"project_id":"project_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'list_schedule_tasks', {"project_id":"project_8c41d2"}); 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
}
]
} List invoices
readPOST 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
| Name | Type | Description |
|---|---|---|
| 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 -X POST https://cotlet.dev/api/v1/contractor-foreman/list_invoices \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("contractor-foreman", "list_invoices") const result = await cotlet.call('contractor-foreman', 'list_invoices'); 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"
}
]
} Create daily log
writePOST 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
| Name | Type | Description |
|---|---|---|
| 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 -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."}' 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."}) 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."}); 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
}
} Create estimate
writePOST 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
| Name | Type | Description |
|---|---|---|
| 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 -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."}' 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."}) 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."}); 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
} 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
| Name | Type | Description |
|---|---|---|
| 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 -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"}' result = client.call("contractor-foreman", "send_estimate", {"estimate_id":"estimate_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'send_estimate', {"estimate_id":"estimate_8c41d2"}); cotlet call contractor-foreman send_estimate --data '{"estimate_id":"estimate_8c41d2"}' Example response
{
"estimate_id": "E-2291",
"status": "sent",
"sent_to": [
"client@example.com"
]
} Create change order
writePOST 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
| Name | Type | Description |
|---|---|---|
| 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 -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."}' 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."}) 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."}); 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
} 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
| Name | Type | Description |
|---|---|---|
| change_order_id required | string | Change order ID from create_change_order. |
| message | string | Email body. |
Request
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"}' result = client.call("contractor-foreman", "send_change_order", {"change_order_id":"change_order_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'send_change_order', {"change_order_id":"change_order_8c41d2"}); 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"
]
} Update schedule task
writePOST 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
| Name | Type | Description |
|---|---|---|
| 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 -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"}' result = client.call("contractor-foreman", "update_schedule_task", {"task_id":"task_8c41d2"}) const result = await cotlet.call('contractor-foreman', 'update_schedule_task', {"task_id":"task_8c41d2"}); 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
} 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
| Name | Type | Description |
|---|---|---|
| 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 -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"}' result = client.call("contractor-foreman", "add_punchlist_item", {"project_id":"project_8c41d2","title":"title"}) const result = await cotlet.call('contractor-foreman', 'add_punchlist_item', {"project_id":"project_8c41d2","title":"title"}); 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"
}