Skip to main content
Dynamo CSMS webhooks push real-time events to your server when things happen on your charging network — sessions start and end, chargers connect or disconnect, alerts fire, and firmware updates complete. Instead of polling the API, you register an HTTPS endpoint and we deliver events as they happen.

Authentication

All webhook management endpoints require your API key:
Authorization: Bearer YOUR_API_KEY
# or
X-API-Key: YOUR_API_KEY

Available events

EventDescription
charge_point.connectedA charge point establishes a WebSocket connection
charge_point.disconnectedA charge point loses its connection
charge_point.status_changedConnector status changes (Available, Charging, Faulted, etc.)
session.startedA charging session begins
session.endedA charging session completes
session.cost_updatedSession cost is recalculated mid-session
commissioning.startedCharger commissioning process begins
commissioning.completedCharger is fully commissioned and operational
commissioning.failedCommissioning failed — check the error details
alert.triggeredA monitoring alert fires
alert.resolvedA previously triggered alert clears
firmware.update_startedFirmware update begins on a charge point
firmware.update_completedFirmware update finishes successfully
handover.completedA charger handover to a new operator completes

Create a webhook endpoint

POST /api/v1/webhooks/endpoints
url
string
required
HTTPS URL where events will be delivered. Must use https://.
events
string[]
required
List of event types to subscribe to. Use ["*"] to subscribe to all events.
secret
string
Signing secret for HMAC-SHA256 payload verification. Store this securely — it is not retrievable after creation.
curl -X POST https://api.dynamo-csms.com/api/v1/webhooks/endpoints \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/dynamo",
    "events": ["session.started", "session.ended", "charge_point.disconnected"],
    "secret": "whsec_your_secret_here"
  }'
{
  "id": "whe_01HX9K2M4N8P3Q7R",
  "url": "https://yourapp.com/webhooks/dynamo",
  "events": ["session.started", "session.ended", "charge_point.disconnected"],
  "active": true,
  "created_at": "2024-01-20T14:30:00Z"
}

List webhook endpoints

GET /api/v1/webhooks/endpoints Returns all webhook endpoints registered for your account.
curl https://api.dynamo-csms.com/api/v1/webhooks/endpoints \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "data": [
    {
      "id": "whe_01HX9K2M4N8P3Q7R",
      "url": "https://yourapp.com/webhooks/dynamo",
      "events": ["session.started", "session.ended"],
      "active": true,
      "created_at": "2024-01-20T14:30:00Z"
    }
  ],
  "total": 1
}

Get a webhook endpoint

GET /api/v1/webhooks/endpoints/{endpoint_id}
endpoint_id
string
required
The ID of the webhook endpoint to retrieve.

Update a webhook endpoint

PATCH /api/v1/webhooks/endpoints/{endpoint_id}
endpoint_id
string
required
The ID of the webhook endpoint to update.
url
string
New delivery URL for this endpoint.
events
string[]
Replacement list of subscribed event types.
active
boolean
Set to false to pause delivery without deleting the endpoint.
curl -X PATCH https://api.dynamo-csms.com/api/v1/webhooks/endpoints/whe_01HX9K2M4N8P3Q7R \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["session.started", "session.ended", "alert.triggered", "alert.resolved"],
    "active": true
  }'

Delete a webhook endpoint

DELETE /api/v1/webhooks/endpoints/{endpoint_id}
endpoint_id
string
required
The ID of the webhook endpoint to delete.
Returns 204 No Content on success.
curl -X DELETE https://api.dynamo-csms.com/api/v1/webhooks/endpoints/whe_01HX9K2M4N8P3Q7R \
  -H "Authorization: Bearer YOUR_API_KEY"

Delivery history

GET /api/v1/webhooks/endpoints/{endpoint_id}/deliveries Retrieve the delivery history for a webhook endpoint. Use this to debug failed deliveries or inspect retry behavior.
endpoint_id
string
required
The ID of the webhook endpoint.
status
string
Filter by delivery status: succeeded, failed, or pending.
limit
number
default:"20"
Number of records to return (max 100).
curl "https://api.dynamo-csms.com/api/v1/webhooks/endpoints/whe_01HX9K2M4N8P3Q7R/deliveries?status=failed" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "data": [
    {
      "id": "whd_01HXB3N7P2Q4R8S9",
      "endpoint_id": "whe_01HX9K2M4N8P3Q7R",
      "event": "session.started",
      "status": "failed",
      "response_code": 500,
      "attempts": 3,
      "last_attempted_at": "2024-01-20T15:05:32Z",
      "next_retry_at": "2024-01-20T15:35:32Z"
    }
  ],
  "total": 1
}
id
string
Unique delivery record ID.
event
string
The event type that triggered this delivery.
status
string
Delivery status: succeeded, failed, or pending.
response_code
number
HTTP status code returned by your endpoint.
attempts
number
Number of delivery attempts made. Dynamo retries failed deliveries with exponential backoff up to 5 times over 24 hours.

Webhook payload structure

Every event is delivered as an HTTP POST with a JSON body:
{
  "event": "session.started",
  "timestamp": "2024-01-20T14:30:00Z",
  "data": {
    "session_id": "sess_abc123",
    "charge_point_id": "cp_001",
    "connector_id": 1,
    "id_tag": "driver@example.com"
  }
}
event
string
The event type (e.g., session.started).
timestamp
string
ISO 8601 timestamp of when the event occurred.
data
object
Event-specific payload. Structure varies by event type.

Signature verification

When you provide a secret at endpoint creation, every delivery includes an X-Webhook-Signature header. The value is an HMAC-SHA256 digest of the raw request body, prefixed with sha256=. Always verify this signature before processing a webhook payload. This confirms the request came from Dynamo CSMS and the body was not tampered with in transit.
Compute the HMAC over the raw request body bytes before any JSON parsing. Parsing and re-serializing the payload may alter whitespace and invalidate the signature.
import hmac
import hashlib

def verify_webhook(payload_body: bytes, signature_header: str, secret: str) -> bool:
    """Return True if the webhook signature is valid."""
    expected = "sha256=" + hmac.new(
        secret.encode("utf-8"),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)

# In your request handler:
# raw_body = request.get_data()  # Flask example
# sig = request.headers.get("X-Webhook-Signature")
# if not verify_webhook(raw_body, sig, "whsec_your_secret_here"):
#     return "Unauthorized", 401
Respond with a 2xx status code within 10 seconds. If your handler needs more time to process an event, acknowledge the delivery immediately and process asynchronously.