APIPricingDocsBlogPartnersContact
Back to blog
Tutorial

Setting Up Webhooks Without a Static IP

A step-by-step guide using the PunchConnect API to set up real-time attendance webhooks without managing local servers or static IPs.

Engineering Team·Mar 3, 2026·8 min read

The problem with traditional setups

Most biometric attendance systems require a local server running 24/7 with a static IP address. The device connects to your server via TCP, and if your server goes down or your IP changes, you lose punch data.

This architecture was designed in the early 2000s when on-premise servers were the norm. But today, most teams run their applications in the cloud — on AWS, GCP, Azure, or platforms like Railway and Render.

PunchConnect flips this model entirely. Instead of your server listening for device connections, PunchConnect acts as the intermediary. Your devices push data to PunchConnect, and PunchConnect pushes it to your app via webhooks.

How PunchConnect webhooks work

When an employee punches in or out on a biometric device, the device sends the event to PunchConnect's protocol engine. PunchConnect processes the event, normalizes the data, and immediately sends an HTTP POST request to your configured callback URL.

Your callback URL can be any publicly accessible endpoint — a serverless function on Vercel, a Flask route on Railway, an Express endpoint on Render, or even a Zapier webhook.

PunchConnect includes automatic retries with exponential backoff. If your server is temporarily unavailable, events are queued and retried for up to 72 hours. No data is lost.

Step 1: Create a webhook endpoint

First, create a simple endpoint on your server that accepts POST requests. Here's an example using Express.js:

javascript
app.post('/api/attendance', (req, res) => {
  const { event, employee_id, timestamp, device_serial } = req.body;

  // Verify the webhook signature
  const signature = req.headers['x-punchconnect-signature'];
  if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the attendance event
  console.log(`${event}: ${employee_id} at ${timestamp}`);

  // Always respond with 200 to acknowledge receipt
  res.status(200).json({ received: true });
});

Step 2: Register the webhook

Use the PunchConnect API to register your webhook URL for the device:

python
from punchconnect import PunchConnect

client = PunchConnect(api_key="pc_live_your_api_key")

webhook = client.webhooks.create(
    device_id="dev_abc123",
    url="https://your-app.com/api/attendance",
    events=["punch_in", "punch_out"],
    secret="whsec_your_signing_secret"
)

print(f"Webhook active: {webhook.id}")

Step 3: Test the integration

PunchConnect provides a test endpoint that simulates a punch event. Use it to verify your webhook is working correctly before connecting a real device.

You can also view webhook delivery logs in your dashboard — every request, response code, and retry attempt is recorded for debugging.

bash
curl -X POST https://api.punchconnect.com/v1/webhooks/test \
  -H "Authorization: Bearer pc_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"webhook_id": "whk_abc123", "event": "punch_in"}'

Security considerations

Always verify webhook signatures. PunchConnect signs every webhook payload using HMAC-SHA256 with your webhook secret. This ensures the request genuinely came from PunchConnect and hasn't been tampered with.

Use HTTPS for your callback URL. PunchConnect will not deliver webhooks to plain HTTP endpoints in production mode.

Implement idempotency. In rare cases (network timeouts), PunchConnect may deliver the same event twice. Use the event_id field to deduplicate.

Conclusion

With PunchConnect webhooks, you don't need a static IP, a local server, or complex networking. Just deploy your app anywhere, expose an endpoint, and receive real-time attendance data.

The entire setup takes about 15 minutes — from creating your account to receiving your first live punch event.

Related articles

Setting Up Webhooks Without a Static IP | PunchConnect