Scenario
As an admin, you want another system to know about activity in PlusPlus as it happens, for example when someone completes an assignment, without polling the API.
Solution
A webhook is a subscription: you choose the types of events to subscribe to, and PlusPlus sends each matching event to your endpoint as it happens.
Do you need an API token? Not if you register the webhook yourself in the dashboard. If another app or agent registers it for you, that app needs an API token with Webhooks: Read & write access. See How to manage API tokens.
Register a webhook
Open the profile menu and select Dashboard.
Select Webhooks under Administration in the left sidebar.
Click Register webhook.
The Register webhook form opens.
Enter a Name that says what the webhook is for.
Enter the Endpoint URL. It must be a public HTTPS URL.
Under Event types, find the group for the object you want, for example Assignment, and expand it if it's collapsed. Then select the events to receive. Each option shows its API name in parentheses, for example Assignment completed (
assignment.completed).Selecting the checkbox in a group's header selects every event in that group. The counter beside the group name shows how many are selected.
Click Register webhook.
The webhook appears in the list with the status Active.
Event types in this form means the kinds of activity you can subscribe to. It doesn't refer to Event Series.
Send a test event
Open the context menu (button with three dots) for the webhook and select Send test event.
PlusPlus sends a signed
pingevent to the endpoint.Confirm that your endpoint received it.
Change event types
Open the context menu for the webhook and select Edit event types.
The Edit event types dialog opens.
Select or clear event types. At least one is required.
Click Save event types.
Delete a webhook
Open the context menu for the webhook and select Delete.
Confirm the action.
Deliveries stop immediately. Deletion can't be undone.
Go deeper
Endpoint requirements
The URL must use HTTPS and point to a public address. PlusPlus rejects private and internal addresses.
The endpoint must return a 2xx response within 5 seconds. Otherwise, the event is retried with increasing delays. If your processing takes longer than that, respond first and do the work afterward.
Delivery is at-least-once, so the same event can arrive more than once. Use the event's
idto ignore duplicates. Theidstays the same across retries.
Event payload
Every event has the same envelope: id, type, api_version, created_at, and data.object. data.object has the same shape as the API's response for that resource. For example, an assignment.completed event contains the full assignment, including the learner's name and email and the content item's name.
The PlusPlus developer docs list the payload for each event at developers.plusplus.co/api. Your site also serves them at /docs/api/.
Signing secret
Each webhook has a signing secret (whsec_...). Copy it from the Signing secret column. Your endpoint uses it to confirm that an event came from PlusPlus, by checking the svix-id, svix-timestamp, and svix-signature headers with a Standard Webhooks–compatible library.
For verification code and examples, see the webhooks guide at developers.plusplus.co/webhooks, also at /docs/webhooks/ on your site.
The signing secret works differently from an API token. You can copy it again at any time. To replace it, use the API's rotate-secret endpoint. The old secret stops working immediately, so update your endpoint at the same time.
Status
Active: events are being delivered.
Disabled: events are not being delivered. A webhook can become disabled without anyone changing it, if its endpoint fails repeatedly. To re-enable it, send
PATCH /api/v2/webhooks/{id}/with{"is_active": true}.
Webhooks and API tokens
A webhook isn't tied to the token that registered it. Revoking that token, or the token expiring, doesn't stop deliveries. To stop a webhook, delete it.
Event types
Event types are grouped by object. In the API, each event type uses object.action format. The Assignment group contains these events:
Event type | Sent when |
| Content is assigned to someone |
| An assignment changes |
| An assignment is completed |
| An assignment is dropped |
| Someone is exempted from an assignment |
| A completion is undone |
| An exemption is undone |
| An assignment is deleted |
The other groups cover:
Content items of any type (All Content Items (Any Type)), plus each content type separately: articles, videos, courses, Guides, links, tracks, scheduled tracks, events, Event Series, and collections
Enrollments
Automated rules
Calendar:
calendar.owner_sync_failed,calendar.owner_sync_restored, andcalendar.owner_transferred
Event Series events use the event_type.* names.
If you select both All Content Items (Any Type) and a type-specific group such as Video, you receive each event for that type twice.
Managing webhooks through the API
All webhook endpoints are under /api/v2/webhooks/ and require a token with Webhooks access. Through the API, you can:
List, create, update, and delete webhooks.
Pause and resume a webhook by setting
is_active.Retrieve or rotate the signing secret.
List delivery attempts.
Send a test event.
List all available event types with
/api/v2/webhooks/event-catalog/.
When registering through the API, you can subscribe to a whole group with a wildcard such as assignment.*.
What you can't do today
You can't edit a webhook's name or endpoint URL in the dashboard. Delete the webhook and register it again, or update it through the API.
You can't pause, resume, or re-enable a webhook, or rotate its signing secret, in the dashboard. Use the API.
You can't view delivery attempts in the dashboard. Use
GET /api/v2/webhooks/{id}/deliveries/, which returns the status, response code, and timestamp of each attempt.Group selections and wildcards are saved as the events that exist at that moment. Event types added to a group later aren't included automatically.
