Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: CI
on:
pull_request:
push:
branches: [main, dev]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: node scripts/generate.mjs && git diff --exit-code
- run: npm test
58 changes: 58 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Development notes

This is a Make custom app in the local project format used by the Make Apps Editor extension for VS Code (`makecomapp.json`, `general/`, `connections/`, `modules/`).

## Layout

- `scripts/generate.mjs` writes every JSON file under `general/`, `connections/`, `modules/`, `webhooks/`, `rpcs/` and `makecomapp.json` from `scripts/params.mjs`, the fixtures in `test/fixtures/` and the shared operation catalog. `scripts/catalog.json` is a vendored copy of the catalog used by the Zapier and n8n apps (`scripts/catalog.sha256` pins it; a test fails on drift) and `scripts/catalog-modules.mjs` translates it into modules, the webhook and the dynamic dropdowns. The generated files are committed. Edit the scripts, then run `node scripts/generate.mjs`.
- `test/catalog.test.mjs` checks every catalog module (request, output, TCPA flag, billing text, guards, webhook attach and detach).
- `test/structure.test.mjs` checks the manifest, file links, billing and compliance copy, and that no callback or wallet fields exist.
- `test/replay.test.mjs` renders the request templates with a small IML evaluator (`test/iml.mjs`) and compares the request bodies and output mapping to the n8n and Zapier integrations.

```
node --test "test/*.test.mjs"
```

Node 20 or later. There are no dependencies.

## Import into Make

1. Create a Make account (the organisation that will own the app) and a Make API key with the `apps:read` and `apps:write` scopes.
2. Install the Make Apps Editor extension in VS Code and open this folder.
3. Put the API key in `.secrets/apikey` (the folder is git-ignored).
4. In `makecomapp.json`, set `origins[0].baseUrl` to your zone, for example `https://us1.make.com/api` or `https://eu1.make.com/api`.
5. Run **Deploy to Make** from the extension. The app is created as a private app with id `batchdata`.
6. Open the app in Make and run the checks below.

## What was and was not verified

Verified here (offline): JSON validity, manifest links, request bodies and output mapping against mocked BatchData responses, billing and compliance copy, no callback or wallet fields.

Not verified, needs a Make account and a BatchData test token (a sandbox token returns mock data at no cost):

- Import with the VS Code extension (the file layout follows public examples, not a Make validator).
- Connection check. It POSTs `{"requests":[]}` to `/v1/address/verify` and marks the connection valid on HTTP 400 or 2xx through `response.valid`. If Make marks the 400 as an error before it reads `valid`, switch the check to `GET https://api.batchdata.com/api/v2/property/search-sessions?take=1` (valid on 2xx). Also confirm with BatchData that the rejected empty request is not billed.
- Optional fields. The templates use `ifempty(x, undefined)` and `omit()` so empty fields are not sent. Nested optional filters (for example Permit Status) are collection parameters that are dropped when empty. Check that an unfilled nested collection (for example Building) is not sent as `{}`.
- Instant triggers. Check that turning a scenario on creates the property subscription (attach), that a test event arrives with `eventId` set, and that turning it off deletes the subscription (detach, `externalHookId`). Create hooks only with a sandbox token: a subscription counts towards the team's limit of 5 and cannot be edited.
- Polling triggers (`Watch New Search Sessions`, `Watch New Properties in a Search Session`): confirm the date ordering and that a first run does not replay old items as expected.
- Dynamic dropdowns (`rpc://listSearchSessions`, `rpc://listMonitors`): confirm the label and value mapping.
- The `{{...}}` spread in the Search Properties output (adds `searchMeta` next to each property).
- Make an API Call: the wallet guard redirects any path containing `wallet` to a non-existent path. IML cannot raise a validation error, so this is best effort. Decide whether to keep the module.

- Webhook dedupe. The webhook sets `uid` to `body.eventId`; confirm in Make that a repeated event does not start a second run.
- Callback keys. IML cannot strip keys recursively. Make an API Call blocks (sends nothing) any body that contains `webhook` or a JSON unicode escape (`u00`). The Additional Criteria JSON fields on search, session and monitor modules are not stripped; BatchData's synchronous endpoints ignore callback keys, and the monitor and trigger modules fix `deliveryConfig` themselves. A Make custom function that strips the keys would close this gap.

## Decisions

- Triggers: the instant triggers use a BatchData webhook subscription (`deliveryConfig {type: "webhook"}`) created on attach and deleted on detach; the hook URL is the scenario's own and is never entered by the user. Polling triggers cover new search sessions and new properties in a session (billed, opt-in by choosing that module). Billed property hydration is a separate module so the default instant trigger never bills a lookup. There is no new-monitor polling trigger (no date or ordered ID).
- Monitor creation (`Create Property Monitor`) is stream delivery only; Make an API Call blocks monitor create or edit calls so webhook URLs only come from the trigger.
- No callback URL fields (`webhookUrl`, `errorWebhookUrl`): they are for asynchronous requests only.
- Skip trace is two modules because V1 and V3 return different shapes. The TCPA option is always sent explicitly (V1 excludes flagged numbers by default, V3 includes them).
- Search sends one request of at most 100 records and does not page, so one run cannot bill more than 100 records.

## Push steps (Make Apps Editor)

1. In the Make account that will own the app, create an API key with scopes `apps:read` and `apps:write` (Profile, API access).
2. Install the Make Apps Editor extension in VS Code, open this folder and save the key to `.secrets/apikey`.
3. Set `origins[0].baseUrl` in `makecomapp.json` to the account zone (for example `https://us1.make.com/api`).
4. Run **Deploy to Make**, then the checks above. The app starts private; to publish it publicly submit it for Make review from the app page in Make.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 BatchData
Copyright (c) 2026 BatchData (batchdata.io)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
62 changes: 48 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# BatchData for Make

Use BatchData property data inside Make scenarios: search properties, get property details, find owner contact details, verify addresses and check phone numbers.
Use BatchData property data inside Make scenarios: search and look up properties, skip trace owners (V1 and V3, single and batch), reverse skip trace, verify and geocode addresses, check phone numbers, get permits, find investors by buy box, run search sessions and watch property monitors, with polling and instant (webhook) triggers and a generic API call module.

Support: support@batchservice.com

> **Status: v0.2.0, not yet imported into Make.** It passes its offline tests. Most operations were smoke-tested live through the BatchData API; monitors and the instant trigger were not (see [What was and was not verified](#what-was-and-was-not-verified)).

![BatchData](assets/logo.png)

## Connect

Expand All @@ -11,22 +17,50 @@ If the token is rejected, create a new one. For help, contact support@batchservi

## Modules

| Module | What it does | Billing |
| --- | --- | --- |
| Search Properties | Finds properties by location and filters. Up to 100 records per run. | Per record returned (0 is billed as 1) |
| Get Property Details | Full property data for one address or ID. | Per matched property |
| Skip Trace Owner (V1) | Owner contact details, one result per person. | Per matched property |
| Skip Trace Owner (V3) | Owner contact details, one result per property with a persons list. | Per matched property |
| Verify Address | Standardizes one US address. | Per address |
| Verify Phone Numbers | Reachability, carrier, DNC and TCPA flags. | Per phone number |
| Check Do Not Call | Do Not Call registry check. | Per phone number |
| Check TCPA Litigator | TCPA litigator list check. | Per phone number |
| Make an API Call | Any other BatchData API path. | Follows the endpoint |
Billing text is also in each module's description in Make.

| Module | Type | What it does | Billing |
| --- | --- | --- | --- |
| Search Properties | Search | Finds properties by location and filters. Up to 100 records per run. | Per record returned (0 is billed as 1) |
| Get Property Details | Search | Full property data for one address or ID. | Per matched property |
| Batch Look Up Properties | Search | Full records for up to 100 addresses in one call. | Per matched property |
| Skip Trace Owner (V1) | Search | Owner contact details, one result per person. | Per matched property |
| Skip Trace Owner (V3) | Search | Owner contact details, one result per property with a persons list. | Per matched property |
| Batch Skip Trace Properties (V3) | Search | Up to 100 properties in one call. | Per matched property |
| Reverse Skip Trace (Phone or Email) | Search | Finds the person behind a phone number or email. | Per matched result |
| Verify Address / Batch Verify Addresses | Search | Standardizes one or up to 100 US addresses. | Per address |
| Autocomplete, Geocode, Reverse Geocode | Search | Address suggestions, coordinates, nearest addresses. | This call does not bill property records |
| Verify Phone Numbers, Check Do Not Call, Check TCPA Litigator | Search | Phone checks. | Per phone number |
| Get Property Permits | Search | Building permits for one property, one result per permit. | See the module description |
| Find Investors (Buy Box), Get Investor Properties | Search | Investors who bought near a subject property, and their holdings. | See the module description |
| List, Create or Advance, Delete Search Session | Search, Action | Persistent search sessions that return only properties not yet delivered. | Create or Advance bills each record delivered |
| List, Get, Create, Delete Property Monitor | Search, Action | Property monitors with stream delivery (Kinesis or Azure Event Hubs). | According to your BatchData plan |
| Watch New Search Sessions | Polling trigger | New search sessions on your team. | Does not bill property records |
| Watch New Properties in a Search Session (Billed) | Polling trigger | New properties delivered by a session. | Every check bills each property delivered |
| Watch Property Monitor Events (Instant) | Instant trigger | Fires when a property is added to, removed from or changed in a monitor. | According to your BatchData plan |
| Watch Property Monitor Events with Property Record (Instant, Billed) | Instant trigger | Same, plus the full property record. | Plan billing, plus one property lookup per event |
| Make an API Call | Universal | Any other BatchData API path. Wallet, asynchronous and monitor create or edit paths are blocked, and so are bodies with callback URL fields. | Follows the endpoint |

### Instant triggers (property monitor events)

Turning a scenario on creates a V2 property subscription whose delivery is the scenario's own Make webhook URL. Turning it off (or deleting the scenario) deletes that subscription. You never enter a callback URL. Each event is `{eventId, propertyId, parcelHash, addressHash, addedToSubscriptionIds, removedFromSubscriptionIds, propertyChangedAt, sentAt}`. The event carries IDs only; use the module with **Property Record** to add the full record (one billed property lookup per event). Use `eventId` to skip repeats.

Limits (also in each trigger's description): up to 5 monitors per team, a monitor cannot be edited after it is created (delete and recreate it), a new monitor can take up to 7 days to start delivering, and delivery is best effort (4 attempts per event). Because of the 5 monitor limit, avoid many scenarios that each create a monitor.

There is no polling "new monitor" trigger in Make: a polling trigger needs a date or an ordered ID on each item, and monitors have neither. Use List Property Monitors on a schedule instead. The Zapier and n8n apps do include one.

## Phone compliance

Skip trace and phone modules return data only. You are responsible for following the TCPA and Do Not Call rules before you contact anyone. Skip trace removes phone numbers flagged as TCPA litigators unless you switch on **Include phone numbers flagged as TCPA litigators**.

## Not included
## What was and was not verified

Verified live (production API, 1 record per call, through the same request shapes the other BatchData integrations use): property search, lookup, skip trace V1 and V3, reverse skip trace (no match), address verify, DNC, permits, investor buy box and properties, geocode, reverse geocode, autocomplete, and the search-session create, list and delete lifecycle.

Mocked only: property monitors and the instant triggers. The token used gets 403 on the subscription endpoints, so create, list, delete and event delivery need a sandbox token (mock data, no cost, from app.batchdata.com) or a token with that ability.

Offline tests (47) check the manifest, file links, copy rules (one support contact, billing text in every module, no callback fields) and the request body, query and output of every module against mocked responses. The offline IML evaluator is a subset of Make's engine, so Make itself has not run these modules; see `DEVELOPMENT.md` for the checks to run after import.

## License

There is no instant trigger (watch) module in this version. Use a scheduled scenario with Search Properties instead.
The code in this repository is released under the MIT License (see `LICENSE`). The BatchData API and the data it returns are proprietary to BatchData (batchdata.io) and are subject to BatchData's terms of service; the MIT License does not cover them. Support: support@batchservice.com
Binary file added assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions connections/batchdata/batchdata.communication.iml.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"url": "https://api.batchdata.com/api/v1/address/verify",
"method": "POST",
"headers": {
"Authorization": "Bearer {{parameters.apiKey}}",
"Content-Type": "application/json"
},
"body": {
"requests": []
},
"response": {
"valid": "{{statusCode == 400 || (statusCode >= 200 && statusCode < 300)}}",
"data": {
"apiKey": "{{parameters.apiKey}}"
},
"error": {
"401": {
"type": "InvalidAccessTokenError",
"message": "Invalid API token. Copy a fresh token from your BatchData account."
},
"403": {
"type": "RuntimeError",
"message": "This token cannot use the BatchData API. Contact support@batchservice.com."
},
"message": "[{{statusCode}}] {{ifempty(body.status.message, 'Could not verify the API token.')}}"
}
},
"log": {
"sanitize": [
"request.headers.authorization"
]
}
}
9 changes: 9 additions & 0 deletions connections/batchdata/batchdata.params.iml.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"name": "apiKey",
"type": "password",
"label": "API token",
"required": true,
"help": "Create an API token in your BatchData account and paste it here. Tokens are only available on plans with API access."
}
]
Loading
Loading