Skip to content

Webhooks

Webhooks let you receive real-time HTTP notifications when events occur in your Appspace. Configure webhook endpoints in your dashboard to get notified about link clicks, installs, deferred link claims, and referral activity.

EventTriggered when
link.clickedA user clicks a deep link
install.trackedA user is redirected to an app store
deferred_link.claimedAn SDK claims a deferred deep link after install
referral.createdA new referral code is created via the API
referral.completedA referral is marked as completed
ecommerce.purchaseA purchase event is recorded
ecommerce.refundA refund event is recorded
ecommerce.cart_abandonedA cart is detected as abandoned
ecommerce.add_to_cartA user adds an item to their cart
ecommerce.begin_checkoutA user starts the checkout process
ecommerce.add_to_wishlistA user adds an item to their wishlist
ecommerce.fraud_flaggedAn event flagged by fraud detection

Every webhook delivery sends a POST request with a JSON body:

{
"event": "link.clicked",
"timestamp": "2026-03-02T12:00:00.000Z",
"data": {
"prefix": "merchant",
"token": "abc123",
"hostname": "myapp.tolinku.com",
"ip": "203.0.113.42",
"platform": "ios",
"device_type": "mobile",
"campaign": "spring-sale"
}
}

link.clicked:

FieldDescription
prefixRoute prefix
tokenDynamic link token (if applicable)
hostnameAppspace domain
ipVisitor IP address
platformios, android, or desktop
device_typemobile or desktop
campaignUTM campaign (if present)

install.tracked:

FieldDescription
hostnameAppspace domain
ipVisitor IP address
platformios or android
device_typeDevice type
campaignUTM campaign (if present)

deferred_link.claimed:

FieldDescription
deep_link_pathThe claimed deep link path
methodtoken or signals
ipVisitor IP address

referral.created:

FieldDescription
referral_codeThe generated code
referrer_idThe referrer’s user ID
referral_urlThe full referral URL

referral.completed:

FieldDescription
referral_codeThe referral code
referrer_idThe referrer’s user ID
referred_user_idThe referred user’s ID
milestoneThe completion milestone
reward_typeReferrer reward type (e.g. credit, discount), or null
reward_valueReferrer reward value, or null
referee_reward_typeReferee reward type, or null
referee_reward_valueReferee reward value, or null

ecommerce.purchase:

FieldDescription
transaction_idUnique order identifier
user_idThe buyer’s user ID
revenueTotal revenue amount
currencyISO 4217 currency code
items_countNumber of items in the order
coupon_codeApplied coupon (if any)

ecommerce.refund:

FieldDescription
transaction_idThe refunded order identifier
user_idThe buyer’s user ID
revenueRefund amount
currencyISO 4217 currency code

ecommerce.cart_abandoned:

FieldDescription
user_idThe user who abandoned checkout
cart_idCart session identifier
checkout_timestampWhen the checkout was started
hours_since_checkoutHours elapsed since checkout began

ecommerce.fraud_flagged:

FieldDescription
event_typeThe ecommerce event type (e.g. purchase)
transaction_idOrder identifier (if applicable)
user_idThe user who triggered the event
revenueRevenue amount
ruleWhich fraud rule was triggered (bot_detection, impossible_revenue, velocity_check, currency_mismatch)
severity1 (flagged, stored but marked)

Every webhook request includes:

HeaderDescription
Content-Typeapplication/json
X-Webhook-EventThe event type (e.g. link.clicked)
X-Webhook-SignatureHMAC-SHA256 signature of the request body

Every webhook endpoint has a signing secret (prefixed whsec_). Use it to verify that webhook deliveries are authentic.

The signature is an HMAC-SHA256 hex digest of the raw request body:

HMAC-SHA256(request_body, signing_secret) = signature

Node.js:

const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
app.post('/webhooks/tolinku', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhook(req.rawBody, signature, 'whsec_your_secret');
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
const { event, data } = req.body;
// Process the event...
res.status(200).json({ ok: true });
});

Python:

import hmac
import hashlib
def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
  • Timeout: 10 seconds. If your endpoint does not respond within 10 seconds, the delivery is marked as failed.
  • Success: Any HTTP 2xx status code is considered successful.
  • Retries: Failed deliveries are retried up to 3 times with increasing delays:
AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes

After 4 total attempts (1 original + 3 retries), the delivery is marked as permanently failed.

Every delivery attempt (success or failure) is logged. You can view delivery history in the Webhooks section of your dashboard, including:

  • HTTP status code
  • Response time
  • Error message (if failed)
  • Attempt number
  • Respond quickly. Return a 200 status code as soon as you receive the payload. Process the event asynchronously if your handler needs to do significant work.
  • Handle duplicates. In rare cases, the same event may be delivered more than once. Use the timestamp and event data to deduplicate.
  • Verify signatures. Always verify the X-Webhook-Signature header before processing the payload.
  • Use HTTPS. Webhook URLs must use HTTPS in production.
PlanEndpointsDeliveries/mo
Free1500
StandardUnlimited10,000
GrowthUnlimited50,000
ScaleUnlimited200,000
EnterpriseUnlimitedUnlimited