Agent skill

Proxyclick Webhooks Skill

Receive and authenticate Proxyclick (now Eptura Visitor) webhooks. Use when setting up a Proxyclick webhook endpoint, checking the HTTP Basic credentials Proxyclick sends, debugging 401s, or handling visitor check-in, check-out and visit created, updated or deleted notifications.

Install this skill

npx skills add hookdeck/webhook-skills --skill proxyclick-webhooks


Proxyclick (now Eptura Visitor, visitor management) POSTs a JSON notification to a URL you choose when a visitor or visit changes. Payloads are not signed. The only security option is HTTP Basic authentication (a username and password you enter on the webhook).

When to Use This Skill

  • How do I receive Proxyclick (Eptura Visitor) webhooks?
  • How do I verify the Proxyclick Basic auth credentials on a webhook?
  • Does Proxyclick sign webhook payloads? (No: Basic auth only)
  • Why does my Proxyclick webhook endpoint return 401?
  • How do I handle visitor check-in, check-out and visit created, updated or deleted events?

Verification (core)

const crypto = require('crypto');

const sha = (s) => crypto.createHash('sha256').update(String(s)).digest();
const safeEqual = (a, b) => crypto.timingSafeEqual(sha(a), sha(b)); // equal-length digests

function verifyProxyclickRequest(headers, env = process.env) {
  const m = /^basic +([A-Za-z0-9+/]+={0,2}) *$/i.exec(headers['authorization'] || '');
  if (!m || !env.PROXYCLICK_WEBHOOK_USERNAME || !env.PROXYCLICK_WEBHOOK_PASSWORD) return false;
  const decoded = Buffer.from(m[1], 'base64').toString('utf8');
  const i = decoded.indexOf(':');                 // split on the FIRST colon
  if (i < 0) return false;
  const userOk = safeEqual(decoded.slice(0, i), env.PROXYCLICK_WEBHOOK_USERNAME);
  const passOk = safeEqual(decoded.slice(i + 1), env.PROXYCLICK_WEBHOOK_PASSWORD);
  return userOk && passOk;                        // both evaluated, no short-circuit
}

Return 401 when this fails (missing or malformed header, wrong username or password), 400 for a body that isn't a JSON object, and 200 once handled. Read the body raw (express.raw({ type: '*/*' })) and parse JSON only after the credential check.

Security notes

  • A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use an HTTPS destination URL (Proxyclick also allows plain HTTP) and rotate the credential if it leaks.
  • The Proxyclick docs don't say whether Basic credentials are sent preemptively, so the credentials must arrive on the first request. A 401 + WWW-Authenticate challenge flow won't work, and it won't work through Hookdeck either, which verifies the request as received.
  • Compare in constant time. In Python use hmac.compare_digest on bytes (encode both sides); passing str raises on non-ASCII input.

Python and Next.js equivalents are in references/verification.md.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Webhook Triggers

Proxyclick's docs name six trigger events, only as labels in the webhook settings UI. They document no event-type field in the payload, and the attribute reference shows API objects rather than a webhook body, so the examples dispatch on nothing. Their handlers use a clearly labelled illustrative body.

Trigger (UI label)Fires when
Visitor on-siteA visitor is on site
Visitor check-inA visitor checks in
Visitor check-outA visitor checks out
Visit createdA visit is created
Visit updatedA visit is updated
Visit deletedA visit is deleted

Proxyclick only guarantees backward compatibility for attributes in its public documentation. Log a real delivery before you rely on any key.

Environment Variables

PROXYCLICK_WEBHOOK_USERNAME=proxyclick
PROXYCLICK_WEBHOOK_PASSWORD=replace-with-a-long-random-password

Local Development

npx hookdeck-cli listen 3000 proxyclick --path /webhooks/proxyclick

No account required. Paste the printed URL into the webhook's destination URL in Proxyclick, and enter the same username and password there.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 5, 2026

View on GitHub →