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).

Next steps​