Gareth Wilson Gareth Wilson

Guide to Zift Webhooks: Features and Best Practices

Published


Zift webhooks (Zift calls them notifications) notify your application about billing and processing activity: a subscription is created, a payment is processed, a chargeback or return occurs. If you're building on Zift, notifications are how you react to these events without polling.

This guide covers how Zift notifications work, the acknowledgement handshake, why there's no signature to verify, and the best practices for production.

What are Zift webhooks?

Zift notifications are HTTPS POSTs carrying a JSON body. There is no signing secret, no signature header, and no Basic or token auth on delivery. This is confirmed from the full rendered docs, not an absence of documentation. Authenticity relies only on HTTPS and endpoint-URL secrecy, so treat Zift's source as unverified passthrough and add your own controls. To acknowledge each delivery, your endpoint must return JSON {"notificationId": <id>}.

Zift webhook features

FeatureDetails
DeliveryHTTPS POST, JSON body
VerificationNone documented (no secret, no signature header, no token auth)
AcknowledgementReturn JSON {"notificationId": <id>} (int or string)
RetriesOn non-ack: +5min, +15min, +60min, +24h, then status "Failed" (no further redelivery)
PayloadnotificationId, eventCode (e.g. billing.subscription-created), eventDate (epoch-ms), dataType, data{}
SetupOut-of-band: email Zift support your HTTPS endpoint and events (integrator/reseller level)
SDKNone

Common events

Zift has a naming quirk: the trigger names you subscribe to use tildes, while the eventCode in the payload uses dots. Map between them:

Trigger namePayload eventCode (example)
subscription~createbilling.subscription-created
payment-option~createbilling payment-option created
allocation~createbilling allocation created
payment~processbilling payment processed
chargebackprocessing chargeback
returnprocessing return
reversalprocessing reversal
NOCprocessing NOC

Subscribe with the tilde trigger names, but branch your handler on the dotted eventCode in the payload.

Setting up Zift webhooks

Setup is out-of-band: email Zift support your HTTPS endpoint and the events you want. Notifications are configured at the integrator or reseller level, not per merchant. There's no self-serve dashboard and no secret to store, so keep your endpoint URL secret and consider IP allowlisting.

Securing Zift webhooks

There's no signature to verify, so security rests on transport and process. Serve the endpoint over HTTPS only, keep the URL secret, and consider allowlisting Zift's source IPs. Acknowledge every delivery by echoing its notificationId, otherwise Zift retries and eventually marks the notification "Failed".

app.post("/webhook", express.json(), (req, res) => {
  // No signature to verify. Authenticity rests on HTTPS + URL secrecy (+ optional IP allowlist).
  const { notificationId, eventCode } = req.body;

  // Acknowledge by echoing the notificationId, or Zift will retry and then mark it Failed
  res.json({ notificationId });

  // Branch on the dotted eventCode (payload), not the tilde trigger name (subscription)
  processQueue.add({ eventCode, body: req.body }); // async, dedupe on notificationId
});

The same handler in Python (FastAPI):

from fastapi import FastAPI, Request

app = FastAPI()


@app.post("/webhook")
async def zift_webhook(request: Request):
    body = await request.json()
    # No signature to verify; acknowledge by echoing notificationId
    enqueue(body)  # async; branch on body["eventCode"], dedupe on notificationId
    return {"notificationId": body["notificationId"]}

Zift webhook limitations and pain points

There's no signature to verify

The Problem: Zift delivers with no signing secret, signature header, or token auth. You can't cryptographically prove a request came from Zift, so a leaked URL is enough for anyone to post events.

Why It Happens: Zift's notification delivery relies on HTTPS and URL secrecy.

Workarounds:

  • Serve HTTPS only, keep the endpoint URL secret, allowlist Zift's source IPs, and validate the payload shape before acting.

How Hookdeck Can Help: Hookdeck can front the endpoint, apply IP allowlisting and its own controls, and give you a managed layer in front of an unverifiable source.

Acknowledgement must echo the notificationId

The Problem: A plain 200 isn't enough. Zift treats a delivery as acknowledged only when you return {"notificationId": <id>}. Miss it and Zift retries, then marks the notification "Failed".

Why It Happens: Zift confirms delivery by matching the echoed id.

Workarounds:

  • Return {"notificationId": <id>} with the exact id from the request.

How Hookdeck Can Help: Hookdeck can manage the acknowledgement contract at the edge, so a missed echo doesn't fail deliveries.

Trigger names and eventCode differ

The Problem: You subscribe to tilde names like subscription~create, but the payload carries dotted codes like billing.subscription-created. Branching on the trigger name instead of the eventCode never matches.

Why It Happens: Zift uses different naming for subscription triggers and payload codes.

Workarounds:

  • Subscribe with tilde names, but branch handlers on the dotted eventCode.

How Hookdeck Can Help: Hookdeck's filters route on the eventCode you actually receive, so the naming mismatch doesn't leak into your app.

Retries end in a terminal Failed state

The Problem: On non-ack, Zift retries at +5m, +15m, +60m, +24h, then marks the notification "Failed" with no further redelivery. A prolonged outage means permanently lost events.

Why It Happens: Zift's retry schedule is finite.

Workarounds:

  • Acknowledge fast and reliably, and reconcile via the API for anything that reached "Failed".

How Hookdeck Can Help: Hookdeck durably queues events and retries on its own schedule, so a downstream outage doesn't drop events at Zift's terminal state.

Best practices

Treat the source as unverified passthrough

There's no signature, so rely on HTTPS, URL secrecy, IP allowlisting, and payload-shape validation.

Echo the notificationId to acknowledge

Return {"notificationId": <id>} with the exact id, or the delivery isn't acknowledged.

Branch on the dotted eventCode

Subscribe with tilde trigger names, but handle events by the payload eventCode.

Return the ack fast and process asynchronously

Acknowledge quickly and defer work to a queue; dedupe on notificationId. See why to process webhooks asynchronously.

Make Zift webhooks production-ready

Hookdeck fronts your endpoint, manages the ack, deduplicates, and durably queues every notification

Conclusion

Zift notifications have no documented signature verification, so authenticity rests on HTTPS and URL secrecy, treat the source as unverified passthrough. Acknowledge each delivery by echoing {"notificationId": <id>}, or Zift retries at +5m/+15m/+60m/+24h then marks it "Failed". Subscribe with tilde trigger names, branch on the dotted eventCode, and dedupe on notificationId.

Hookdeck fronts your endpoint, manages the acknowledgement, deduplicates, and durably queues every notification at the edge, so your app processes a reliable, unique stream.

Get started with Hookdeck for free and handle Zift webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.