
Last updated: October 30, 2026
Two-way sync between Quire and another app requires a middle-layer server that receives webhooks from both sides and calls each API to mirror the change. Architecture: Quire ↔ Your App ↔ Other App. Four implementation steps: stand up the webhook server, register it with Quire (add as project follower), register it with the other app, then handle events using activity types from the Quire API docs. Two safety rules: tag the origin of each change to avoid infinite loops, and keep an ID mapping between Quire task IDs and the other app's item IDs. The Google Calendar Two-Way Sync app is a working example.
The calendar says the design review is on the 14th. The task board says it moved to the 18th. Both were right at some point, and now someone spends a morning finding out which one is right today.
When the same fact lives in two apps, every change gets made twice or gets made once and lost. Two-way sync fixes that by letting the apps tell each other. Quire's Open API and webhooks were built for the pattern, and the Google Calendar Two-Way Sync app is a working example of it. This post shows how to build the same thing against any other app's API.
The cost of the manual version is measurable. McKinsey's 2012 report on the social economy found that knowledge workers spend about a fifth of their week looking for internal information or tracking down colleagues, and estimated that better-connected tools could raise their productivity by 20 to 25 percent. A sync that works is a small piece of that.
Google Calendar Two-Way Sync is made for Premium and higher subscription tiers. More information can be found on our Pricing page.
| Component | Role |
|---|---|
| Quire app | Provides API credentials; registered as project follower for webhooks |
| Middle-layer server (your app) | Receives webhooks from both sides; calls each API to mirror the change |
| Other app (e.g. Google Calendar) | Source of events on its side; target of API writes |
| Webhook URL in Quire app settings | Where Quire POSTs activity events |
| ID mapping table | Maps Quire task IDs ↔ other app's item IDs |
| Origin tag on each change | Prevents infinite update loops |
A conversation between two apps. When you change a task in Quire, Quire tells the other app. When something changes in the other app, it tells Quire. Neither side has to be reminded, and the fact you read is the same in both places.

A Quire app, first. It holds the credentials your code uses to reach a Quire project through the API.
For a step-by-step guide on how to create your own app with Quire API, please visit our blog post.
Then a middle-layer app of your own, sitting between Quire and the target app. It's a translator. It takes an event from one side, works out what it means, and sends the right command to the other side. The flow is Quire ↔ Your App ↔ Other App, and the translator is the only part you have to write.
Your server is the middle layer, and its job is to receive webhook POST requests from both Quire and the other app. It needs to do three things.
Any stack works. Node.js, Python, Ruby, whatever your team already runs. The examples below use Node.js.
The one hard requirement is that the server is reachable from the internet, or the webhooks have nowhere to go.
Here's the smallest Express server that qualifies.
const express = require('express');
const app = express();
app.use(express.json());
app.listen(3000, () => {
console.log('Server is running on port 3000');
});Add a route that receives Quire's events.
app.post('/webhook', (req, res) => {
console.log('Received webhook event:', req.body);
// TODO: Handle the event and update Quire or other app via API
res.status(200).send('Event received');
});The route is /webhook, so the full URL is ${your-host}/webhook.
Paste that webhook URL into the Quire app settings. That's how Quire learns where to send event notifications.

One more step, and it's the one people forget. Register your Quire app as a follower of the project you want to sync. A follower gets notified. An app that isn't following hears nothing and looks broken.
For a step-by-step guide on how to receive notifications via Quire API, please visit our guide.
Same idea in the other direction. Add a second route for the other app's events, then configure that app to send its notifications to your endpoint. The registration steps differ by app, but the shape is the one you've already built.
Now your server hears both sides, and the sync logic goes in the middle. For each event, the handler does four things.
Here's an example using Node.js and axios.
const axios = require('axios');
app.post('/webhook', (req, res) => {
const { type } = req.body.data;
// Reference of activity types:
// https://github.com/quire-api/quire-api/blob/master/docs/activity_types.md
switch (type) {
case 0: //Quire task created
onQuireTaskCreate();
break;
case 1: //Quire task deleted
onQuireTaskDelete();
break;
}
res.status(200).send('Event received');
});
// Route for handling events from another app to Quire
app.post('/anotherwebhook', async (req, res) => {
const { isCreate, id, name, projectId } = req.body;
if (isCreate) {
// Create a task in the Quire project
await axios.post(`https://quire.io/api/task/${projectId}`, { name });
// Optionally, store the mapping between your app's id and Quire's task id
} else {
// Retrieve the corresponding Quire task id using your mapping logic
const taskOid = getTaskIdByAppEventId(id, projectId);
// Delete the task from the Quire project
await axios.delete(`https://quire.io/api/task/${taskOid}`);
}
res.status(200).send('Event processed successfully');
});This handles create and delete events from another app and mirrors them into Quire. Add error handling, and treat the ID mapping as the heart of the sync rather than an afterthought. Lose the mapping and every later update creates a duplicate.
Two rules cover the failures that bite every first implementation.
Track the origin of each change. Tag the updates your sync triggered, and ignore them when they come back as a webhook. Without the tag, Quire pushes to the other app, the other app fires a webhook back, your server pushes again, and the loop runs until someone pulls the plug.
Keep data formats consistent. A field that means one thing in Quire, like a Markdown description, may need explicit conversion before it lands as a calendar event description, a plain-text issue note, or whatever the target expects. Decide the conversion once and apply it on every hop.
A third rule, now that Quire supports it: lock the Custom Fields your sync owns, so a hand edit never fights the next sync. See how to lock a Custom Field.
The loop and the format mismatch are the famous failures. What breaks once real users touch the sync? Four quieter things.
The same event arrives twice. Webhook senders retry when they don't get a fast 200, and a slow handler can be retried mid-work. Record each event's ID when you process it, and skip any ID you've seen. Respond 200 first, then do the work, if the sender's timeout is short.
Events arrive out of order. A rename and a delete can land in the wrong sequence under load. Compare timestamps before applying a change, and never apply an older state over a newer one.
The mapping table disappears. It was in memory, the server restarted, and now nothing matches. Put the mapping in a database from day one. It's the only state the sync owns, and it's the whole sync.
A record is deleted on one side only. Decide the policy before it happens. Delete the twin, archive it, or flag it for a human, but decide, because the default (do nothing) leaves an orphan on one side that a later update will try to find.
None of these needs clever code. They need a decision written down before the first user hits the edge case, which is the kind of decision that's hard to make at 2 a.m. and easy to make now.
Start with the smallest sync that can work. One event type, one direction. Create a task in Quire, watch it appear in the other app, and confirm nothing bounces back. Then add the reverse direction, then the second event type.
Open API plus webhooks turns Quire and your other tools into one record instead of two competing ones. Build it in that order and the loop never gets a chance to start.
Related: Integrate External Tools with Quire via Quire API, Using n8n as an Example, a worked example if you'd rather start with a no-code automation tool than a custom server.
A two-way sync sits near the top of the automation ladder. For the rungs below it, see what to automate first in Quire, from recurring tasks to Zapier recipes.
A bidirectional connection where updates flow both ways: changes in Quire push to the other app, and changes there push back to Quire. The Google Calendar Two-Way Sync app is a working example.
A Quire app with API credentials, a middle-layer server reachable from the internet to receive webhooks, and logic to translate events between the two APIs. Any backend language works.
It acts as a translator between Quire and the other service, receiving webhook events, deciding what API calls to make, and maintaining the mapping between Quire task IDs and the other app's item IDs.
Track where each change originated and ignore updates triggered by your own sync process. Without this safeguard, every update ping-pongs between the two apps forever.
Premium and up. Check the current tier limits on the pricing page.