Sheet Smith

Template-to-PDF API. Turn JSON into clean, branded PDFs: quotes, invoices, receipts, certificates, packing slips and proposals, with real line items. Works from any HTTP client, Airtable buttons, Make and n8n.

Quickstart

  1. Get an API key. Keys are issued by the service operator during the beta. Your key looks like ss_live_…; keep it secret.
  2. Send a render request with a template id and your data. The response body is the PDF itself.
curl -X POST https://api.sheetsmith.pro/v1/render \
  -H "Authorization: Bearer $SHEETSMITH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "quote",
    "data": {
      "company": {"name": "Your Company LLC"},
      "client":  {"name": "Client Inc."},
      "quote_number": "Q-1001",
      "date": "2026-09-28",
      "items": [
        {"description": "Design work", "quantity": 10, "unit_price": 95},
        {"description": "Hosting (1 year)", "quantity": 1, "unit_price": 240}
      ],
      "tax_rate": 8.25
    },
    "branding": {"brand_color": "#1F5F8B"}
  }' \
  -o quote.pdf

Open quote.pdf. Totals are calculated for you. Browse every template and its example payload at Templates or GET https://api.sheetsmith.pro/v1/templates.

Render API

POST /v1/render. Authenticate with Authorization: Bearer <key> or X-API-Key: <key>. Returns application/pdf.

Body

FieldTypeDescription
templatestring, requiredTemplate id: quote, invoice, receipt, certificate, packing_slip, proposal.
dataobject, requiredTemplate fields (see each template's example). Unknown keys are ignored.
brandingobject, optionalLogo, brand color and font (below).
optionsobject, optionalpage_size (Letter default, or A4), filename, date_format (strftime, default %b %d, %Y).

Line items and totals

Each item takes description, quantity (default 1), unit_price, and optionally details, sku, unit, line_total. Aliases qty, price/rate, amount and name also work. Totals use exact decimal math: subtotal = Σ quantity × unit_price, then discount or discount_percent, then tax or tax_rate (percent of subtotal minus discount), plus shipping. Any amount you send yourself is used as-is. Percentages are whole numbers: 8.25 means 8.25%. Set currency to an ISO code (default USD) and optionally currency_symbol. Up to 500 line items per document.

Branding

FieldDescription
logo_urlPublic https:// URL of a PNG, JPEG, SVG or WebP logo.
logo_base64Or the image itself as base64 / data URI (max 1 MB). Use one or the other.
brand_colorHex color for headings and accents, e.g. #1F5F8B.
font_familyFont name, e.g. Lato. Falls back to a clean sans-serif if unavailable.
font_urlPublic URL of a TTF/OTF/WOFF/WOFF2 file to load that font.

Remote files must be on public http(s) hosts (ports 80/443), are fetched with a short timeout and size limit, and private or internal addresses are refused.

Response headers

HeaderMeaning
X-Usage-CountDocuments rendered by this key in the current UTC month (including this one).
X-Usage-LimitMonthly limit for the key's plan (unlimited if none).
X-Page-CountPages in the PDF.
X-Watermarktrue on the free plan.
Content-Dispositioninline; filename="quote-Q-1001.pdf" (from the document number).
X-Render-WarningsPresent when a remote logo or font could not be loaded (the PDF still renders).

Errors

Errors are JSON: {"error": {"code": "...", "message": "...", "details": [{"field": "data.items[2].unit_price", "message": "..."}]}}

StatusCodeWhen
401missing_api_key, invalid_api_keyNo key, unknown key or revoked key.
413payload_too_largeRequest body over 2 MB.
422validation_error, unknown_templateMissing required fields, bad values, blocked URLs, too many line items. details lists each field.
429monthly_limit_reachedThe key's monthly document limit is used up. Includes limit, used and period.

Templates

All templates accept the same branding. Required fields are marked; everything else is optional.

Quote / Estimate quote

Quote with company and client blocks, line items, discount, tax, totals, notes, terms and an acceptance block.

Required: company, client, quote_number, date, items

{
  "template": "quote",
  "data": {
    "company": {
      "name": "Harborline Digital Studio LLC",
      "address": "410 Example Avenue, Suite 12\nPortland, OR 97201\nUnited States",
      "email": "hello@harborline.example.com",
      "phone": "+1 (503) 555-0142",
      "website": "harborline.example.com",
      "tax_id": "EIN 00-0000000"
    },
    "client": {
      "name": "Cedar & Pine Outfitters Inc.",
      "contact_name": "Jordan Alvarez",
      "address": "88 Sample Road\nBoise, ID 83702",
      "email": "jordan@cedarpine.example.com",
      "phone": "+1 (208) 555-0199"
    },
    "quote_number": "Q-2026-0142",
    "date": "2026-09-28",
    "valid_until": "2026-10-28",
    "project": "E-commerce storefront refresh",
    "prepared_by": "Rowan Ellis",
    "currency": "USD",
    "items": [
      {
        "description": "Discovery workshop",
        "details": "Half-day session with stakeholders, requirements summary",
        "quantity": 1,
        "unit_price": 1200
      },
      {
        "description": "UX wireframes",
        "details": "Home, category, product, cart, checkout",
        "quantity": 5,
        "unit": "pages",
        "unit_price": 350
      },
      {
        "description": "Visual design system",
        "quantity": 1,
        "unit_price": 2400
      },
      {
        "description": "Front-end development",
        "quantity": 64,
        "unit": "hrs",
        "unit_price": 115
      },
      {
        "description": "Product data migration",
        "details": "Up to 1,500 SKUs from CSV",
        "quantity": 1,
        "unit_price": 950
      },
      {
        "description": "Launch support",
        "quantity": 8,
        "unit": "hrs",
        "unit_price": 95
      }
    ],
    "discount_percent": 5,
    "discount_label": "Returning client discount",
    "tax_rate": 0,
    "notes": "Pricing assumes content (copy and product photos) is supplied by Cedar & Pine before development starts.",
    "terms": "50% deposit due on acceptance, balance due on launch. Quote valid for 30 days. Additional work billed at $115/hr."
  },
  "branding": {
    "brand_color": "#1F5F8B"
  }
}
Invoice invoice

Invoice with bill-to/ship-to, due date, PO number, line items, tax, amount paid, balance due and payment instructions.

Required: company, bill_to, invoice_number, date, items

{
  "template": "invoice",
  "data": {
    "company": {
      "name": "Harborline Digital Studio LLC",
      "address": "410 Example Avenue, Suite 12\nPortland, OR 97201\nUnited States",
      "email": "hello@harborline.example.com",
      "phone": "+1 (503) 555-0142",
      "website": "harborline.example.com",
      "tax_id": "EIN 00-0000000"
    },
    "bill_to": {
      "name": "Cedar & Pine Outfitters Inc.",
      "contact_name": "Jordan Alvarez",
      "address": "88 Sample Road\nBoise, ID 83702",
      "email": "jordan@cedarpine.example.com",
      "phone": "+1 (208) 555-0199"
    },
    "ship_to": null,
    "invoice_number": "INV-2026-0317",
    "date": "2026-09-28",
    "due_date": "2026-10-28",
    "po_number": "PO-55120",
    "payment_terms": "Net 30",
    "currency": "USD",
    "items": [
      {
        "description": "Front-end development (September)",
        "quantity": 42,
        "unit": "hrs",
        "unit_price": 115
      },
      {
        "description": "Hosting & maintenance plan",
        "details": "Monthly retainer",
        "quantity": 1,
        "unit_price": 450
      },
      {
        "description": "Stock photography license",
        "quantity": 12,
        "unit_price": 18.5
      },
      {
        "description": "Rush turnaround surcharge",
        "quantity": 1,
        "unit_price": 300
      }
    ],
    "tax_rate": 8.25,
    "tax_label": "Sales tax",
    "amount_paid": 2000,
    "payment_instructions": "Bank transfer: Example Bank, Routing 000000000, Account 0000123456 (fictitious)\nPlease include the invoice number as the payment reference.",
    "notes": "Thank you for your business!"
  },
  "branding": {
    "brand_color": "#2E6B4F"
  }
}
Receipt receipt

Payment receipt with items, tax, payment method and transaction ID.

Required: company, receipt_number, date, items

{
  "template": "receipt",
  "data": {
    "company": {
      "name": "Little Fern Café",
      "address": "12 Placeholder Lane\nAsheville, NC 28801",
      "phone": "+1 (828) 555-0107",
      "website": "littlefern.example.com"
    },
    "customer": {
      "name": "Sam Rivera",
      "email": "sam.rivera@example.com"
    },
    "receipt_number": "R-000981",
    "date": "2026-09-28",
    "payment_method": "Visa •••• 4242",
    "transaction_id": "txn_test_7F3K9Q",
    "currency": "USD",
    "items": [
      {
        "description": "Catering platter - Mediterranean",
        "quantity": 2,
        "unit_price": 64
      },
      {
        "description": "Cold brew growler (64 oz)",
        "quantity": 3,
        "unit_price": 18
      },
      {
        "description": "Seasonal pastry box",
        "quantity": 1,
        "unit_price": 32
      },
      {
        "description": "Delivery",
        "quantity": 1,
        "unit_price": 15
      }
    ],
    "tax_rate": 7,
    "notes": "Thanks for supporting local! Questions? Reply to your email receipt."
  },
  "branding": {
    "brand_color": "#8A5A2B"
  }
}
Certificate certificate

Landscape certificate of completion/achievement with signature lines.

Required: recipient_name, achievement, date

{
  "template": "certificate",
  "data": {
    "title": "Certificate of Completion",
    "recipient_name": "Avery Thompson",
    "achievement": "Airtable Automations Masterclass",
    "description": "Successfully completed 12 hours of instruction and a final project on workflow automation.",
    "date": "2026-09-28",
    "certificate_id": "CERT-2026-04417",
    "company": {
      "name": "Northwind Learning Collective",
      "website": "northwind.example.com"
    },
    "signatories": [
      {
        "name": "Dana Whitfield",
        "title": "Lead Instructor"
      },
      {
        "name": "Morgan Lee",
        "title": "Program Director"
      }
    ]
  },
  "branding": {
    "brand_color": "#6B4C9A"
  }
}
Packing Slip packing_slip

Packing slip with ship-to, shipment details and SKU / ordered / shipped quantities (no prices).

Required: company, ship_to, order_number, date, items

{
  "template": "packing_slip",
  "data": {
    "company": {
      "name": "Bramble & Co. Home Goods",
      "address": "900 Warehouse Way, Unit B\nReno, NV 89502",
      "email": "orders@bramble.example.com",
      "phone": "+1 (775) 555-0163"
    },
    "ship_to": {
      "name": "Priya Natarajan",
      "address": "27 Specimen Street, Apt 4C\nMadison, WI 53703",
      "phone": "+1 (608) 555-0118"
    },
    "order_number": "BR-104522",
    "date": "2026-09-26",
    "ship_date": "2026-09-28",
    "shipping_method": "UPS Ground",
    "tracking_number": "1Z999AA10123456784",
    "package_count": 2,
    "weight": "14.2 lb",
    "items": [
      {
        "sku": "LIN-QN-OAT",
        "description": "Stonewashed linen duvet cover - Queen, Oat",
        "quantity_ordered": 1,
        "quantity": 1
      },
      {
        "sku": "LIN-PC-OAT",
        "description": "Linen pillowcase pair - Oat",
        "quantity_ordered": 2,
        "quantity": 2
      },
      {
        "sku": "CER-MUG-SG",
        "description": "Stoneware mug - Sage",
        "quantity_ordered": 4,
        "quantity": 4
      },
      {
        "sku": "CND-CED-8",
        "description": "Cedar & smoke candle, 8 oz",
        "quantity_ordered": 2,
        "quantity": 1,
        "details": "1 unit backordered - ships separately"
      }
    ],
    "notes": "Backordered items ship at no extra cost. Returns accepted within 30 days."
  },
  "branding": {
    "brand_color": "#37474F"
  }
}
Proposal proposal

Multi-section proposal with summary, sections, milestones, optional pricing table and acceptance block.

Required: title, company, client, date

{
  "template": "proposal",
  "data": {
    "title": "Operations Dashboard & Automation Proposal",
    "company": {
      "name": "Harborline Digital Studio LLC",
      "address": "410 Example Avenue, Suite 12\nPortland, OR 97201\nUnited States",
      "email": "hello@harborline.example.com",
      "phone": "+1 (503) 555-0142",
      "website": "harborline.example.com",
      "tax_id": "EIN 00-0000000"
    },
    "client": {
      "name": "Cedar & Pine Outfitters Inc.",
      "contact_name": "Jordan Alvarez",
      "address": "88 Sample Road\nBoise, ID 83702",
      "email": "jordan@cedarpine.example.com",
      "phone": "+1 (208) 555-0199"
    },
    "proposal_number": "P-2026-021",
    "date": "2026-09-28",
    "valid_until": "2026-10-31",
    "prepared_by": "Rowan Ellis, Principal Consultant",
    "summary": "Cedar & Pine currently tracks orders, inventory and supplier quotes across four spreadsheets. This proposal outlines a single Airtable base with automated quote and invoice generation, cutting manual admin by an estimated 6-8 hours per week.",
    "sections": [
      {
        "heading": "Goals",
        "body": "1. One source of truth for orders, inventory and suppliers.\n2. Quotes and invoices generated from records in one click.\n3. Weekly inventory report emailed automatically."
      },
      {
        "heading": "Approach",
        "body": "We start with a two-hour discovery call to map current workflows, then build the base iteratively with a review at each milestone. Your team gets a recorded walkthrough and written runbook at hand-off."
      },
      {
        "heading": "What's not included",
        "body": "Third-party subscription costs (Airtable, automation platforms) and data clean-up beyond the first 2,000 records."
      }
    ],
    "milestones": [
      {
        "name": "Discovery & data model",
        "timing": "Week 1",
        "description": "Workflow mapping, base schema sign-off"
      },
      {
        "name": "Base build & migration",
        "timing": "Weeks 2-3",
        "description": "Tables, views, import of existing spreadsheets"
      },
      {
        "name": "Automations & documents",
        "timing": "Week 4",
        "description": "Quote/invoice PDFs, inventory report"
      },
      {
        "name": "Training & hand-off",
        "timing": "Week 5",
        "description": "Live session, recording, runbook"
      }
    ],
    "currency": "USD",
    "items": [
      {
        "description": "Discovery & data model",
        "quantity": 1,
        "unit_price": 1500
      },
      {
        "description": "Base build & migration",
        "quantity": 1,
        "unit_price": 4200
      },
      {
        "description": "Automations & document templates",
        "quantity": 1,
        "unit_price": 2800
      },
      {
        "description": "Training & hand-off",
        "quantity": 1,
        "unit_price": 900
      }
    ],
    "terms": "40% on signature, 40% at milestone 3, 20% on hand-off. Proposal valid until the date above."
  },
  "branding": {
    "brand_color": "#1F5F8B"
  }
}

Airtable button setup

Add a button to any Airtable record that opens its PDF, pulling the record and its linked line-item records. No scripting or automations needed.

1. Create a personal access token

  1. In Airtable, open Builder hub → Personal access tokens → Create token.
  2. Add the scope data.records:read only.
  3. Under Access, add just the one base that holds your quotes.
  4. Copy the token (it starts with pat).

2. Create a connection

Tell the service which table to read and how your fields map to the template. field_map maps template fields to your Airtable field names; use dotted names for the client block (client.name). Put constant values such as your own company details in static_data.

curl -X POST https://api.sheetsmith.pro/v1/airtable/connections \
  -H "Authorization: Bearer $SHEETSMITH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Quotes",
    "pat": "patXXXXXXXXXXXXXX.XXXXXXXX",
    "base_id": "appXXXXXXXXXXXXXX",
    "table": "Quotes",
    "template": "quote",
    "field_map": {
      "quote_number": "Quote #",
      "date": "Date",
      "valid_until": "Valid Until",
      "client.name": "Client Name",
      "client.email": "Client Email",
      "client.address": "Client Address",
      "tax_rate": "Tax Rate",
      "discount_percent": "Discount",
      "notes": "Notes"
    },
    "static_data": {
      "company": {"name": "Your Company LLC", "email": "hello@example.com"},
      "currency": "USD",
      "terms": "50% deposit on acceptance."
    },
    "line_items": {
      "link_field": "Line Items",
      "table": "Line Items",
      "field_map": {"description": "Item", "quantity": "Qty", "unit_price": "Unit Price",
                    "line_total": "Amount", "details": "Notes"}
    },
    "logo_field": "Logo",
    "branding": {"brand_color": "#1F5F8B"}
  }'

The token is checked with one Airtable call. If it is invalid, lacks data.records:read or can't see the base/table, you get a clear error. The response includes your button formula:

CONCATENATE("https://api.sheetsmith.pro/v1/airtable/b/<link-token>/", RECORD_ID())
Copy the formula when you create the connection. The link token is stored hashed and can't be shown again; POST /v1/airtable/connections/{id}/rotate-link issues a new one (the old link stops working).

3. Add the Button field

  1. In the Quotes table add a field of type Button, label it e.g. PDF.
  2. Action: Open URL. Paste the formula from step 2 as the URL formula.
  3. Click the button on any record: the PDF opens in a new tab.

Field types

Each button link is rate-limited per plan: free keys get 5 PDFs per minute and 30 per hour; paid keys get 30 per minute and 300 per hour. Beyond that a friendly "try again shortly" page is shown. Clicks over the limit never call Airtable and never count against your monthly quota.

Manage connections with GET /v1/airtable/connections, PATCH /v1/airtable/connections/{id} (e.g. {"enabled": false} or a new pat) and DELETE /v1/airtable/connections/{id}. The token is never returned by the API.

Make

Use the built-in HTTP → Make a request module. (A dedicated Make app is planned; it is not available yet.)

SettingValue
URLhttps://api.sheetsmith.pro/v1/render
MethodPOST
HeadersAuthorization: Bearer ss_live_…
Body typeRaw, content type JSON (application/json)
Request contentYour JSON, e.g. {"template": "invoice", "data": {…}}, mapping values from earlier modules.
Parse responseNo. The response is a binary file: the module's Data output is the PDF.

Pass the Data output to Google Drive "Upload a file", Gmail/Email attachments or Airtable. Name the file e.g. quote-{{number}}.pdf.

n8n

Use the HTTP Request node:

SettingValue
MethodPOST
URLhttps://api.sheetsmith.pro/v1/render
AuthenticationGeneric credential → Header Auth: name Authorization, value Bearer ss_live_…
Send BodyOn. Body content type JSON, "Using JSON" with your payload (expressions allowed).
Options → ResponseResponse format File; put output in field data.

The binary data property can go straight into Send Email, Google Drive or Write Binary File nodes.

Free plan & limits

Data retention