# Yardbook API

> Every Yardbook endpoint on Cotlet: inputs, JSON Schema, cURL, Python and Node.js examples and an example response for each call.

Source: https://cotlet.dev/docs/api/yardbook

Docs sections: [Get started](https://cotlet.dev/docs.md) · [REST API](https://cotlet.dev/docs/api.md) · [MCP](https://cotlet.dev/docs/mcp.md) · [SDKs & CLI](https://cotlet.dev/docs/sdks.md) · [Integrations](https://cotlet.dev/docs/integrations.md)

14 endpoints for Yardbook. Each one is a POST with a JSON body, called with your API key.

- Base URL: `https://cotlet.dev/api/v1/yardbook`
- Connects with: Your own Yardbook account (email and password, the account owner or an office user)
- Integration page: https://cotlet.dev/integrations/yardbook-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `list_customers` | read | Customers and prospects with address, email, phone and balance. |
| `get_customer` | read | One customer with contact details, notes, upcoming jobs, open estimates and invoices. |
| `list_jobs` | read | Scheduled and completed jobs in a date range, with customer, services and assigned crew member. |
| `list_estimates` | read | Estimates with customer, total and status, newest first. |
| `list_invoices` | read | Invoices with customer, total, amount due, due date and status. |
| `get_invoice` | read | Full invoice: line items, payments recorded and amount due. |
| `create_customer` | write | Add a customer or prospect with contact details and service address. |
| `schedule_job` | write | Add a one-time or recurring job to the schedule, optionally assigned to a crew member. |
| `complete_job` | write | Mark a job as completed, so it can be invoiced. |
| `create_estimate` | write | Draft estimate for a customer or prospect. Nothing is sent until you call send_estimate. |
| `send_estimate` | write | Email an estimate to the customer with a link to approve it online. |
| `create_invoice` | write | Invoice from a completed job or an approved estimate, or with your own line items. Not sent yet. |
| `send_invoice` | write | Email an invoice to the customer with a link to view it. |
| `record_payment` | write | Record a cash, check or other payment received against an invoice. |

## List customers

`POST https://cotlet.dev/api/v1/yardbook/list_customers`

Access: read.

Lists customers, prospects or both. Search matches name, address, email and phone. Balance is the amount the customer still owes on open invoices. Pass next_cursor back as cursor for the next page.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `type` | enum | no | customer, prospect or all. Default: customer. |
| `search` | string | no | Match on name, address, email or phone. |
| `limit` | integer | no | 1 to 200. Default: 50. |
| `cursor` | string | no | Next page cursor from the previous call. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/list_customers \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("yardbook", "list_customers")
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'list_customers');
```

**CLI**

```bash
cotlet call yardbook list_customers
```

### Example response

```json
{
  "customers": [
    {
      "customer_id": "284117",
      "name": "Maria Lopez",
      "type": "customer",
      "address": "18 Elm Street",
      "email": "maria@example.com",
      "phone": "555-0142",
      "balance": "0.00"
    },
    {
      "customer_id": "284230",
      "name": "Parker Property",
      "type": "customer",
      "address": "7 Ridge Road",
      "email": "office@parker.example.com",
      "phone": "555-0177",
      "balance": "240.00"
    }
  ],
  "next_cursor": null
}
```

## Get customer

`POST https://cotlet.dev/api/v1/yardbook/get_customer`

Access: read.

Returns one customer with contact details and property notes, plus their upcoming jobs, open estimates and unpaid invoices. Use it before scheduling or billing so your agent sees what is already there.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `customer_id` | string | yes | Customer ID from list_customers. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/get_customer \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"customer_8c41d2"}'
```

**Python**

```python
result = client.call("yardbook", "get_customer", {"customer_id":"customer_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'get_customer', {"customer_id":"customer_8c41d2"});
```

**CLI**

```bash
cotlet call yardbook get_customer --data '{"customer_id":"customer_8c41d2"}'
```

### Example response

```json
{
  "customer_id": "284117",
  "name": "Maria Lopez",
  "type": "customer",
  "address": "18 Elm Street",
  "notes": "Side gate code 1234. Dog in yard.",
  "upcoming_jobs": [
    {
      "job_id": "9930412",
      "date": "2026-10-13",
      "services": [
        "Mowing",
        "Edging"
      ]
    }
  ],
  "open_estimates": [],
  "unpaid_invoices": []
}
```

## List jobs

`POST https://cotlet.dev/api/v1/yardbook/list_jobs`

Access: read.

Lists jobs between two dates, oldest first, with customer, services and the crew member each job is assigned to. Filter by status, crew member or customer. Recurring jobs appear as one entry per visit in the range.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `from` | date | yes | First day of the range. |
| `to` | date | yes | Last day of the range. |
| `status` | enum | no | scheduled, completed or all. Default: all. |
| `assignee_id` | string | no | Only jobs assigned to this crew member. |
| `customer_id` | string | no | Only jobs for this customer. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/list_jobs \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"from":"2026-10-01","to":"2026-10-01"}'
```

**Python**

```python
result = client.call("yardbook", "list_jobs", {"from":"2026-10-01","to":"2026-10-01"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'list_jobs', {"from":"2026-10-01","to":"2026-10-01"});
```

**CLI**

```bash
cotlet call yardbook list_jobs --data '{"from":"2026-10-01","to":"2026-10-01"}'
```

### Example response

```json
{
  "jobs": [
    {
      "job_id": "9930412",
      "date": "2026-10-13",
      "customer_id": "284117",
      "customer": "Maria Lopez",
      "services": [
        "Mowing",
        "Edging"
      ],
      "status": "scheduled",
      "assignee": "Crew 1"
    },
    {
      "job_id": "9930455",
      "date": "2026-10-13",
      "customer_id": "284230",
      "customer": "Parker Property",
      "services": [
        "Spring cleanup"
      ],
      "status": "scheduled",
      "assignee": "Crew 2"
    }
  ]
}
```

## List estimates

`POST https://cotlet.dev/api/v1/yardbook/list_estimates`

Access: read.

Lists estimates newest first with customer, total and status. Draft estimates have not been sent. Approved estimates can be turned into an invoice with create_invoice.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `status` | enum | no | draft, sent, approved or all. Default: all. |
| `customer_id` | string | no | Only estimates for this customer. |
| `limit` | integer | no | 1 to 100. Default: 50. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/list_estimates \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("yardbook", "list_estimates")
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'list_estimates');
```

**CLI**

```bash
cotlet call yardbook list_estimates
```

### Example response

```json
{
  "estimates": [
    {
      "estimate_id": "51802",
      "customer_id": "284230",
      "customer": "Parker Property",
      "total": "490.00",
      "status": "draft",
      "created_at": "2026-10-09"
    }
  ]
}
```

## List invoices

`POST https://cotlet.dev/api/v1/yardbook/list_invoices`

Access: read.

Lists invoices newest first. Status defaults to unpaid. Amount due is the total minus the payments recorded. older_than_days keeps invoices issued at least that many days ago, which is how you find overdue ones.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `status` | enum | no | unpaid, paid or all. Default: unpaid. |
| `customer_id` | string | no | Only invoices for this customer. |
| `older_than_days` | integer | no | Only invoices issued at least this many days ago. |
| `limit` | integer | no | 1 to 100. Default: 50. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/list_invoices \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("yardbook", "list_invoices")
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'list_invoices');
```

**CLI**

```bash
cotlet call yardbook list_invoices
```

### Example response

```json
{
  "invoices": [
    {
      "invoice_id": "73194",
      "customer_id": "284230",
      "customer": "Parker Property",
      "issued_at": "2026-09-02",
      "due_date": "2026-09-16",
      "total": "240.00",
      "amount_due": "240.00",
      "status": "unpaid"
    }
  ]
}
```

## Get invoice

`POST https://cotlet.dev/api/v1/yardbook/get_invoice`

Access: read.

Returns one invoice with every line item, the payments recorded against it and the amount due. Use it to check an invoice before sending it or recording a payment.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `invoice_id` | string | yes | Invoice ID from list_invoices. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/get_invoice \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"invoice_id":"invoice_8c41d2"}'
```

**Python**

```python
result = client.call("yardbook", "get_invoice", {"invoice_id":"invoice_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'get_invoice', {"invoice_id":"invoice_8c41d2"});
```

**CLI**

```bash
cotlet call yardbook get_invoice --data '{"invoice_id":"invoice_8c41d2"}'
```

### Example response

```json
{
  "invoice_id": "73194",
  "customer": "Parker Property",
  "status": "unpaid",
  "line_items": [
    {
      "service": "Mowing",
      "description": "Weekly mowing, September",
      "quantity": 4,
      "unit_price": "60.00"
    }
  ],
  "total": "240.00",
  "payments": [],
  "amount_due": "240.00"
}
```

## Create customer

`POST https://cotlet.dev/api/v1/yardbook/create_customer`

Access: write.

Adds a customer, or a prospect if type is prospect, with the service address and contact details. It reaches no one and changes only your customer list, so it runs without asking for your OK.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Customer or company name. |
| `address` | string | yes | Service address. |
| `email` | string | no | Email for estimates and invoices. |
| `phone` | string | no | Phone number. |
| `type` | enum | no | customer or prospect. Default: customer. |
| `notes` | string | no | Gate codes, pets, property notes. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/create_customer \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Jane Doe","address":"address"}'
```

**Python**

```python
result = client.call("yardbook", "create_customer", {"name":"Jane Doe","address":"address"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'create_customer', {"name":"Jane Doe","address":"address"});
```

**CLI**

```bash
cotlet call yardbook create_customer --data '{"name":"Jane Doe","address":"address"}'
```

### Example response

```json
{
  "customer_id": "284117",
  "name": "Maria Lopez",
  "type": "customer",
  "address": "18 Elm Street"
}
```

## Schedule job

`POST https://cotlet.dev/api/v1/yardbook/schedule_job`

Access: write.

Adds a job for a customer on the date of the first visit. With repeat set to weekly or biweekly it creates a recurring job. Services are names from your product and service catalog. It sends nothing to the customer, so it runs without asking for your OK.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `customer_id` | string | yes | Customer ID from list_customers. |
| `date` | date | yes | Date of the first visit. |
| `services` | string[] | yes | Services from your product catalog, e.g. Mowing. |
| `repeat` | enum | no | none, weekly or biweekly. Default: none. |
| `assignee_id` | string | no | Crew member to assign. |
| `notes` | string | no | Instructions for the crew. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/schedule_job \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"284117","date":"2026-10-13","services":["Mowing","Edging"],"repeat":"weekly","assignee_id":"5521","notes":"Side gate code 1234. Bag clippings."}'
```

**Python**

```python
result = client.call("yardbook", "schedule_job", {"customer_id":"284117","date":"2026-10-13","services":["Mowing","Edging"],"repeat":"weekly","assignee_id":"5521","notes":"Side gate code 1234. Bag clippings."})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'schedule_job', {"customer_id":"284117","date":"2026-10-13","services":["Mowing","Edging"],"repeat":"weekly","assignee_id":"5521","notes":"Side gate code 1234. Bag clippings."});
```

**CLI**

```bash
cotlet call yardbook schedule_job --data '{"customer_id":"284117","date":"2026-10-13","services":["Mowing","Edging"],"repeat":"weekly","assignee_id":"5521","notes":"Side gate code 1234. Bag clippings."}'
```

### Example response

```json
{
  "job_id": "9930412",
  "customer_id": "284117",
  "date": "2026-10-13",
  "repeat": "weekly",
  "status": "scheduled",
  "services": [
    "Mowing",
    "Edging"
  ],
  "assignee": "Crew 1"
}
```

## Complete job

`POST https://cotlet.dev/api/v1/yardbook/complete_job`

Access: write.

Marks one job completed, with optional notes on what was done. A completed job can be passed to create_invoice. It sends nothing to the customer, so it runs without asking for your OK.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `job_id` | string | yes | Job ID from list_jobs. |
| `notes` | string | no | What was done on site. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/complete_job \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"job_id":"job_8c41d2"}'
```

**Python**

```python
result = client.call("yardbook", "complete_job", {"job_id":"job_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'complete_job', {"job_id":"job_8c41d2"});
```

**CLI**

```bash
cotlet call yardbook complete_job --data '{"job_id":"job_8c41d2"}'
```

### Example response

```json
{
  "job_id": "9930412",
  "status": "completed",
  "notes": "Mowed and edged, bagged clippings."
}
```

## Create estimate

`POST https://cotlet.dev/api/v1/yardbook/create_estimate`

Access: write.

Saves a draft estimate with your line items. The total is the sum of quantity times unit_price over all lines. Nothing is sent to the customer until send_estimate, so the draft runs without asking for your OK.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `customer_id` | string | yes | Customer ID from list_customers. |
| `line_items` | object[] | yes | List of { service, description, quantity, unit_price }. |
| `description` | string | no | Scope of work shown on the estimate. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/create_estimate \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"284230","description":"Spring cleanup, mulch and shrub trimming","line_items":[{"service":"Spring cleanup","description":"Leaf removal and cleanup of all beds","quantity":1,"unit_price":"220.00"},{"service":"Mulch","description":"Hardwood mulch, installed","quantity":6,"unit_price":"45.00"},{"service":"Shrub trimming","description":"Boxwoods along the walk","quantity":4,"unit_price":"15.00"}]}'
```

**Python**

```python
result = client.call("yardbook", "create_estimate", {"customer_id":"284230","description":"Spring cleanup, mulch and shrub trimming","line_items":[{"service":"Spring cleanup","description":"Leaf removal and cleanup of all beds","quantity":1,"unit_price":"220.00"},{"service":"Mulch","description":"Hardwood mulch, installed","quantity":6,"unit_price":"45.00"},{"service":"Shrub trimming","description":"Boxwoods along the walk","quantity":4,"unit_price":"15.00"}]})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'create_estimate', {"customer_id":"284230","description":"Spring cleanup, mulch and shrub trimming","line_items":[{"service":"Spring cleanup","description":"Leaf removal and cleanup of all beds","quantity":1,"unit_price":"220.00"},{"service":"Mulch","description":"Hardwood mulch, installed","quantity":6,"unit_price":"45.00"},{"service":"Shrub trimming","description":"Boxwoods along the walk","quantity":4,"unit_price":"15.00"}]});
```

**CLI**

```bash
cotlet call yardbook create_estimate --data '{"customer_id":"284230","description":"Spring cleanup, mulch and shrub trimming","line_items":[{"service":"Spring cleanup","description":"Leaf removal and cleanup of all beds","quantity":1,"unit_price":"220.00"},{"service":"Mulch","description":"Hardwood mulch, installed","quantity":6,"unit_price":"45.00"},{"service":"Shrub trimming","description":"Boxwoods along the walk","quantity":4,"unit_price":"15.00"}]}'
```

### Example response

```json
{
  "estimate_id": "51802",
  "customer_id": "284117",
  "status": "draft",
  "line_items": [
    {
      "service": "Spring cleanup",
      "quantity": 1,
      "unit_price": "220.00",
      "amount": "220.00"
    },
    {
      "service": "Mulch",
      "quantity": 6,
      "unit_price": "45.00",
      "amount": "270.00"
    }
  ],
  "total": "490.00"
}
```

## Send estimate

`POST https://cotlet.dev/api/v1/yardbook/send_estimate`

Access: write. Confirm: waits for the user's OK before it runs.

Emails a draft estimate to the customer, with your optional note and a link to approve it online. The customer needs an email address on file. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `estimate_id` | string | yes | Estimate ID from list_estimates. |
| `message` | string | no | Note added to the email. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/send_estimate \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"estimate_id":"estimate_8c41d2"}'
```

**Python**

```python
result = client.call("yardbook", "send_estimate", {"estimate_id":"estimate_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'send_estimate', {"estimate_id":"estimate_8c41d2"});
```

**CLI**

```bash
cotlet call yardbook send_estimate --data '{"estimate_id":"estimate_8c41d2"}'
```

### Example response

```json
{
  "estimate_id": "51802",
  "status": "sent",
  "sent_to": "maria@example.com"
}
```

## Create invoice

`POST https://cotlet.dev/api/v1/yardbook/create_invoice`

Access: write.

Creates an invoice from a completed job, from an approved estimate, or from line items you pass. It is saved unsent; send_invoice emails it. It reaches no one, so it runs without asking for your OK.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `customer_id` | string | yes | Customer ID from list_customers. |
| `job_id` | string | no | Completed job to invoice. |
| `estimate_id` | string | no | Approved estimate to convert. |
| `line_items` | object[] | no | List of { service, description, quantity, unit_price }, when there is no job or estimate. |
| `due_date` | date | no | Payment due date. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/create_invoice \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"customer_8c41d2"}'
```

**Python**

```python
result = client.call("yardbook", "create_invoice", {"customer_id":"customer_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'create_invoice', {"customer_id":"customer_8c41d2"});
```

**CLI**

```bash
cotlet call yardbook create_invoice --data '{"customer_id":"customer_8c41d2"}'
```

### Example response

```json
{
  "invoice_id": "73210",
  "customer_id": "284117",
  "job_id": "9930412",
  "status": "unpaid",
  "sent": false,
  "total": "85.00",
  "amount_due": "85.00",
  "due_date": "2026-10-27"
}
```

## Send invoice

`POST https://cotlet.dev/api/v1/yardbook/send_invoice`

Access: write. Confirm: waits for the user's OK before it runs.

Emails an invoice to the customer, with your optional note, for example a reminder on an overdue one. The customer needs an email address on file. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `invoice_id` | string | yes | Invoice ID from list_invoices. |
| `message` | string | no | Note added to the email, e.g. a reminder. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/send_invoice \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"invoice_id":"invoice_8c41d2"}'
```

**Python**

```python
result = client.call("yardbook", "send_invoice", {"invoice_id":"invoice_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'send_invoice', {"invoice_id":"invoice_8c41d2"});
```

**CLI**

```bash
cotlet call yardbook send_invoice --data '{"invoice_id":"invoice_8c41d2"}'
```

### Example response

```json
{
  "invoice_id": "73194",
  "status": "unpaid",
  "sent_to": "office@parker.example.com"
}
```

## Record payment

`POST https://cotlet.dev/api/v1/yardbook/record_payment`

Access: write. Confirm: waits for the user's OK before it runs.

Records a payment you received against one invoice. The amount due goes down by the amount; an invoice paid in full becomes paid. It moves no money and charges no card. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `invoice_id` | string | yes | Invoice ID from list_invoices. |
| `amount` | string | yes | Amount received, e.g. 240.00. |
| `method` | string | yes | How it was paid, e.g. Check or Cash. |
| `date` | date | no | Date received. Default: today. |
| `reference` | string | no | Check number or note. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/yardbook/record_payment \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"invoice_id":"73194","amount":"240.00","method":"Check","date":"2026-10-16","reference":"Check 3318"}'
```

**Python**

```python
result = client.call("yardbook", "record_payment", {"invoice_id":"73194","amount":"240.00","method":"Check","date":"2026-10-16","reference":"Check 3318"})
```

**Node.js**

```js
const result = await cotlet.call('yardbook', 'record_payment', {"invoice_id":"73194","amount":"240.00","method":"Check","date":"2026-10-16","reference":"Check 3318"});
```

**CLI**

```bash
cotlet call yardbook record_payment --data '{"invoice_id":"73194","amount":"240.00","method":"Check","date":"2026-10-16","reference":"Check 3318"}'
```

### Example response

```json
{
  "invoice_id": "73194",
  "payment": {
    "amount": "240.00",
    "method": "Check",
    "date": "2026-10-11",
    "reference": "Check 3318"
  },
  "amount_due": "0.00",
  "status": "paid"
}
```
