Sync Airtable usage rows into Tabs for billing
When a new usage event lands in your Airtable tracker, find the matching customer in Tabs, log the event for billing, and stamp the row as synced.
Build a code workflow that syncs new usage events from an Airtable tracker into Tabs for billing. The trigger is a poll on Airtable, event type new_record, watching a table called Usage Events. The columns on that table are: Customer External ID (text), External ID Source (single select with values like SALESFORCE, HUBSPOT, NETSUITE), Event Type (text, matches a Tabs event type slug), Quantity (number), Event Timestamp (ISO 8601 date-time), Synced (checkbox), Tabs Event ID (text), and Sync Error (text). The workflow should only act on rows where Synced is false.
For each new row, run these steps in order:
1. Call the Tabs List Customers operation, filtered by the external ID and external ID source from the Airtable row, to resolve the Tabs customer UUID. Use the page-based pagination but we only need the first match.
2. If zero customers come back, call Airtable Update Record on the same row to set Sync Error to a clear message like "No Tabs customer found for {source} ID {externalId}" and leave Synced unchecked. Then stop for this row.
3. If a customer is found, call the Tabs Create Event operation with that customer UUID, the Event Type from the row, the Quantity from the row, and the Event Timestamp formatted as ISO 8601. Capture the returned event ID.
4. Call Airtable Update Record to set Tabs Event ID to the returned event ID, flip Synced to true, and clear the Sync Error column if it had a previous value.
Important behaviors: handle Tabs API errors by writing the error message into the Sync Error column on the Airtable row instead of throwing, so a single bad row never blocks future ones. Treat the Synced checkbox as the idempotency guard so reprocessing the same row is safe. Allow the user to configure the Airtable base ID, table name, and the exact column names at setup time so it works against their existing tracker without renaming fields.
Additional information
What does this prompt do?
- Watches your Airtable Usage Events table and fires the moment a new row is added.
- Looks up the matching customer in Tabs using the external ID on the row, whether it came from Salesforce, HubSpot, or NetSuite.
- Records the usage event in Tabs with the event type, quantity, and timestamp from your row.
- Writes the new Tabs event ID and a Synced flag back to Airtable so you have a clean audit trail and never double-bill on retries.
- If no matching customer is found, writes a clear error message back to the row instead of silently failing.
What do I need to use this?
- An Airtable base with a Usage Events table that includes a customer external ID, event type, quantity, timestamp, a Synced checkbox, a Tabs Event ID column, and a Sync Error column.
- A Tabs account and an API key from the Developers section.
- Your Airtable customer external IDs should match the IDs Tabs already has on file from Salesforce, HubSpot, or NetSuite.
How can I customize it?
- Point at a different Airtable base, table, or set of column names if your usage tracker is laid out differently.
- Switch which external ID source you match on if your customers live in NetSuite, HubSpot, Salesforce, or somewhere else.
- Change the error column or add a Slack ping when a customer cannot be resolved so the right person sees it.
Frequently asked questions
Do I have to manually run this every time my team adds a usage row?
What happens if Tabs cannot find a matching customer?
Will it double-bill if the same row is processed twice?
Can I use this with Salesforce, HubSpot, or NetSuite IDs?
Is this a good fit if my team already has a metering pipeline?
Stop manually copying usage rows into your billing system.
Connect Airtable and Tabs once, and Geni keeps every new usage event flowing into billing the moment it lands.