API & Webhook Integration

Last updated March 2026

Porter provides a REST API and webhook system so you can integrate visitor management into your existing tools and workflows. Use the API to query visitor data programmatically and webhooks to receive real-time event notifications.

Getting Your API Key

To use the Porter API, you first need to generate an API key from your dashboard.

  • Navigate to Settings > API
  • Click "Generate API Key"
  • Copy the key immediately — it will only be shown once
  • Store the key securely (e.g., in a secrets manager or environment variable)
API settings page with Generate API Key button

You can revoke an API key at any time and generate a new one. Revoking a key immediately invalidates it — any integration using that key will stop working.

Authentication

All API requests must be authenticated using your API key and sent over HTTPS.

API Key Header

Include your API key in the X-API-Key header with every request:

X-API-Key: your_api_key_here

Rate Limiting

  • Rate limit: 100 requests per minute per API key
  • Exceeding the limit returns a 429 Too Many Requests response
  • The response includes a Retry-After header indicating when you can retry
  • All requests must use HTTPS — HTTP requests are rejected

Available Endpoints

The Porter API provides the following endpoints for interacting with your visitor management data.

MethodEndpointDescription
GET/api/v1/visitorsList all visitors with pagination and filters
GET/api/v1/visitors/:idGet a specific visitor record by ID
POST/api/v1/visitors/pre-registerPre-register a visitor
GET/api/v1/locationsList all locations
GET/api/v1/contractorsList all contractors
API endpoint reference table in the documentation

Webhook Setup

Webhooks let Porter push real-time event notifications to your server. Instead of polling the API, you receive data the moment something happens.

Creating a Webhook

  • Navigate to Settings > Webhooks
  • Click "Add Webhook"
  • Enter the URL where you want to receive webhook events
  • Select the events you want to subscribe to
  • Click "Save"
Add Webhook form with URL input and event selection

Available Events

  • visitor.checked_in — fired when a visitor checks in
  • visitor.checked_out — fired when a visitor checks out
  • visitor.pre_registered — fired when a visitor is pre-registered
  • contractor.approved — fired when a contractor is approved
  • evacuation.activated — fired when evacuation mode is activated

Testing Webhooks

After creating a webhook, click the "Test" button to send a sample payload to your URL. This lets you verify your endpoint is working correctly before relying on it in production.

Webhook Signatures

Every webhook request includes a signature so you can verify it genuinely came from Porter and hasn't been tampered with.

How Signatures Work

  • Each webhook request includes an X-Porter-Signature header
  • The signature is an HMAC-SHA256 hash of the request body
  • The hash is computed using your webhook secret (found in Settings > Webhooks)
  • Always verify signatures in production to prevent spoofed requests
Webhook signature verification flow diagram

Code Examples

Here are practical examples showing how to interact with the Porter API and verify webhook signatures.

cURL — List Visitors

curl -X GET https://yourapp.portervisitors.com/api/v1/visitors \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json"

JavaScript — List Visitors

const response = await fetch("https://yourapp.portervisitors.com/api/v1/visitors", {
  method: "GET",
  headers: {
    "X-API-Key": "your_api_key_here",
    "Content-Type": "application/json",
  },
});

const data = await response.json();
console.log(data.visitors);

Python — List Visitors

import requests

response = requests.get(
    "https://yourapp.portervisitors.com/api/v1/visitors",
    headers={
        "X-API-Key": "your_api_key_here",
        "Content-Type": "application/json",
    },
)

data = response.json()
print(data["visitors"])

JavaScript — Verify Webhook Signature

import crypto from "crypto";

function verifyWebhookSignature(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:
const isValid = verifyWebhookSignature(
  rawBody,
  req.headers["x-porter-signature"],
  process.env.PORTER_WEBHOOK_SECRET
);

if (!isValid) {
  return res.status(401).json({ error: "Invalid signature" });
}

Python — Verify Webhook Signature

import hmac
import hashlib

def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        body,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

# In your webhook handler:
is_valid = verify_webhook_signature(
    request.body,
    request.headers.get("X-Porter-Signature"),
    os.environ["PORTER_WEBHOOK_SECRET"],
)

if not is_valid:
    return JsonResponse({"error": "Invalid signature"}, status=401)
Was this article helpful?