How it works
By subscribing to receive “ENTITY_UPDATE” webhooks, your server can asynchronously fetch updated data at the exact moment it becomes available. When that new data is available, the Tight API will make a POST call to a URL of your choosing with the data needed for your server to update appropriately. This approach ensures your users always have up-to-date data while removing unnecessary polls/refreshes from your server, saving you valuable resources. By subscribing to receive “LIFECYCLE” webhooks, you can trigger timely lifecycle notifications (e.g. push notifications, emails, and/or other alerts) based on timely user actions. For example, if a user’s client views their invoice, the Tight API will make a POST call to a URL of your choosing with the data needed for your server to alert your user that their client viewed the invoice.Subscribing to receive webhooks
Tight’s API team is here to help! Simply email api@tight.com with the subject line “Subscribe to Webhooks”, and provide the following info: a. Your APIclient_Idb. Webhook URL for the Sandbox environment
c. Webhook URL for the Production environment Our API team will respond back within 5 business days with your Sandbox
webhook_secret and your Production webhook_secret and will fire off sample webhooks to your Sandbox Webhook URL, for your team to develop/test with.
ENTITY_UPDATE
An “ENTITY_UPDATE” webhook will contain a JSON body like the following:entities and recommended actions on how to update each given entity are listed below:
| Webhook Type | Entity | Recommended action |
|---|---|---|
| ENTITY_UPDATE | attachment | GET /attachments |
| ENTITY_UPDATE | bankAccount | GET /bankAccounts |
| ENTITY_UPDATE | bankTransfer | GET /bankTransfers |
| ENTITY_UPDATE | business | GET /businesses |
| ENTITY_UPDATE | client | GET /clients |
| ENTITY_UPDATE | expense | GET /expenses |
| ENTITY_UPDATE | expenseCategory | GET /expenses/categories |
| ENTITY_UPDATE | expenseRule | GET /expenses/rules |
| ENTITY_UPDATE | glAccount | GET /glAccounts |
| ENTITY_UPDATE | glEntry | GET /glEntries |
| ENTITY_UPDATE | integration | GET /integrations |
| ENTITY_UPDATE | invoice | GET /invoices |
| ENTITY_UPDATE | invoiceSetup | GET /invoiceSetup |
| ENTITY_UPDATE | manualJournalEntry | GET /manualJournalEntries |
| ENTITY_UPDATE | payment | GET /payments |
| ENTITY_UPDATE | personalExpenseCategory | GET /expenses/personalCategories |
| ENTITY_UPDATE | revenue | GET /revenues |
| ENTITY_UPDATE | revenueRule | GET /revenueRules |
| ENTITY_UPDATE | task | GET /tasks |
| ENTITY_UPDATE | taxEstimates | GET /taxEstimates |
| ENTITY_UPDATE | taxPayment | GET /taxPayments |
| ENTITY_UPDATE | time | GET /times |
| ENTITY_UPDATE | userTaxSetup | GET /userTaxSetup |
| ENTITY_UPDATE | vendor | GET /vendors |
LIFECYCLE
A “LIFECYCLE” webhook will contain a JSON body like the following:👍 Additional use cases The Lifecycle Events can be used in varying ways depending on your product’s use case. For example, if your product manages corporate/employee spend, it may benefit your user experience to make thetransactionCreatedevent trigger a push notification prompting the user to add a receipt image. TheeventDataincluded with thetransactionCreatedevent contains the information necessary to route the user to the exact transaction that requires a receipt.
Webhook Verification
Tight signs every webhook, so that you have the option to verify the webhooks you receive. This helps you protect against a bad actor flooding your server with fake webhooks. Verifying WebhooksTight follows the JSON Web Token (JWT) standard and includes its JWTs in the
Tight-Verification HTTP header of the webhook.
To verify a Tight JWT, follow these steps:
-
Extract the
Tight-VerificationHTTP header from the Tight webhook - Select a JWT library of your choice
-
Pass in HMAC-SHA256 as the signing algorithm to your selected JWT library and then use the library to verify the value of the
Tight-Verificationheader against your webhook_secret, obtained in Subscribing to receive webhooks
Node.js
- Ensure that the webhook is not expired. Verify that the difference between the
iatfield of the payload and the currentNumericDatetimestamp is within your tolerance. Tight recommends a default tolerance of 5 minutes.
Node.js
- Ensure that the webhook was not modified by anyone other than Tight. Verify that the
request_body_sha256field of the payload is equal to the SHA-256 hash of the webhook’s request body.
Node.js