Skip to main content

NocoDB

Prerequisites

  • A PolyDoc account and API key - sign up for free, no credit card required. The free plan includes 150 PDF conversions per month.
  • A cloud storage bucket you control (S3, GCS, Azure Blob, R2, Wasabi, …). A NocoDB webhook is fire-and-forget - it can't read PolyDoc's response back into the table - so PolyDoc uploads the PDF to a presigned URL of yours and the object lives at that URL. See the cloud storage guide for per-provider presigning recipes.
  • A NocoDB base - NocoDB Cloud (free plan works) or self-hosted. The custom webhook payload, the Button field, and the Button's Run Webhook action are all available on the Free plan.

Use Case 1: Save the PDF to your bucket on record creation

Generate an invoice PDF whenever a new record is created in the invoices table, and upload it straight to your own cloud bucket.
Record created → Webhook (custom payload) → PolyDoc → your bucket

Set up your table

Use invoices (one row per invoice) and invoice_items (line rows linked by invoice_number). Examples below - two tabs in Sheets; two tables or linked records elsewhere.

invoice_numberinvoice_dateinvoice_due_dateinvoice_subtotalinvoice_tax_rateinvoice_tax_amountinvoice_totalcustomer_namecustomer_emailcustomer_streetcustomer_citycustomer_country
INV-2026-0012026-01-152026-02-1412000.11201320John Doejohn.doe@example.com456 Customer AvenueBeautiful CityUK
invoice_numberquantitynamedescriptionpriceoriginal_price
INV-2026-0011Web Design ServicesCustom website design and development for company homepage800
INV-2026-0011Logo DesignProfessional logo design with 3 revision rounds300
INV-2026-0011SEO OptimizationSearch engine optimization for 10 target keywords100150

In NocoDB you keep everything on one invoices table. Drop the separate line-items table and instead add three columns to invoices:

  • items_json (Long text): the line items as a JSON array string, e.g. [{"quantity":1,"name":"Web Design","description":"…","price":800}]. The script that creates the invoice row writes this.
  • presigned_url (URL): a presigned PUT URL for your bucket, one per invoice row, populated by the same script.
  • pdf_url (URL): optional. The webhook can't write back, but the finished PDF always lives at your presigned URL with the query string stripped, so you already know its address - store it here if you want it in the grid.

Create the webhook and trigger

Open the invoices table, switch to the Details tab, pick Webhooks, and click New Webhook. Configure:

  • Trigger: Record / After insert.
  • Action: HTTP Webhook, method POST, URL https://api.polydoc.tech/pdf/convert.
  • Headers tab - add three rows:
app.nocodb.com

Build the custom payload

Open the Body tab and paste the custom payload below. NocoDB renders it with Handlebars on every trigger, substituting the new row's fields:

{
"source": "[template:YOUR_TEMPLATE_ID]",
"templateData": {
"invoice_number": {{ json event.data.rows.[0].invoice_number }},
"invoice_date": {{ json event.data.rows.[0].invoice_date }},
"invoice_due_date": {{ json event.data.rows.[0].invoice_due_date }},
"invoice_subtotal": {{ json event.data.rows.[0].invoice_subtotal }},
"invoice_tax_rate": {{ json event.data.rows.[0].invoice_tax_rate }},
"invoice_tax_amount": {{ json event.data.rows.[0].invoice_tax_amount }},
"invoice_total": {{ json event.data.rows.[0].invoice_total }},
"customer_name": {{ json event.data.rows.[0].customer_name }},
"customer_email": {{ json event.data.rows.[0].customer_email }},
"customer_street": {{ json event.data.rows.[0].customer_street }},
"customer_city": {{ json event.data.rows.[0].customer_city }},
"customer_country": {{ json event.data.rows.[0].customer_country }},
"items": {{{ event.data.rows.[0].items_json }}}
},
"cloudStorage": {
"presignedUrl": {{ json event.data.rows.[0].presigned_url }}
}
}

A few NocoDB-specific points:

  • Text and date fields (invoice_number, the customer_* fields, invoice_date, invoice_due_date): wrap each in the {{ json … }} helper. It adds the quotes and escaping for you, so don't put your own quotes around it. NocoDB date columns serialise as ISO strings (YYYY-MM-DD).
  • Number fields (invoice_subtotal, invoice_tax_rate, invoice_tax_amount, invoice_total): the same {{ json … }} helper emits a real JSON number (not a quoted string), so the API gets 1320, not "1320".
  • The items array (items): use triple braces - {{{ event.data.rows.[0].items_json }}}. Triple braces inject the value raw, so the JSON array string in items_json lands as a real array. Double braces or the json helper would wrap it in quotes and the API would reject it.
app.nocodb.com

Save and generate

Click Save changes. Now create a test record in invoices with a fresh presigned_url and a populated items_json. Within a few seconds PolyDoc PUTs the finished PDF to your bucket - open the object URL (your presigned URL without its query string) to confirm.

Use Case 2: Generate the PDF on demand from a button

Add a Generate PDF button to each row so you can produce (or regenerate) an invoice PDF on demand, instead of only on creation.
Click button → Webhook (Button trigger) → PolyDoc → your bucket

Create a Button-trigger webhook

Create a new webhook on the invoices table exactly like Use Case 1, Steps 2 and 3 - same POST to https://api.polydoc.tech/pdf/convert, same three headers, and the same custom Body - but set the Trigger to Button instead of Record / After insert. Give it a recognisable title such as PolyDoc: generate on click.

Add the Button field

Add a new field to invoices, set its type to Button, then:

  • Label: e.g. Generate PDF.
  • On click: Run Webhook.
  • Webhook: select the Button-trigger webhook from Step 1.
app.nocodb.com

Click to generate

Click the Generate PDF button on any row whose presigned_url and items_json are filled. NocoDB fires the webhook and PolyDoc uploads the PDF to your bucket, same as Use Case 1. Re-clicking regenerates it (against a fresh presigned URL).