Gareth Wilson Gareth Wilson

Guide to Quickbase Webhooks: Features and Best Practices

Published


Quickbase webhooks send an HTTP request when records in a table change. A new project is added, a ticket's status moves to Issue, an order is deleted: each can call a URL with a message you design, so you can keep another system in sync, notify a chat tool, or start a process in your own service the moment the data changes.

This guide covers how Quickbase table webhooks are triggered and built, how to authenticate them with a secret header, the markers that make a message useful to a receiver, and the limits that decide whether a message is sent at all.

What are Quickbase webhooks?

A Quickbase webhook belongs to one table. Its When section picks the trigger: a record added, modified or deleted, in any combination, optionally narrowed to changes in specific fields or to records whose field values match criteria after the change. Its Then section is the whole outgoing request: endpoint URL, HTTP method, message format, headers and body.

Because you write the request, Quickbase adds nothing of its own. There's no event field, no fixed schema and no signature. What arrives is the body you composed, with field references and markers replaced by values from the record.

That includes authentication. You add a secret header to the webhook's Message header list, and your receiver checks it.

Quickbase webhook features

FeatureDetails
ConfigurationTable Settings > Workflow & Permissions > Webhooks > New Webhook, or API_Webhooks_Create
Who can create themApp admins and managers
TriggersRecord added, modified, deleted, with optional field and value criteria
EndpointMust begin with https://
HTTP methodPOST by default. Also GET, PUT, PATCH, DELETE
Message formatXML, JSON or RAW
HeadersUp to 10 name/value pairs
BodyYour template, with field references and markers. Sent as UTF-8
AuthenticationA secret header you add. No signature
Limits10 webhooks per table, 4 MB per message, 50 messages per second per app
Error reporting30-day error history, and email to the webhook owner
Retries and timeoutNot documented
PlansAll plans except Quickbase Essential

Building the message

Quickbase gives you field references and markers to fill the body. Field references are field names in square brackets, such as [Status], and [old.status] gives the value before the change. Markers include:

MarkerInserts
%action%Add, Replace or Delete, depending on what triggered the webhook
%webhookid%The webhook's numeric ID
%dbid%, %dbName%The table's ID and name
%appid%, %appName%The app's ID and name
%curuser%The user who triggered the webhook
%curdate%When the webhook was triggered
%reclink%A link to the changed record
%RepeatOn% ... %RepeatOff%Repeated content for each record when one event changes several rows

A JSON template for your own receiver might be:

{
  "action": "%action%",
  "webhook_id": "%webhookid%",
  "table_id": "%dbid%",
  "record_id": "[Record ID#]",
  "status": "[Status]",
  "previous_status": "[old.Status]",
  "changed_at": "%curdate%"
}

Use the field names from your own table. %action% and %webhookid% together tell your receiver what happened and which webhook sent it. Grid edits, CSV imports, search-and-replace and table merges can change several records in one event; use %RepeatOn% and %RepeatOff% if you need every row.

Quickbase's documentation gives Content-Type: application/json as an example message header, so add it when you send JSON.

Inspect Quickbase webhooks as they arrive. Point a webhook at a Hookdeck Inspect URL to see the method, headers and rendered body your template produces, with no account or setup required.

Setting up Quickbase webhooks

Generate a long random value first, for example with openssl rand -hex 32.

  1. Open the table, select Settings, and under Workflow & Permissions select Webhooks.
  2. Select New Webhook and give it a Name and Description.
  3. Under When, choose added, modified and/or deleted, and any Additional criteria.
  4. Under Then, enter the Endpoint URL and choose the HTTP method (leave it on POST unless you need another).
  5. Choose the Message format.
  6. Under Message header, add Content-Type if needed, and a secret header such as Authorization with the value Bearer <your random value>.
  7. Write the Message body, then select Save.

To route through Hookdeck, create a source with the Quickbase type and use its URL in step 4. Enter your secret header's name in API Key Header and its exact value, including any Bearer prefix, in API Key. Hookdeck finds the header case-insensitively and compares the whole value.

The Hookdeck source pre-selects POST but doesn't manage the method, because Quickbase lets you choose it. If your webhook uses PUT, PATCH, GET or DELETE, add that method to the source's allowed HTTP methods, or Hookdeck won't accept the request.

Securing Quickbase webhooks

Look up the header you added and compare its whole value with the stored secret, in constant time. Accept the methods your webhook uses, and don't assume there is a body: a GET or DELETE may have none.

const crypto = require('crypto');
const express = require('express');

const HEADER_NAME = (process.env.QUICKBASE_WEBHOOK_HEADER || 'authorization').toLowerCase();
const EXPECTED = process.env.QUICKBASE_WEBHOOK_SECRET; // e.g. "Bearer 3f9c..."

function safeEqual(received, expected) {
  const a = Buffer.from(received, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  // timingSafeEqual throws on unequal lengths, so check first.
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

const app = express();

// Quickbase lets each webhook choose its method, so accept the ones you configured.
app.all('/webhooks/quickbase', express.raw({ type: '*/*' }), (req, res) => {
  if (!['POST', 'PUT', 'PATCH', 'GET', 'DELETE'].includes(req.method)) {
    return res.sendStatus(405);
  }

  const received = req.get(HEADER_NAME);
  if (!EXPECTED || typeof received !== 'string' || !safeEqual(received, EXPECTED)) {
    return res.sendStatus(401);
  }

  const raw = Buffer.isBuffer(req.body) ? req.body.toString('utf8') : '';
  // Parse raw as JSON or XML to match the webhook's message format, then queue it.
  res.sendStatus(200);
});

The same check in Python:

import hmac
import os

HEADER_NAME = os.environ.get("QUICKBASE_WEBHOOK_HEADER", "Authorization")
EXPECTED = os.environ.get("QUICKBASE_WEBHOOK_SECRET", "")


def verify_quickbase_request(headers) -> bool:
    if not EXPECTED:
        return False  # never accept when unconfigured
    received = headers.get(HEADER_NAME)  # most frameworks look headers up case-insensitively
    if not received:
        return False
    # Compare bytes: compare_digest raises TypeError on a non-ASCII str.
    return hmac.compare_digest(received.encode("utf-8"), EXPECTED.encode("utf-8"))

A secret header authenticates the sender, not the body. It cannot detect a modified message, and with no signature or timestamp a captured request can be replayed and still pass. Quickbase also warns that webhooks "can be edited or copied by all admins in the app", and any credentials you enter are visible to them. Use a value that exists only for this webhook, keep it long and random, and change it if an admin leaves or it might have leaked.

Make Quickbase webhooks production-ready. Hookdeck Event Gateway checks your secret header, accepts each record change straight away, and delivers it to your service with retries, so a short outage doesn't lose an update.

Quickbase webhook limitations and pain points

Messages over the limits are not sent

The Problem: A bulk import or a busy app silently drops messages your receiver was counting on.

Why It Happens: Quickbase allows at most 50 webhook messages per second per app, shared with Pipelines listening on the same app, and won't send a message larger than 4 MB. Messages past either limit are not sent; the app manager gets an alert and an email.

Workarounds:

  • Narrow triggers with Additional criteria so only meaningful changes fire.
  • Send IDs and the fields you need, not whole records, to stay well under 4 MB.
  • Reconcile against the Quickbase API after large imports.

How Hookdeck Can Help: Hookdeck accepts bursts as fast as Quickbase sends them and delivers to your service at a max delivery rate you choose, so your endpoint never becomes the bottleneck.

No documented retries

The Problem: A request your endpoint fails during a deploy may never be resent.

Why It Happens: Quickbase logs failures in the error history and emails the webhook owner, but its documentation doesn't describe a retry policy or timeout.

Workarounds:

  • Keep the endpoint simple and available, and make sure the webhook owner reads the failure emails.
  • Review the 30-day View error history list after incidents.

How Hookdeck Can Help: Hookdeck stores each request it accepts and delivers it to your service with retries on your schedule, and you can replay any request after a fix.

Webhooks that stop firing

The Problem: A webhook that worked yesterday sends nothing today.

Why It Happens: The owner must have permission to the table, be a registered user and not be on the deny list, or the webhook isn't sent. Copied apps carry their webhooks over as inactive, and sharing an app to the Exchange removes them.

Workarounds:

  • Make a long-lived service account the owner of production webhooks.
  • After copying an app, select the copied webhooks and Activate them.

How Hookdeck Can Help: Issues and Hookdeck's request history make a sudden drop in traffic visible, so a silent webhook gets noticed.

Loops

The Problem: A webhook that writes back to its own table triggers itself again and again.

Why It Happens: An update made by the receiver is a record change like any other.

Workarounds:

  • Use Additional criteria so the receiver's own update can't match the trigger, as Quickbase advises.

How Hookdeck Can Help: Filters can drop requests that match your receiver's own changes before they reach it.

Best practices

Put %action% and %webhookid% in every body

They tell the receiver what happened and which webhook sent it, which Quickbase otherwise doesn't.

Keep the secret in a header

Add it under Message header and compare it whole, in constant time. Never put it in the URL or the body.

Prefer POST

It is the default and what most receivers expect. If you choose another method, allow it on the Hookdeck source and in your route.

Deduplicate

Include the record ID and %curdate% in the body and build an idempotency key from them. See our guide to webhook idempotency.

Acknowledge fast and process asynchronously

Store the message and respond, then do the work. See why to process webhooks asynchronously.

Conclusion

A Quickbase table webhook sends a request you design when records are added, modified or deleted, with no signature and no Quickbase-defined fields. Authenticate it with a secret header, put %action% and identifiers in the body, stay inside the 50-per-second and 4 MB limits, and allow any non-POST method on your receiver and on the Hookdeck source.

Hookdeck Event Gateway checks the header, absorbs bursts, and keeps every request until your service has processed it.

Get started with Hookdeck for free and handle Quickbase webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.