SQL Server
There is no direct connector to SQL Server. There are two reliable ways to keep a table current, and which to choose depends on whether you need rows within seconds or within the hour.
| Scheduled pull | Webhook receiver | |
|---|---|---|
| Latency | minutes to hours, your schedule | seconds |
| Needs a public endpoint | no | yes |
| Runs where | inside your network, on a schedule | a small web service |
| Effort | one script | one small service |
| Recommended for | most reporting | live dashboards, triggers |
Scheduled pull
A script on your side signs in, asks the API for records changed since it last ran, and upserts them. Nothing is exposed to the internet, and it recovers from any outage by asking for everything since the last successful run.
Create a dedicated integrations member with View on the forms it pulls. Its token then does nothing else.
The table. One row per record, keyed on the record’s id, with the
record’s metadata and the fields you care about as columns. Keep the whole
data JSON as well — a field added to the form later is then already in the
database, waiting to be promoted to a column.
CREATE TABLE dbo.equipment_inspections (
id uniqueidentifier NOT NULL PRIMARY KEY,
status nvarchar(20) NOT NULL,
submitted_at datetime2 NULL,
updated_at datetime2 NOT NULL,
asset_id nvarchar(50) NULL,
inspected_on date NULL,
hours_run decimal(9,1) NULL,
safe_to_use bit NULL,
data nvarchar(max) NOT NULL -- the whole record, as JSON
);The pull, in outline — any language with an HTTP client and a SQL driver:
- Read the high-water mark:
SELECT MAX(updated_at) FROM dbo.equipment_inspections. - Sign in and request
/rest/v1/submissions?form_id=eq.<form>&updated_at=gt.<mark>&order=updated_at&limit=500, paging withoffsetuntil fewer than 500 come back. - For each record,
MERGEonid: update if present, insert if not. Pull the columns you want out ofdatawithJSON_VALUEon the way in, or afterwards with a computed column. - Schedule it — SQL Agent, Task Scheduler, a cron — as often as you need.
JSON_VALUE(data, '$.asset.asset_id') reaches into a Record Lookup;
OPENJSON(data, '$.checks') turns a repeatable section into rows.
Deleted records do not come back from the API, so a record deleted in
FormDragon stays in your table until you ask for it. If that matters, also
subscribe a webhook to submission.deleted.
Webhook receiver
For rows within seconds, run a small HTTPS service that receives a
webhook and does the same MERGE. Verify
the signature, answer 200 immediately, do the insert afterwards, and make it
idempotent on data.id — deliveries can repeat.
What it receives
A POST with the record under data, its answers under data.data. Filter
on data.form_id — a webhook fires for every form.
Combine the two: the webhook keeps the table live, and a nightly pull catches anything a webhook missed.
Rather not build either? Write to customer.service@firedragontech.com and tell us where the data needs to land. We will help you get it there.