Every time someone clicks a deep link, opens your app, completes a referral, or converts on a campaign, your deep linking platform records an event. The question is: how does your system find out about it?
There are two fundamental approaches. You can poll the platform's REST API at regular intervals, asking "has anything happened since I last checked?" Or you can register a webhook and let the platform push events to your server the moment they occur.
Both approaches work. Neither is universally better. The right choice depends on your latency requirements, infrastructure constraints, engineering resources, and the specific workflows you are building. This article breaks down the tradeoffs, shows code examples for both, and explains when a hybrid approach makes the most sense.
For a deeper look at webhook architecture and integration patterns, see our pillar post on webhooks and integrations for deep linking.
The webhooks page with create form, webhook list, and delivery log.
How Polling Works
Polling is the simpler of the two approaches. Your server sends HTTP GET requests to the Tolinku REST API on a schedule, fetching events that have occurred since the last request. You process the results, store a cursor or timestamp, and repeat.
The pattern is straightforward and follows the standard HTTP request-response model. Here is a basic implementation using the Tolinku API:
// Poll the Tolinku API for new events every 60 seconds
const API_BASE = "https://api.tolinku.com/v1";
const API_KEY = "tolk_sec_your_secret_key";
let lastTimestamp = new Date().toISOString();
async function pollEvents() {
const response = await fetch(
`${API_BASE}/events?since=${lastTimestamp}&limit=100`,
{
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
}
);
const { data: events } = await response.json();
for (const event of events) {
await processEvent(event);
lastTimestamp = event.timestamp;
}
}
// Run every 60 seconds
setInterval(pollEvents, 60_000);
This works reliably. You control the schedule, you control the retry logic, and you do not need to expose a public endpoint. But it comes with inherent limitations.
How Webhooks Work
With webhooks, the data flow reverses. Instead of your server asking for events, Tolinku pushes events to a URL you have registered. When a link.clicked, deferred_link.claimed, install.tracked, referral.created, or referral.completed event fires, Tolinku sends an HTTP POST to your endpoint with the event payload.
Each delivery includes an X-Webhook-Signature header (HMAC-SHA256) so your server can verify the request is authentic. The payload follows a consistent envelope:
{
"event": "link.clicked",
"timestamp": "2026-05-19T10:24:33.112Z",
"data": {
"prefix": "product",
"token": "42",
"hostname": "links.example.com",
"ip": "203.0.113.42",
"platform": "ios",
"device_type": "mobile",
"campaign": "summer-launch"
}
}
Here is a minimal webhook receiver in Express:
import express from "express";
import crypto from "crypto";
const app = express();
app.use("/webhooks", express.raw({ type: "application/json" }));
const WEBHOOK_SECRET = process.env.TOLINKU_WEBHOOK_SECRET; // whsec_...
function verifySignature(rawBody, signature) {
const expected = crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");
const sig = Buffer.from(signature, "hex");
const exp = Buffer.from(expected, "hex");
if (sig.length !== exp.length) return false;
return crypto.timingSafeEqual(sig, exp);
}
app.post("/webhooks/tolinku", (req, res) => {
const signature = req.headers["x-webhook-signature"];
if (!signature || !verifySignature(req.body, signature)) {
return res.status(401).json({ error: "Invalid signature" });
}
const { event, timestamp, data } = JSON.parse(req.body.toString());
// Process the event asynchronously
processEvent({ event, timestamp, data });
// Respond quickly to acknowledge receipt
res.status(200).json({ received: true });
});
app.listen(3000);
For a step-by-step walkthrough of configuring webhook endpoints in Tolinku, see the webhook setup guide.
The Tradeoffs: A Side-by-Side Comparison
The choice between webhooks and polling touches several dimensions. Here is how they compare:
| Factor | Polling | Webhooks |
|---|---|---|
| Latency | Seconds to minutes (depends on interval) | Near-instant (sub-second) |
| Resource usage | Wastes bandwidth on empty responses | Only transmits when events occur |
| Infrastructure | No public endpoint needed | Requires a publicly reachable HTTPS endpoint |
| Reliability | You control retries entirely | Depends on the provider's retry policy |
| Ordering | Events arrive in order (sorted by cursor) | Events may arrive out of order |
| Complexity | Simple to implement | Requires signature verification, idempotency |
| Rate limits | Consumes API quota on every request | Does not consume API quota |
| Discoverability | Easy to debug (just call the API) | Harder to inspect (need logging) |
| Backfill | Natural; just query a wider time range | Requires a separate API call for missed events |
Latency
This is usually the deciding factor. If you need to react to deep link events in real time (triggering a push notification when a referral completes, updating a live dashboard as clicks come in, or syncing conversion data to your ad platform immediately), webhooks are the clear winner. A polling interval of 60 seconds means your average latency is 30 seconds. An interval of 5 minutes means an average of 2.5 minutes. Webhooks deliver in milliseconds.
For batch analytics, daily reports, or workflows where a few minutes of delay are acceptable, polling works just fine.
Resource Usage
Every polling request that returns zero new events is a wasted round trip. If your deep links generate 50 events per day but you poll every minute, you are making 1,440 API requests and getting data back on roughly 50 of them. That is a 97% waste rate.
Webhooks eliminate this entirely. Your server only receives traffic when something actually happens. For high-volume Appspaces processing thousands of events per day, this difference is less dramatic. But for lower-volume use cases, polling is disproportionately expensive in terms of API quota and network overhead.
The Tolinku REST API enforces rate limits per Appspace, so aggressive polling intervals can consume quota that your application needs for other operations.
Reliability
Polling has an underappreciated reliability advantage. If your server goes down for an hour, you miss nothing. When it comes back online, you simply poll for all events since your last checkpoint. The data sits in the API, waiting.
Webhooks require more care. If your endpoint is unreachable when an event fires, the delivery fails. Tolinku mitigates this with automatic retries using exponential backoff, which means transient outages are handled gracefully. But extended downtime could exhaust the retry window.
The solution is to build your webhook receiver to be idempotent. Use the event id field to deduplicate, so processing the same event twice produces the same result. This protects you against duplicate deliveries, which can happen during retries.
Complexity
Polling is genuinely simpler. You need an HTTP client, a timer, and a place to store your cursor. No public endpoints, no signature verification, no idempotency logic.
Webhooks require more infrastructure. You need a publicly accessible HTTPS endpoint, TLS certificates, signature verification to prevent spoofed requests, idempotency keys, and a queue or background worker if processing takes more than a few seconds. You should respond to webhook deliveries with a 200 status code quickly; any heavy processing should happen asynchronously.
That said, the complexity is front-loaded. Once your webhook receiver is built and tested, it tends to be lower maintenance than a polling system that needs careful tuning of intervals and error handling.
When to Use Polling
Polling is the right choice when:
- You need to backfill historical data or run batch analytics
- Your server is behind a firewall or NAT without a public endpoint
- You are building a prototype or internal tool where latency does not matter
- You want full control over when and how often you fetch data
- You are integrating from a serverless function that runs on a schedule (a cron job or scheduled Lambda)
When to Use Webhooks
Webhooks are the right choice when:
- You need real-time reactions to deep link events
- You are triggering automated workflows (email sequences, Slack alerts, CRM updates)
- You want to minimize API quota usage
- You are building a live analytics dashboard
- You are processing high event volumes where polling latency would compound
The Hybrid Approach
In practice, the best systems use both. Webhooks handle the real-time path: your server gets notified instantly when events occur, and it processes them as they arrive. Polling serves as a safety net: a periodic sweep that catches any events the webhook pipeline might have missed.
Here is what a hybrid architecture looks like:
// Primary path: webhook receiver for real-time events
app.post("/webhooks/tolinku", (req, res) => {
const signature = req.headers["x-webhook-signature"];
if (!verifySignature(req.body, signature)) {
return res.status(401).end();
}
// Store event with idempotency check
const { id } = req.body;
if (!alreadyProcessed(id)) {
processEvent(req.body);
markProcessed(id);
}
res.status(200).json({ received: true });
});
// Secondary path: periodic polling as a safety net
async function reconciliationPoll() {
const events = await fetchEventsSince(lastReconciliationTime);
for (const event of events) {
if (!alreadyProcessed(event.id)) {
processEvent(event);
markProcessed(event.id);
}
}
lastReconciliationTime = new Date().toISOString();
}
// Run reconciliation every 15 minutes
setInterval(reconciliationPoll, 15 * 60_000);
The idempotency check (using the event id) ensures that events processed by the webhook path are not reprocessed by the polling path. This gives you the best of both worlds: real-time delivery with guaranteed completeness.
Practical Recommendations
If you are starting from scratch, here is a decision framework:
Start with webhooks if you need real-time data and have a server with a public endpoint. The Tolinku webhook documentation covers setup, event types, and security in detail.
Start with polling if you are building an internal dashboard, running on a schedule, or working in an environment without public endpoints.
Add the second approach when your system matures. If you started with webhooks, add a reconciliation poller. If you started with polling, add a webhook receiver for time-sensitive events.
Always build idempotent event processing, regardless of which approach you use. Events can be delivered more than once (webhook retries, overlapping poll windows), and your system should handle that gracefully.
The Tolinku REST API and webhook system are designed to work together. You do not have to choose one and commit forever. Start with what fits your current needs, and layer in the other approach as your requirements evolve.
Get deep linking tips in your inbox
One email per week. No spam.