Incoming Webhooks
Incoming webhooks are endpoints that GxP exposes for external systems to send data into the platform.
Overview
GxP provides webhook endpoints for integrating with external services like:
- MQTT gateways for access control hardware
- CRM systems for attendee synchronization
- External registration platforms
- Third-party ticketing systems
Authentication
Incoming webhooks authenticate using HMAC signatures. Each webhook source has a configured secret key that must be used to sign requests.
Signature Verification
Include the signature in the X-GxP-Signature header:
X-GxP-Signature: sha256=abc123...
Generating Signatures
$payload = json_encode($data);
$signature = hash_hmac('sha256', $payload, $webhookSecret);
const crypto = require('crypto');
const signature = crypto
.createHmac('sha256', webhookSecret)
.update(JSON.stringify(data))
.digest('hex');
Available Endpoints
MQTT Gateway Status
Receives status updates from MQTT gateway devices.
Endpoint: POST /webhook/v1/mqtt-gateway-status
Headers:
Content-Type: application/jsonX-GxP-Signature: sha256={signature}
Payload:
{
"gateway_id": "GW-001",
"status": "online",
"readers": [
{
"reader_id": "READER-001",
"status": "connected",
"last_scan": "2024-01-15T10:30:00Z"
}
],
"timestamp": "2024-01-15T10:31:00Z"
}
Response:
{
"success": true,
"message": "Status updated"
}
Access Event
Receives access scan events from external readers.
Endpoint: POST /webhook/v1/access-event
Payload:
{
"reader_id": "READER-001",
"credential_value": "ABC123456",
"scan_type": "barcode",
"timestamp": "2024-01-15T14:30:00Z"
}
Response:
{
"success": true,
"access_granted": true,
"attendee": {
"id": 12345,
"first_name": "Jane",
"last_name": "Smith"
}
}
Cvent Webhook
Receives events from Cvent integration.
Endpoint: POST /webhook/v1/cvent
Headers:
Content-Type: application/jsonX-Cvent-Signature: {signature}
Payload:
{
"event_type": "registration.created",
"event_id": "evt_123",
"data": {
"registration_id": "reg_456",
"attendee": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com"
}
},
"timestamp": "2024-01-15T09:00:00Z"
}
Supported Cvent Events:
registration.createdregistration.updatedregistration.cancelledattendee.checked_in
Attendee Sync
Bulk synchronize attendees from external systems.
Endpoint: POST /webhook/v1/attendee-sync
Payload:
{
"project_slug": "my-event",
"team_slug": "my-team",
"sync_mode": "upsert",
"attendees": [
{
"external_id": "EXT-001",
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@example.com",
"attendee_type": "general"
}
]
}
Sync Modes:
upsert: Create or update based on external_idcreate: Only create new recordsupdate: Only update existing records
Response:
{
"success": true,
"results": {
"created": 5,
"updated": 10,
"skipped": 2,
"errors": []
}
}
Error Responses
Invalid Signature (401)
{
"error": "Invalid signature",
"message": "The request signature does not match"
}
Invalid Payload (400)
{
"error": "Validation failed",
"message": "The given data was invalid",
"errors": {
"attendees": ["The attendees field is required"]
}
}
Rate Limited (429)
{
"error": "Too Many Requests",
"message": "Rate limit exceeded",
"retry_after": 60
}
IP Allowlisting
For additional security, configure IP allowlists for webhook sources:
- Navigate to Project Settings > Integrations > Webhooks
- Select the webhook endpoint
- Add allowed IP addresses or CIDR ranges
- Save changes
Retry Policy
If your webhook returns an error (non-2xx response), GxP will:
- Not retry: Incoming webhooks do not retry
- Log the error: Failures are logged for debugging
- Return error: The calling system receives the error response
Testing Webhooks
Using cURL
# Calculate signature
PAYLOAD='{"gateway_id":"GW-001","status":"online"}'
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "your-secret-key" | cut -d' ' -f2)
# Send webhook
curl -X POST "https://api.gramercy.cloud/webhook/v1/mqtt-gateway-status" \
-H "Content-Type: application/json" \
-H "X-GxP-Signature: sha256=$SIGNATURE" \
-d "$PAYLOAD"
Using Postman
- Set the request body
- In Pre-request Script:
const secret = pm.environment.get('webhook_secret');
const body = pm.request.body.raw;
const signature = CryptoJS.HmacSHA256(body, secret).toString();
pm.request.headers.add({key: 'X-GxP-Signature', value: 'sha256=' + signature});
Monitoring
View webhook activity in the dashboard:
- Navigate to Project Settings > Integrations > Webhooks
- Click View Logs
- Filter by endpoint, status, or date range
Webhook Log Entry
{
"id": "log_123",
"endpoint": "/webhook/v1/mqtt-gateway-status",
"method": "POST",
"status": 200,
"source_ip": "203.0.113.50",
"received_at": "2024-01-15T10:31:00Z",
"response_time_ms": 45
}
Best Practices
- Always verify signatures: Never process webhooks without signature verification
- Use HTTPS: All webhook URLs should use HTTPS
- Respond quickly: Return responses within 5 seconds
- Process asynchronously: Queue long-running tasks
- Log all requests: Keep records for debugging
- Monitor for failures: Set up alerts for failed webhooks