<!-- SKILL-VERSION: library/quote-v1 3a76850@2026-10-04T07:41:12+10:00 -->
> **Skill version:** `3a76850@2026-10-04T07:41:12+10:00` (`library/quote-v1`).
> If you have a cached copy of this skill with a different version token,
> discard it and use this copy. Re-fetch this URL at the start of each
> session to detect updates.

# makesPDF — Quote skill `quote-v1`

> Version: `quote-v1`. **Immutable** — this file never changes after
> release. Fixes land in `quote-v2`, served alongside this file. If a
> newer version exists, it is noted at the top of this file; this URL
> keeps serving regardless.

> **Note to AI agents:** this document is served over HTTP at
> `https://makespdf.com/skills/library/quote-v1.md` (or
> `http://localhost:8788/skills/library/quote-v1.md` in dev). It is
> **not a local file.** Re-fetch it with a web fetch / HTTP tool — do
> **not** call your filesystem `Read` tool with `/skills/...`. Paths
> that begin with `/api/v1/` or `/skills/` below are URL paths relative
> to the makespdf origin, not filesystem paths.

Read [`/skills/pdf-template-author.md`](https://makespdf.com/skills/pdf-template-author.md)
first for the builder DSL, style properties, and the preview/render loop.
This file is the quote-specific companion: which fields to use, which
library template to start from, and a worked fetch, fill, render example.

A quote (estimate / proposal) is proposed pricing before a sale. For a
formal request to buy, use the purchase-order skill; for a bill after
delivery, use the invoice skill.

## Canonical fields (field registry)

Source: `docs/field-registry.md` and
`apps/web/src/utils/field-registry.ts` (`documentTypes` containing
`"quote"`). Use these canonical ids when naming data keys. The
`Aliases` column lists common incoming names the registry already
recognises — prefer the canonical id for new data.

### Document identity

| Canonical id    | Label         | Type / format | Common aliases                          |
| --------------- | ------------- | ------------- | --------------------------------------- |
| `quote-number`  | Quote Number  | string        | quoteno, estimatenumber, proposalnumber |
| `document-date` | Date          | date          | date, quotedate, issuedate              |
| `valid-until`   | Valid Until   | date          | validto, expirydate, quoteexpiry        |
| `payment-terms` | Payment Terms | string        | paymentterms, terms, netterms           |
| `currency`      | Currency      | code          | currencycode, cur                       |

### Seller (your company)

| Canonical id     | Label           | Type / format | Common aliases                |
| ---------------- | --------------- | ------------- | ----------------------------- |
| `seller-name`    | Company Name    | string        | companyname, vendorname       |
| `seller-address` | Company Address | string        | companyaddress, vendoraddress |
| `seller-phone`   | Phone           | phone         | phone, mobile, tel            |
| `seller-email`   | Email           | email         | email, companyemail           |
| `seller-website` | Website         | url           | website, url                  |
| `seller-tax-id`  | Tax ID          | tax-id        | gstin, vat, ein, abn          |
| `seller-logo`    | Logo            | url           | logo, companylogo             |

### Buyer (prospective customer)

| Canonical id    | Label          | Type / format | Common aliases                  |
| --------------- | -------------- | ------------- | ------------------------------- |
| `buyer-name`    | Client Name    | string        | customername, client            |
| `buyer-address` | Client Address | string        | customeraddress, billingaddress |
| `buyer-contact` | Contact Name   | string        | contactname, attn, attention    |
| `buyer-email`   | Client Email   | email         | customeremail, contactemail     |
| `buyer-phone`   | Client Phone   | phone         | customerphone, contactphone     |

### Line items

| Canonical id       | Label       | Type / format | Common aliases                 |
| ------------------ | ----------- | ------------- | ------------------------------ |
| `item-description` | Description | string        | description, itemname, service |
| `item-quantity`    | Quantity    | integer       | qty, quantity, count           |
| `item-unit-price`  | Unit Price  | currency      | unitprice, price, rate         |
| `item-unit`        | Unit        | code          | uom, unitofmeasure             |
| `item-discount`    | Discount    | currency      | discount, rebate               |
| `item-tax-rate`    | Tax Rate    | percentage    | taxrate, vatrate, gstrate      |
| `item-line-total`  | Line Total  | currency      | linetotal, amount, total       |
| `item-hours`       | Hours       | number        | hours, billablehours           |

### Totals

| Canonical id       | Label            | Type / format | Common aliases                       |
| ------------------ | ---------------- | ------------- | ------------------------------------ |
| `subtotal`         | Subtotal         | currency      | subtotal, netamount                  |
| `discount-total`   | Discount         | currency      | discounttotal, totaldiscount         |
| `tax-rate`         | Tax Rate         | percentage    | taxrate, vatrate                     |
| `tax-amount`       | Tax Amount       | currency      | tax, vat, gst, salestax              |
| `total`            | Total            | currency      | grandtotal, totaldue                 |
| `deposit-required` | Deposit Required | currency      | deposit, downpayment, advancepayment |

### Notes

| Canonical id           | Label                | Type / format | Common aliases                  |
| ---------------------- | -------------------- | ------------- | ------------------------------- |
| `notes`                | Notes                | string        | notes, memo, remarks            |
| `terms-and-conditions` | Terms & Conditions   | string        | terms, tandcs                   |
| `acceptance-signature` | Acceptance Signature | string        | signature, signedby, approvedby |

## Library template

Start from **`quote-classic`** (header bar, meta strip with quote no. /
reference / dates / validity, from + prepared-for panels, project
block, schedule-of-charges table, category subtotals + totals, payment
schedule). A modern variation exists (`quote-modern`) — list it with
`GET /api/v1/templates?owner=library&category=quote`.

## Worked example: fetch, fill, render

All calls need `Authorization: Bearer $MAKESPDF_API_KEY`.

**1. Fetch the template's DSL and sample data.**

```sh
curl -s -H "Authorization: Bearer $MAKESPDF_API_KEY" \
  "https://makespdf.com/api/v1/templates/quote-classic"
# -> { templateId, name, dsl, sampleData, ... }
```

**2. Fill.** Start from the returned `sampleData`, keep its keys, replace
the values with the real quote. Map incoming names to the canonical ids
above (`estimateno` -> Quote Number, `validthrough` -> Valid Until).
Minimal override shape:

```json
{
  "quoteNumber": "Q-2026-0071",
  "date": "2026-09-11",
  "validUntil": "2026-10-11",
  "currency": "USD",
  "projectName": "Warehouse Wi-Fi refresh",
  "vendor": { "name": "Northline Networks LLC" },
  "customer": { "name": "Harbor Foods Co-op" },
  "items": [{ "description": "Site survey", "qty": 1, "total": 950 }],
  "subtotal": 18400,
  "total": 19932,
  "depositLabel": "Deposit due on acceptance (25%)"
}
```

**3. Render.** Production path is the stored template (billed, 1 credit
per 10 pages):

```sh
curl -s -X POST https://makespdf.com/api/v1/render \
  -H "Authorization: Bearer $MAKESPDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"templateId": "quote-classic", "data": {...}}' -o quote.pdf
```

Iterating on a customised fork? Draft it free with
`POST /api/v1/preview { dsl, data }`, pre-flight with
`POST /api/v1/preview/validate`, then save via
`POST /api/v1/templates { dsl, name }` and render your copy.

## Traps

- Every quote needs an expiry: always fill `valid-until`, and say the
  validity window in days alongside it.
- Quotes that become orders need `acceptance-signature` (or the
  template's signature block) — a quote without an acceptance path is a
  brochure, not an offer.
- Numeric table columns stay `auto`/`1fr`, never fixed `%` widths on
  Qty / Unit Price / Amount.
