T TradieBridge Docs Sign in

TradieBridge docs

TradieBridge keeps a copy of your business's systems that you own. Read it from your own code with the data API, or from an AI assistant with the MCP server. Neither changes a source.

Sources

Data API

Authenticate

A company admin makes an API key in Settings → API keys and chooses the sources it reads.

curl -H "Authorization: Bearer tbk_…" https://app.tradiebridge.com/api/v1/connections

Endpoints

GET/connections

Your sources. A source that leaves this list was removed, with every record it held.

GET/changes

The IDs that changed after a cursor, across your sources. Keep the cursor it returns and send it next time. A webhook only says when to ask.

cursor
query · string. The cursor the last call answered. Leave it out to start from the oldest change held.
resources
query · string. Resource keys, comma-separated, to hear about those only.
limit
query · integer. How many changes a page: default 500, at most 1000.

GET/connections/{connection_id}/resources

What a source holds, with the columns a list filters and sorts by.

connection_id*
path · string. A source's id, from /connections.

GET/connections/{connection_id}/records/{resource}

A list of records by their stored columns: query, filters, sort, cursor, limit.

connection_id*
path · string. A source's id, from /connections.
resource*
path · string. A resource key, from that source's /resources.
query
query · string. Matches a source ID as a prefix, or a name holding every word.
filters
query · string. A JSON object keyed by stored column, e.g. {"stage": "Progress"}. A value, a list, or an object of operators: eq, ne, in, not_in, gte, lte, contains, null.
modified_since
query · string. An ISO 8601 time. Only records modified at or after it.
sort
query · string. A stored column, with - before it to sort descending, e.g. -modified_at.
cursor
query · string. The cursor the last page answered.
limit
query · integer. How many records a page: default 50, at most 200.

GET/connections/{connection_id}/documents/{resource}

Up to 100 whole documents by key, and the keys not held.

connection_id*
path · string. A source's id, from /connections.
resource*
path · string. A resource key, from that source's /resources.
keys*
query · string. Keys, comma-separated, at most 100.

GET/connections/{connection_id}/documents/{resource}/{key}

One whole document, exactly as the source sent it.

connection_id*
path · string. A source's id, from /connections.
resource*
path · string. A resource key, from that source's /resources.
key*
path · string. The record's key, as a list or the change feed answered it.

GET/connections/{connection_id}/answers/{question}

The common questions, answered from the backup. Each question takes its own arguments as query parameters.

connection_id*
path · string. A source's id, from /connections.
question*
path · string. A question the source answers, from that source's page in these docs.

GET/openapi.json

This reference as an OpenAPI 3.1 document. It needs no key.

Every path starts https://app.tradiebridge.com/api/v1.

Errors

An error answers JSON with one error string that says what to change.

  • 401: no key, or a key that was revoked.
  • 404: no such record, or a source this key does not read.
  • 422: refused, such as an unknown resource or column, or too many keys.
  • 429: more than 600 requests a minute or 20,000 requests an hour from one key. Wait the seconds in Retry-After.

Webhooks

When a sync writes records a webhook listens for, we POST one event per source and resource to it. An event carries IDs, never documents.

{
  "id": "evt_3kQ9xWm2PzR7vT4bN8cY1dLh",
  "type": "records.changed",
  "connection_id": 12,
  "resource": "jobs",
  "keys": [2111, 2746],
  "removed_keys": [],
  "created_at": "2026-10-03T04:12:55.120Z"
}
  • Answer with any 2xx within 10 seconds. We do not follow a redirect.
  • A failed delivery is sent again, less often each time, for three days. Then the webhook turns off and we email your admins.
  • Events can arrive twice or out of order. Use the event's id to drop a repeat, and read the current documents each time.
  • If your app was down, the change feed still holds every change since your cursor.

Check the signature

Every delivery carries a TradieBridge-Signature header:

TradieBridge-Signature: t=1790999575,v1=5f0c…

v1 is the hex HMAC-SHA256 of t.body, keyed with the signing secret shown once when the webhook was added. Compare in constant time, and refuse a t more than 300 seconds old.

timestamp, signature = header.split(",").map { _1.split("=", 2).last }
expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{raw_body}")
valid = ActiveSupport::SecurityUtils.secure_compare(expected, signature) &&
  (Time.now.to_i - timestamp.to_i).abs < 300

Exports

Any member can export a source's whole copy from its page in the app, as a zip file in one of three formats:

Documents
Every record exactly as the source sent it, in .ndjson files.
Spreadsheets
The searchable columns of every record, in .csv files.
Postgres
One .sql file that psql loads into any Postgres database, Supabase included.

AI assistants

For Claude, ChatGPT or any MCP assistant.

Connect

https://app.tradiebridge.com/mcp
  1. In Claude, open Settings → Connectors → Add custom connector.
  2. Paste the server URL. Claude sends you to TradieBridge to sign in and approve the connection.
  3. Turn it on in a chat from the + menu.

Any MCP client that supports OAuth connects the same way: the server publishes its protected resource metadata and authorization server metadata, and registers clients dynamically. A client without OAuth sends a bearer token from Connect to AI in the app.

An assistant reads as the person who connected it. It never sees tax file numbers, bank details or birth dates.

More than 120 requests a minute or 3,000 requests an hour from one assistant answers 429. Wait the seconds in Retry-After.

Tools

whoami

Return the authenticated TradieBridge user and company. Use to confirm the connection works.

No arguments.

list_connections

List the company's builds, each a copy of one source: id (pass it as build_id to the other tools), name, source, web address, the company or organisation backed up, sync health, when it last synced and how many records the backup holds.

No arguments.

describe_resources

What a build's backup holds. Without resource: every resource key with what it means, how many records it holds and what it hangs off, and the keys that hold none. Name one resource or several to add when each last synced and the columns search_records filters and orders by and summarize_records sums and groups by.

build_id
integer. Omit when only one of the company's builds holds the resource; list_connections names them.
resource
any. A resource key, or several, e.g. ["invoices", "customer_payments"].

search_records

Find records of one resource in a build's backup, of any source, highest source ID first, or largest first by order_by (ascending: true for smallest or oldest; empty values last). query matches a source ID as a prefix or a name holding every word; filters and order_by take the columns describe_resources lists. Answers the total that match and, when more remain, next_before_id to pass back as before_id (with order_by, raise limit instead). Each result's id is what get_record takes. For totals and counts use summarize_records instead of paging.

build_id
integer. Omit when only one of the company's builds holds the resource; list_connections names them.
resource*
string. A resource key from describe_resources, e.g. invoices.
query
string.
filters
object. Column filters, from the columns describe_resources lists for the resource: {"<column>": "value"}, {"<column>": ["one", "another"]}, {"<column>": {"contains": "acme"}}, {"<date column>": {"gte": "2026-04-01", "lte": "2026-06-30"}}. Operators: eq, ne, in, not_in, gte, lte, contains, null.
modified_since
string. ISO 8601 time; only records the source changed since then.
order_by
string. A number or date column describe_resources lists, to rank by.
ascending
boolean.
before_id
string. The next_before_id a previous page answered.
limit
integer. Default 25, at most 200.

summarize_records

Count, sum, average, min or max over one resource's records in one call, of any source, optionally per group. Takes the same query and filters as search_records. column is a number column from describe_resources (min and max also take a date). measures asks several figures at once, e.g. ["count", "sum", "avg"] over column, or "sum:<column>" for another column; the answer is then values, keyed as asked. group_by is a column, week:/month:/quarter:/year:<date column>, or a list of two, e.g. ["<column>", "month:<date column>"]. A week is named by its Monday. Groups come largest first, or in date order when a date is bucketed, at most 100.

build_id
integer. Omit when only one of the company's builds holds the resource; list_connections names them.
resource*
string. A resource key from describe_resources, e.g. invoices.
measure
string. Default count.
measures
array. Several figures in one call, in place of measure.
column
string. What to sum, average, min or max: a column describe_resources lists.
group_by
any. e.g. <column>, month:<date column>, or ["<column>", "quarter:<date column>"].
query
string.
filters
object. Column filters, from the columns describe_resources lists for the resource: {"<column>": "value"}, {"<column>": ["one", "another"]}, {"<column>": {"contains": "acme"}}, {"<date column>": {"gte": "2026-04-01", "lte": "2026-06-30"}}. Operators: eq, ne, in, not_in, gte, lte, contains, null.
modified_since
string. ISO 8601 time; only records the source changed since then.
limit
integer. Groups to answer. Default and most 100.

get_record

Records from a build's backup, of any source, exactly as the source sent them, with the records each one names (links) and the records hanging off it (related, first 50 of each). id is the source's own ID, or the id search_records returned; ids reads up to 20 at once. fields keeps only those keys of each document: top-level keys or dotted paths such as Contact.Name.

build_id
integer. Omit when only one of the company's builds holds the resource; list_connections names them.
resource*
string. A resource key from describe_resources.
id
string.
ids
array. Several ids, instead of id.
fields
array. Keys or dotted paths to keep, e.g. ["Name", "Contact.Name"].
related
boolean. Default true. False leaves out links and related records.

discover_questions

The questions ask_question answers in one call, for the sources this company holds: each one's name, what it answers and the arguments it takes, as a JSON schema. A question two sources share is listed under each, answered from that source's own records. Filter by source, or by a word or topic (money, tax, jobs, customers, sales, schedule, staff).

source
string. Only this source's questions, as list_connections names it.
topic
string. Only questions whose name, topic or description holds this word.

ask_question

Answer one of the questions the instructions name (discover_questions describes them) in one call, reading the build's copy server-side. arguments are the question's own; a missing or wrong one answers with the arguments it takes. Without build_id every build that answers the question answers it, each under answers with its build_id, build, source and as_of: two sources measure different ledgers, so read them side by side and never add them. build_id narrows to one build.

name*
string. The question's name, e.g. receivables.
arguments
object. The question's arguments. Omit for none.
build_id
integer. Only this build's answer; list_connections names them.

discover_operations

Search everything else TradieBridge can do, beyond the tools listed here — every screen and action in the app, named as "controller#action", with the arguments each one takes and the tool that runs it: call_read_operation for a read, call_write_operation for a write. Each refuses the other kind. Use it when no dedicated tool fits. Search by word: "export", "sync", "member".

query
string. Filter by substring, e.g. "invoice". Omit for all.

call_read_operation

Run one of the read-only operations discover_operations lists, with the arguments it named. A path argument goes at the top level ({"id": 7}). It changes nothing. You never name a company: the tenant comes from your token.

operation*
string. As listed by discover_operations, e.g. "connections#show".
params
object. Arguments for the operation. Omit for none.

call_write_operation

Run one of the write or destructive operations discover_operations lists, with the arguments it named. It changes data in TradieBridge. A path argument goes at the top level ({"id": 7}); a write's fields go nested under the key discover_operations printed them against ({"connection": {"name": "Main"}}). You never name a company: the tenant comes from your token.

operation*
string. As listed by discover_operations, e.g. "connections/syncs#create".
params
object. Arguments for the operation. Omit for none.

A tool's build_id is the data API's connection_id. Each source's page lists the questions ask_question answers.