Hey there, fellow JavaScript enthusiast! Ready to supercharge your Harvest integration with some webhook magic? Let's dive right in and get those real-time updates flowing!
Webhooks are like the cool kids of the API world – they don't wait around for you to ask for updates, they proactively ping you when something interesting happens. For Harvest, this means instant notifications about new time entries, invoices, and more. If you're building a user-facing integration, webhooks are your best friend for keeping everything in sync without constantly polling the API.
Before we jump into the code, make sure you've got:
Got all that? Great! Let's roll up our sleeves and get coding.
First things first, we need somewhere for Harvest to send those juicy webhook payloads. Let's whip up a quick Express server:
const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; app.use(express.json()); app.post('/webhooks/harvest', (req, res) => { console.log('Received webhook:', req.body); res.sendStatus(200); }); app.listen(PORT, () => console.log(`Webhook server running on port ${PORT}`));
Simple, right? This sets up a basic endpoint at /webhooks/harvest
that'll log incoming webhooks and send a 200 OK response.
Now that we've got our endpoint, let's tell Harvest about it. We'll use the Harvest API to register our webhook:
const axios = require('axios'); const HARVEST_ACCOUNT_ID = 'your_account_id'; const HARVEST_ACCESS_TOKEN = 'your_access_token'; async function registerWebhook() { try { const response = await axios.post( 'https://api.harvestapp.com/v2/webhooks', { event_type: 'timeentry.created', url: 'https://your-server.com/webhooks/harvest' }, { headers: { 'Harvest-Account-ID': HARVEST_ACCOUNT_ID, 'Authorization': `Bearer ${HARVEST_ACCESS_TOKEN}`, 'Content-Type': 'application/json' } } ); console.log('Webhook registered:', response.data); } catch (error) { console.error('Error registering webhook:', error.response.data); } } registerWebhook();
Make sure to replace 'your_account_id'
, 'your_access_token'
, and 'https://your-server.com/webhooks/harvest'
with your actual details.
When those webhooks start rolling in, you'll want to do something useful with them. Let's expand our endpoint to handle different event types:
app.post('/webhooks/harvest', (req, res) => { const { event_type, payload } = req.body; switch (event_type) { case 'timeentry.created': handleNewTimeEntry(payload); break; case 'invoice.paid': handlePaidInvoice(payload); break; // Add more cases as needed default: console.log(`Unhandled event type: ${event_type}`); } res.sendStatus(200); }); function handleNewTimeEntry(payload) { console.log('New time entry:', payload); // Do something cool with the new time entry } function handlePaidInvoice(payload) { console.log('Invoice paid:', payload); // Maybe update your own database or notify the user }
Webhooks can fail for various reasons, so it's crucial to implement proper error handling and retries. Here's a simple example:
app.post('/webhooks/harvest', async (req, res) => { try { await processWebhook(req.body); res.sendStatus(200); } catch (error) { console.error('Error processing webhook:', error); res.sendStatus(500); } }); async function processWebhook(data, retries = 3) { try { // Process the webhook data // ... } catch (error) { if (retries > 0) { console.log(`Retrying... (${retries} attempts left)`); await new Promise(resolve => setTimeout(resolve, 1000)); return processWebhook(data, retries - 1); } throw error; } }
This setup will retry processing the webhook up to 3 times before giving up.
Harvest provides a handy webhook tester in their developer tools. But for local testing, you can simulate webhook events like this:
// test-webhook.js const axios = require('axios'); async function testWebhook() { try { const response = await axios.post('http://localhost:3000/webhooks/harvest', { event_type: 'timeentry.created', payload: { id: 123456, user_id: 789, hours: 2.5, notes: 'Test time entry' } }); console.log('Test webhook sent:', response.status); } catch (error) { console.error('Error sending test webhook:', error.message); } } testWebhook();
Run this script to send a test webhook to your local server.
Remember, with great power comes great responsibility. Keep these security tips in mind:
And there you have it! You're now equipped to implement webhooks in your Harvest integration like a pro. Remember, this is just scratching the surface – there's a whole world of possibilities when it comes to real-time data syncing with Harvest.
Keep experimenting, and don't hesitate to dive into Harvest's API docs for more advanced features. Happy coding, and may your integrations be ever responsive!