This is an info Alert.
SnapKey Logo
  • Løsninger
      • Løsninger
      • SnapKey Residential
      • SnapKey Utility
      • SnapKey Public
      • SnapKey Logistics
      • SnapKey Sensors
      • Gæste Check-in
      • Genaktiverbare nøgler
      • Vognudlejning
  • Brancher
      • Brancher
      • Forsyningsvirksomheder
      • Beboelsesejendomme
      • Kontorbygninger og Coworking Spaces
      • Logistik
      • Feriehuse
      • Offentlige toiletter
      • Byggepladser
      • Ubemandede butikker
      • Midlertidige opbevaringsskabe
      • Virtuel nøgleboks
  • Ressourcer
      • Ressourcer
      • Viden
      • Videoer
      • API-dokumentation
      • Tillid & sikkerhed
      • Systemstatus
  • Partnere
  • Virksomhed
      • Virksomhed
      • Om os
      • Hvorfor SnapKey
      • Kontakt
auth.sign_inBook en demo

API og Webhook-integrationer – Automatiser din adgangskontrol med SnapKey

Komplet teknisk guide til SnapKey's REST API, webhooks, MQTT og integrationer. Perfekt til udviklere der vil automatisere adgangskontrol og integrere med eksisterende systemer.
17. november 2025
8 min
API og Webhook-integrationer – Automatiser din adgangskontrol med SnapKey

SnapKey tilbyder et fuldt RESTful API og real-time webhooks for at integrere adgangskontrol med jeres eksisterende systemer. Denne guide er skrevet til udviklere og IT-arkitekter der vil automatisere adgangsstyring.


Integration-muligheder

REST API

Fuldt CRUD API til nøgler, brugere, låse, logs og konfiguration

Webhooks

Real-time push-notifikationer når events sker

MQTT

IoT-protocol til real-time kommunikation med devices

GraphQL

Fleksibel query-språk for complex data fetching

OAuth 2.0

Moderne autentifikation med scoped access tokens

Bulk operations

Batch-import/export via CSV, JSON og XML


REST API Overview

Authentication

# Obtain access token
curl -X POST https://api.snapkey.dk/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "your_client_id",
    "client_secret": "your_client_secret",
    "grant_type": "client_credentials"
  }'

# Response
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Core Endpoints

Base URL: https://api.snapkey.dk/v1

Authentication:
├─ POST   /auth/token          # Get access token
└─ POST   /auth/refresh        # Refresh token

Users:
├─ GET    /users               # List users
├─ GET    /users/{id}          # Get user details
├─ POST   /users               # Create user
├─ PATCH  /users/{id}          # Update user
└─ DELETE /users/{id}          # Delete user

Keys:
├─ GET    /keys                # List keys
├─ GET    /keys/{id}           # Get key details
├─ POST   /keys                # Issue new key
├─ PATCH  /keys/{id}           # Update key permissions
└─ DELETE /keys/{id}           # Revoke key

Locks:
├─ GET    /locks               # List all locks
├─ GET    /locks/{id}          # Get lock details
├─ GET    /locks/{id}/status   # Get real-time status
└─ POST   /locks/{id}/unlock   # Remote unlock (emergency)

Access Logs:
├─ GET    /logs/access         # Query access logs
├─ GET    /logs/access/{id}    # Get specific event
└─ GET    /logs/access/export  # Export logs (CSV/JSON)

Organizations:
├─ GET    /organizations       # List organizations
└─ GET    /organizations/{id}  # Get org details

Webhooks:
├─ GET    /webhooks            # List webhook subscriptions
├─ POST   /webhooks            # Create webhook
├─ PATCH  /webhooks/{id}       # Update webhook
└─ DELETE /webhooks/{id}       # Delete webhook

Common Use Cases

Use Case 1: Automatic onboarding

Scenario: New employee in HR system → automatic key provisioning

import requests

class SnapKeyIntegration:
    def __init__(self, api_key):
        self.base_url = "https://api.snapkey.dk/v1"
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }

    def onboard_employee(self, employee_data):
        # 1. Create user in SnapKey
        user_payload = {
            "email": employee_data["email"],
            "first_name": employee_data["first_name"],
            "last_name": employee_data["last_name"],
            "department": employee_data["department"],
            "role": employee_data["role"]
        }

        user_response = requests.post(
            f"{self.base_url}/users",
            json=user_payload,
            headers=self.headers
        )
        user_id = user_response.json()["id"]

        # 2. Issue keys based on department
        locks = self.get_locks_for_department(employee_data["department"])

        key_payload = {
            "user_id": user_id,
            "locks": locks,
            "valid_from": employee_data["start_date"],
            "valid_until": None,  # Permanent until terminated
            "time_restrictions": {
                "monday": {"start": "07:00", "end": "19:00"},
                "tuesday": {"start": "07:00", "end": "19:00"},
                "wednesday": {"start": "07:00", "end": "19:00"},
                "thursday": {"start": "07:00", "end": "19:00"},
                "friday": {"start": "07:00", "end": "19:00"}
            }
        }

        key_response = requests.post(
            f"{self.base_url}/keys",
            json=key_payload,
            headers=self.headers
        )

        # 3. Send welcome email with QR code
        self.send_welcome_email(user_id, key_response.json()["qr_code_url"])

        return {"user_id": user_id, "key_id": key_response.json()["id"]}

# Usage
snapkey = SnapKeyIntegration(api_key="your_api_key")

new_employee = {
    "email": "jens@firma.dk",
    "first_name": "Jens",
    "last_name": "Jensen",
    "department": "IT",
    "role": "Developer",
    "start_date": "2025-12-01"
}

result = snapkey.onboard_employee(new_employee)

Use Case 2: Temporary contractor access

// Node.js example: Issue temporary key to contractor

const axios = require('axios');

async function grantContractorAccess(contractor, project) {
  const snapkey = axios.create({
    baseURL: 'https://api.snapkey.dk/v1',
    headers: {
      'Authorization': `Bearer ${process.env.SNAPKEY_API_KEY}`,
      'Content-Type': 'application/json'
    }
  });

  try {
    // 1. Create temporary user
    const userResponse = await snapkey.post('/users', {
      email: contractor.email,
      first_name: contractor.first_name,
      last_name: contractor.last_name,
      company: contractor.company,
      tags: ['contractor', 'temporary']
    });

    const userId = userResponse.data.id;

    // 2. Issue time-limited key
    const keyResponse = await snapkey.post('/keys', {
      user_id: userId,
      locks: project.authorized_locks,
      valid_from: project.start_date,
      valid_until: project.end_date,
      time_restrictions: {
        // Only during business hours
        monday: { start: '08:00', end: '17:00' },
        tuesday: { start: '08:00', end: '17:00' },
        wednesday: { start: '08:00', end: '17:00' },
        thursday: { start: '08:00', end: '17:00' },
        friday: { start: '08:00', end: '17:00' }
      },
      max_uses: 50  // Maximum 50 uses
    });

    // 3. Send SMS with access instructions
    await sendSMS(contractor.phone, {
      message: `Din adgang til ${project.name} er nu aktiv.
                Scan QR-koden: ${keyResponse.data.qr_code_url}`,
      qr_code_url: keyResponse.data.qr_code_url
    });

    // 4. Schedule automatic cleanup
    scheduleKeyRevocation(keyResponse.data.id, project.end_date);

    return {
      user_id: userId,
      key_id: keyResponse.data.id,
      expires: project.end_date
    };

  } catch (error) {
    console.error('Failed to grant contractor access:', error.response.data);
    throw error;
  }
}

// Usage
grantContractorAccess(
  {
    email: 'contractor@firma.dk',
    first_name: 'Peter',
    last_name: 'Pedersen',
    company: 'Pedersen Bygning ApS',
    phone: '+4512345678'
  },
  {
    name: 'Renovering Bygning A',
    authorized_locks: ['lock_building_a_entrance', 'lock_building_a_basement'],
    start_date: '2025-12-01T00:00:00Z',
    end_date: '2025-12-31T23:59:59Z'
  }
);

Webhooks

Setting Up Webhooks

# Create webhook subscription
curl -X POST https://api.snapkey.dk/v1/webhooks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/snapkey",
    "events": [
      "access.granted",
      "access.denied",
      "key.created",
      "key.revoked",
      "door.forced"
    ],
    "secret": "your_webhook_secret_for_verification"
  }'

Available Events

Access Events:
├─ access.granted        # Successful access
├─ access.denied         # Access denied
├─ access.expired        # Attempted use of expired key
└─ access.invalid        # Invalid credentials

Key Events:
├─ key.created           # New key issued
├─ key.updated           # Key permissions changed
├─ key.revoked           # Key revoked
└─ key.expired           # Key reached expiration

Lock Events:
├─ lock.online           # Lock came online
├─ lock.offline          # Lock went offline
├─ door.forced           # Door forced open (sensor)
└─ door.left_open        # Door left open (timeout)

User Events:
├─ user.created          # New user added
├─ user.updated          # User details changed
└─ user.deleted          # User removed

Webhook Handler Example

from flask import Flask, request, jsonify
import hmac
import hashlib

app = Flask(__name__)

WEBHOOK_SECRET = "your_webhook_secret"

@app.route('/webhooks/snapkey', methods=['POST'])
def snapkey_webhook():
    # 1. Verify signature
    signature = request.headers.get('X-SnapKey-Signature')
    payload = request.get_data()

    expected_signature = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected_signature):
        return jsonify({"error": "Invalid signature"}), 401

    # 2. Parse event
    event = request.json
    event_type = event['type']

    # 3. Handle different event types
    if event_type == 'access.granted':
        handle_access_granted(event['data'])

    elif event_type == 'access.denied':
        handle_access_denied(event['data'])

    elif event_type == 'door.forced':
        handle_security_alert(event['data'])

    elif event_type == 'key.revoked':
        handle_key_revocation(event['data'])

    # 4. Acknowledge receipt
    return jsonify({"status": "received"}), 200

def handle_access_granted(data):
    """Log successful access to SIEM"""
    send_to_siem({
        "event_type": "physical_access",
        "result": "success",
        "user": data['user_email'],
        "location": data['lock_name'],
        "timestamp": data['timestamp']
    })

def handle_access_denied(data):
    """Alert on repeated failed access attempts"""
    failed_attempts = count_recent_failures(data['user_id'], minutes=10)

    if failed_attempts >= 3:
        send_alert({
            "severity": "high",
            "message": f"Multiple failed access attempts by {data['user_email']}",
            "location": data['lock_name']
        })

def handle_security_alert(data):
    """Immediate response to forced door"""
    send_sms_to_security({
        "message": f"🚨 ALARM: Door forced at {data['lock_name']}",
        "location": data['location_coordinates']
    })

    trigger_video_recording(data['lock_id'])

if __name__ == '__main__':
    app.run(port=5000)

Integration Patterns

Pattern 1: HR System Sync

HR System → API → SnapKey
├─ Employee hired → Create user + issue keys
├─ Department change → Update key permissions
├─ Employee terminated → Revoke all keys immediately
└─ Daily sync → Verify consistency

Pattern 2: Building Management System (BMS)

# Integrate SnapKey with BMS for climate control

def access_event_handler(access_event):
    """When someone enters a room, adjust HVAC"""

    if access_event['type'] == 'access.granted':
        room = access_event['lock']['room']

        # Turn on lights
        bms.set_lights(room, state='on')

        # Adjust temperature
        bms.set_temperature(room, target=21)

        # Log occupancy
        bms.mark_occupied(room, user=access_event['user'])

        # Schedule auto-off after 2 hours
        schedule_room_reset(room, delay_minutes=120)

Pattern 3: Visitor Management

// Complete visitor flow integration

async function registerVisitor(visitor, host, duration_hours) {
  // 1. Create temporary user
  const user = await snapkey.post('/users', {
    email: visitor.email,
    first_name: visitor.first_name,
    last_name: visitor.last_name,
    tags: ['visitor'],
    metadata: {
      host_employee: host.email,
      company: visitor.company,
      purpose: visitor.purpose
    }
  });

  // 2. Issue time-limited key
  const key = await snapkey.post('/keys', {
    user_id: user.id,
    locks: ['lobby_entrance', 'meeting_room_a'],
    valid_from: new Date().toISOString(),
    valid_until: new Date(Date.now() + duration_hours * 3600000).toISOString()
  });

  // 3. Print visitor badge with QR code
  await printBadge({
    name: visitor.first_name + ' ' + visitor.last_name,
    company: visitor.company,
    host: host.first_name + ' ' + host.last_name,
    qr_code: key.qr_code_url,
    valid_until: key.valid_until
  });

  // 4. Notify host
  await sendEmail(host.email, {
    subject: 'Your visitor has arrived',
    body: `${visitor.first_name} ${visitor.last_name} from ${visitor.company} has checked in.`
  });

  return key;
}

MQTT for IoT Integration

import paho.mqtt.client as mqtt
import json

# Connect to SnapKey MQTT broker
client = mqtt.Client()
client.username_pw_set("your_api_key", "")
client.connect("mqtt.snapkey.dk", 8883)

# Subscribe to lock events
client.subscribe("snapkey/locks/+/status")
client.subscribe("snapkey/locks/+/access")

def on_message(client, userdata, msg):
    topic = msg.topic
    payload = json.loads(msg.payload)

    if 'status' in topic:
        # Lock status changed
        lock_id = topic.split('/')[2]
        print(f"Lock {lock_id} is now {payload['status']}")

    elif 'access' in topic:
        # Access event
        print(f"Access: {payload['result']} by {payload['user']}")

client.on_message = on_message
client.loop_forever()

Rate Limits & Best Practices

Rate Limits

Standard tier:
├─ 1000 requests/hour
└─ 100 webhook deliveries/minute

Enterprise tier:
├─ 10,000 requests/hour
├─ 1000 webhook deliveries/minute
└─ Dedicated API endpoints

Best Practices

  1. Cache responses – Don't fetch the same data repeatedly
  2. Use webhooks instead of polling when possible
  3. Implement exponential backoff for retries
  4. Batch operations when creating multiple keys
  5. Use GraphQL for complex queries to reduce roundtrips
  6. Monitor API usage to avoid rate limits

FAQ

Er API-adgang inkluderet i alle licenser?

API-adgang er inkluderet i Enterprise-licenser. Contact us for pricing på andre tiers.

Hvor hurtigt leveres webhooks?

Webhooks sendes typisk inden for 1 sekund efter event. Vi garanterer delivery med automatic retries.

Kan jeg teste API'en uden at påvirke produktion?

Ja, vi tilbyder et komplet sandbox-miljø på https://sandbox-api.snapkey.dk/v1


Kontakt os

Brug for hjælp til at komme i gang med SnapKey API? Vores udviklerteam står klar.

Kontakt udviklerteam
Relaterede artikler
Digital adgangskontrol for detailhandel og selvbetjeningsboder

Moderne adgangsløsninger til unmanned stores, 24/7 butikker, vending operations og selvbetjening. SnapKey til retail automation.

Integration af fysisk og digital sikkerhed – Fremtidens helhedsorienterede sikkerhedsmodel

Lær hvordan moderne sikkerhedssystemer kombinerer adgangskontrol med cybersikkerhed gennem SIEM-integration, korrelation af hændelser og unified security operations.

6.000 danske virksomheder skal sikre kritisk infrastruktur – Er du omfattet?

Nye EU-direktiver betyder at ca. 6.000 danske virksomheder skal opfylde skærpede sikkerhedskrav. Tjek om din virksomhed er omfattet af NIS2 og CER-direktiverne.


SnapKey Logo

SnapKey er din digitale nøgle til alle typer låse. Åbn nemt døre og låse direkte fra din smartphone, og få hurtig, sikker og fleksibel adgang uden behov for fysiske nøgler eller ekstra apps. Perfekt til private hjem, virksomheder og delte rum.

Løsninger
SnapKey ResidentialSnapKey UtilitySnapKey PublicSnapKey LogisticsGæste Check-in
Udviklere
API-dokumentationAPI-referenceWebhooksÆndringslogSystemstatus
Virksomhed
Om osHvorfor SnapKeyBliv partnerVidenVideoerKontakt os
Juridisk
HandelsbetingelserPrivatlivspolitikTillid & sikkerhed
Kontakt
SnapKey ApS+45 3242 9050info@snapkey.dk

© Alle rettigheder forbeholdes.