Webhooks
Overview
Webhooks allows you to notify your downstream systems when relevant events are raised by Socotra. Here are some examples how webhooks can be used:
Triggering integration processes, such as printing and sending an invoice after it is issued
Enabling automated processes, such as a renewal process after a policy nears expiration
Capturing data changes for maintaining an external database that includes Socotra data
Create a a webhook using an External Service Integration for each external system to be notified. Each webhook will listen for a set of events and notify the associated external system when any event in the webhook event set is raised.
Setting Up External Service Integrations
External service integrations (ESIs) provide a gateway for Socotra to communicate with external systems. Each webhook will use an ESI, so you’ll need to establish those first. To establish and manage webhook integration points, use the External Service Integration API and create an integration with type webhook.
After you establish your ESI, you can begin to create and use webhooks.
Note
The names for each event will be the name as shown elsewhere in the documentation, such as policy.create or endorsement.update. See External Service Integration API
Setting Up Webhooks
You can create as many webhook instances as you need. Each instance will listen for a set of events and notify its associated ESI when any of those events are raised.
This endpoint will create (or update, if a webhook exists with that name) a webhook definition:
PUT /webhooks| Name | Position | Type | Required |
|---|---|---|---|
| request | body | WebhookRequest | required |
WebhookResponserequiredname stringoptionalalertIntegrationName stringdisplayName stringenabled booleanevents [string cancellation.create | cancellation.update | cancellation.rescind | cancellation.issue | cancellation.effective | claim.close | claim.create | claim.discard | claim.open | claim.update | policy.gracePeriod | policy.gracePeriod.update | invoice.issue | invoice.invalidate | invoice.pastDue | invoice.writtenOff | payment.pay | policy.cancel | policy.create | policy.discard | policy.endorse | policy.finalize | policy.issue | policy.lapse | policy.reinstatement.close | policy.reinstatement.invoice | policy.reinstatement.issue | policy.reinstatement.open | policy.renew | policy.update | policy.upgrade | subClaim.open | subClaim.update | subClaim.close | subClaim.reopen | subClaim.updateReserve | policy.end.reminder | subClaim.createPayable | subClaim.reversePayable | endorsement.create | endorsement.update | endorsement.quote | endorsement.accept | endorsement.issue | endorsement.invalidate | endorsement.discard | endorsement.effective | reinstatement.accept | reinstatement.create | reinstatement.issue | reinstatement.invalidate | reinstatement.deadlineReached | reinstatement.effective | renewal.create | renewal.update | renewal.quote | renewal.accept | renewal.issue | renewal.invalidate | renewal.discard | renewal.effective | policy.effective | policy.end | policy.quote.create | policy.quote.discard | policy.quote.update | policy.quote.quoted | policy.quote.accept | policy.quote.declined | policy.quote.invalidate | premiumReport.create | premiumReport.update | premiumReport.issue | premiumReport.discard | premiumReport.reverse | premiumReport.replace | premiumReport.effective | premiumReport.pay | login.success | login.failure | policyholder.create | policyholder.update | payment.reverse | payment.update | payment.ready | payment.discard | payment.return | payment.decline | payment.draft | policy.gracePeriod.satisfied | disbursement.issue | disbursement.create | disbursement.update | catchUp.issue | catchUp.writtenOff | catchUp.pay | catchUp.pay.reverse | catchUp.invalidate | catchUp.pastDue | cash.transfer]failureHandling FailureHandlingRequestintegrationName stringresetAlertIntegrationName booleanretryStrategy string none | one | three
The alertIntegrationName, if provided, will be used to POST the FailureMessage object. See Failure Handling for details.
requiredname stringenabled booleanevents [string cancellation.create | cancellation.update | cancellation.rescind | cancellation.issue | cancellation.effective | claim.close | claim.create | claim.discard | claim.open | claim.update | policy.gracePeriod | policy.gracePeriod.update | invoice.issue | invoice.invalidate | invoice.pastDue | invoice.writtenOff | payment.pay | policy.cancel | policy.create | policy.discard | policy.endorse | policy.finalize | policy.issue | policy.lapse | policy.reinstatement.close | policy.reinstatement.invoice | policy.reinstatement.issue | policy.reinstatement.open | policy.renew | policy.update | policy.upgrade | subClaim.open | subClaim.update | subClaim.close | subClaim.reopen | subClaim.updateReserve | policy.end.reminder | subClaim.createPayable | subClaim.reversePayable | endorsement.create | endorsement.update | endorsement.quote | endorsement.accept | endorsement.issue | endorsement.invalidate | endorsement.discard | endorsement.effective | reinstatement.accept | reinstatement.create | reinstatement.issue | reinstatement.invalidate | reinstatement.deadlineReached | reinstatement.effective | renewal.create | renewal.update | renewal.quote | renewal.accept | renewal.issue | renewal.invalidate | renewal.discard | renewal.effective | policy.effective | policy.end | policy.quote.create | policy.quote.discard | policy.quote.update | policy.quote.quoted | policy.quote.accept | policy.quote.declined | policy.quote.invalidate | premiumReport.create | premiumReport.update | premiumReport.issue | premiumReport.discard | premiumReport.reverse | premiumReport.replace | premiumReport.effective | premiumReport.pay | login.success | login.failure | policyholder.create | policyholder.update | payment.reverse | payment.update | payment.ready | payment.discard | payment.return | payment.decline | payment.draft | policy.gracePeriod.satisfied | disbursement.issue | disbursement.create | disbursement.update | catchUp.issue | catchUp.writtenOff | catchUp.pay | catchUp.pay.reverse | catchUp.invalidate | catchUp.pastDue | cash.transfer]failureHandling FailureHandlingResponseintegrationName stringretryStrategy string none | one | threesuspended booleanoptionalsuspendedTimestamp timestampalertIntegrationName stringdisplayName string
The webhook name must not be longer than 128 characters, and may contain only letters, numbers, and symbols as follows:
Alphanumeric characters – the arabic numerals (
0to9)Latin letters (
AtoZ,atoz) – and theThe hyphen, underscore, and tilde symbols (
-,_,~)
The webhook displayName must not be longer than 256 characters and may contain only the following:
Alphanumeric characters and latin characters (with the same allowed characters as for the
name)The hyphen, underscore, and tilde, just as the
namemay use, and additionally these characters are allowed:
Exclamation points
!Periods
.Asterisks
*Parentheses
(or)Spaces
GET /webhooksWebhooksResponserequiredwebhooks [WebhookResponse]
GET /webhooks/{name}| Name | Position | Type | Required |
|---|---|---|---|
| name | path | string | required |
WebhookResponseDELETE /webhooks/{name}| Name | Position | Type | Required |
|---|---|---|---|
| name | path | string | required |
voidNote
Webhooks can also be created and managed through the admin user interface. All the webhooks endpoints require admin user access. This requirement is the same as the requirement for setting up the external service integrations that the webhooks will use.
Behavior
After each event is fired, the application will scan all webhooks, and for each one that is enabled, and for which the event is included in the events property, the application will POST the WebhookPayload object to the associated External Service Integration for that webhook.
The data property contains the same information as is returned in the Event Stream API.
On time out or non-200 responses from the call, error handling will be used, as discussed below.
requiredid stringtimestamp timestampdata EventStreamDatatransactionId stringtype stringusername string
Startup
When a webhook is first enabled (or when it is re-enabled after being suspended), the webhook will not attempt to catch up on old messages.
Event ordering
Events sent for a specific webhook will be ordered based on the timestamp on the event response. Multiple events for the same webhook will be sent in sequence.
If there are multiple webhooks for a single event type, the webhooks may or may not be triggered in at the same time. The order and timing is not guaranteed.
For example, if two webhooks, CancelEventHandlerA and CancelEventHandlerB, handle cancellation.issue events, when several cancellation.issue events occur, CancelEventHandlerB may receive some or all of the cancellation.issue events before the first cancellation.issue event is sent to CancelEventHandlerA.
Failure Handling
If an ESI responds with anything other than a 2xx HTTP response, or times out (does not respond within 120 seconds), the message will be considered failed.
The WebhookRequest.alertIntegrationName, if provided, will be used to POST the FailureMessage object.
If resetAlertIntegrationName is true, the application will reset alertIntegrationName to null.
requiredactualStatus stringeventData EventStreamDataexpectedStatus stringurl stringwebhookName object
optionalactOnStatusCodes [string]actOnTimeout booleanmode string none | divert | suspend
requiredactOnStatusCodes [string]actOnTimeout booleanmode string none | divert | suspend
Failure handling will be invoked based on the response (or non-response) from the webhook target.
The FailureHandlingRequest properties, actOnTimeout and actOnStatusCodes control which failures and time outs are handled as errors:
The
actOnStatusCodesproperty takes an array of strings, where each string is three characters long and can have the following values:4xx(to act on all 400 Errors)5xx(to act on all 500 Errors)Specific 400 or 500 error codes such as
403,501,504If the
actOnStatusCodesproperty is empty, Socotra will invoke failure-handling for all failures.
If
actOnTimeoutistrue, failure handling will be invoked for time outs. Otherwise, ifactOnTimeoutisfalse, time outs will be ignored.
Retry Strategy
On failure, the webhook retryStrategy property will be used to determine the course of action:
none: The failure will be silently ignored and the system will act as if the message had succeeded.one: The system will try one more time, after 60 seconds. If this succeeds, the operation will be considered to have succeeded.three: The system will try three more times, each 60 seconds apart. If any of these succeed, the operation will be considered to have succeeded. Note: subsequent messages will not be sent once one succeeds.
The default value of failureHandling.mode is suspend, unless retryStrategy is none.
If retryStrategy is none, the default value of value of failureHandling.mode is also none.
Failure Handling Mode
If no message succeeds during the retry attempts, the webhook FailureHandlingRequest.mode property will be used to determine the course of action:
none: The failure will be silently ignored and the system will act as if the message had succeeded.suspend: The webhooksuspendedproperty will be set totrue, and the event stream will emit awebhook.suspendedevent. The webhook will not receive or process events, and will remain inactive until the webhook is reactivated.divert: TheWebhookPayloadwill be stored for 90 Days and can be retrieved withGET /webhooks/{name}/diverted.
Use suspend to handle failures when you would like to pause handling these events until the failure is resolved.
Use divert if you need to collect these events that occur while you are resolving the failure, for retrieval and reuse after the failure is resolved.
Suspended Events
When a webhook is suspended, a webhook.suspended event will fire, with the following payload:
requiredevent string cancellation.create | cancellation.update | cancellation.rescind | cancellation.issue | cancellation.effective | claim.close | claim.create | claim.discard | claim.open | claim.update | policy.gracePeriod | policy.gracePeriod.update | invoice.issue | invoice.invalidate | invoice.pastDue | invoice.writtenOff | payment.pay | policy.cancel | policy.create | policy.discard | policy.endorse | policy.finalize | policy.issue | policy.lapse | policy.reinstatement.close | policy.reinstatement.invoice | policy.reinstatement.issue | policy.reinstatement.open | policy.renew | policy.update | policy.upgrade | subClaim.open | subClaim.update | subClaim.close | subClaim.reopen | subClaim.updateReserve | policy.end.reminder | subClaim.createPayable | subClaim.reversePayable | endorsement.create | endorsement.update | endorsement.quote | endorsement.accept | endorsement.issue | endorsement.invalidate | endorsement.discard | endorsement.effective | reinstatement.accept | reinstatement.create | reinstatement.issue | reinstatement.invalidate | reinstatement.deadlineReached | reinstatement.effective | renewal.create | renewal.update | renewal.quote | renewal.accept | renewal.issue | renewal.invalidate | renewal.discard | renewal.effective | policy.effective | policy.end | policy.quote.create | policy.quote.discard | policy.quote.update | policy.quote.quoted | policy.quote.accept | policy.quote.declined | policy.quote.invalidate | premiumReport.create | premiumReport.update | premiumReport.issue | premiumReport.discard | premiumReport.reverse | premiumReport.replace | premiumReport.effective | premiumReport.pay | login.success | login.failure | policyholder.create | policyholder.update | payment.reverse | payment.update | payment.ready | payment.discard | payment.return | payment.decline | payment.draft | policy.gracePeriod.satisfied | disbursement.issue | disbursement.create | disbursement.update | catchUp.issue | catchUp.writtenOff | catchUp.pay | catchUp.pay.reverse | catchUp.invalidate | catchUp.pastDue | cash.transferintegrationName stringwebhookName string
The suspended webhook will not receive or process events, and will remain inactive until you reactivate the webhook. Enable (reactivate) a suspended webhook using the following endpoint:
PATCH /webhooks/{name}/unsuspend| Name | Position | Type | Required |
|---|---|---|---|
| name | path | string | required |
WebhookResponseDiverted events
The WebhookPayload will be stored for 90 Days and can be retrieved with GET /webhooks/{name}/diverted.
GET /webhooks/{name}/diverted| Name | Position | Type | Required |
|---|---|---|---|
| limit | query | integer | optional |
| name | path | string | required |
| offset | query | integer | optional |
WebhookDivertedEventsResponseThe limit and offset properties are used to page through the list of results, getting batches of diverted events of size limit. Increase the offset property with each query, to skip the events you have already retrieved.
The default value of limit is 100, and the default value of offset is 0, so the first call to GET /webhooks/{name}/diverted will return the first 100 diverted events (or fewer if there are less than 100 events).
requiredevents [WebhookDivertedEventResponse]webhookName string
requiredeventType string cancellation.create | cancellation.update | cancellation.rescind | cancellation.issue | cancellation.effective | claim.close | claim.create | claim.discard | claim.open | claim.update | policy.gracePeriod | policy.gracePeriod.update | invoice.issue | invoice.invalidate | invoice.pastDue | invoice.writtenOff | payment.pay | policy.cancel | policy.create | policy.discard | policy.endorse | policy.finalize | policy.issue | policy.lapse | policy.reinstatement.close | policy.reinstatement.invoice | policy.reinstatement.issue | policy.reinstatement.open | policy.renew | policy.update | policy.upgrade | subClaim.open | subClaim.update | subClaim.close | subClaim.reopen | subClaim.updateReserve | policy.end.reminder | subClaim.createPayable | subClaim.reversePayable | endorsement.create | endorsement.update | endorsement.quote | endorsement.accept | endorsement.issue | endorsement.invalidate | endorsement.discard | endorsement.effective | reinstatement.accept | reinstatement.create | reinstatement.issue | reinstatement.invalidate | reinstatement.deadlineReached | reinstatement.effective | renewal.create | renewal.update | renewal.quote | renewal.accept | renewal.issue | renewal.invalidate | renewal.discard | renewal.effective | policy.effective | policy.end | policy.quote.create | policy.quote.discard | policy.quote.update | policy.quote.quoted | policy.quote.accept | policy.quote.declined | policy.quote.invalidate | premiumReport.create | premiumReport.update | premiumReport.issue | premiumReport.discard | premiumReport.reverse | premiumReport.replace | premiumReport.effective | premiumReport.pay | login.success | login.failure | policyholder.create | policyholder.update | payment.reverse | payment.update | payment.ready | payment.discard | payment.return | payment.decline | payment.draft | policy.gracePeriod.satisfied | disbursement.issue | disbursement.create | disbursement.update | catchUp.issue | catchUp.writtenOff | catchUp.pay | catchUp.pay.reverse | catchUp.invalidate | catchUp.pastDue | cash.transfertimestamp timestampdata EventStreamDataeventId stringtransactionId stringoptionalusername string
After you resolve the webhook failure and re-enable the diverted webhook, you can process the list of diverted events, and POST or DELETE any or all of these events.
DELETE /webhooks/{name}/diverted/{transactionId}| Name | Position | Type | Required |
|---|---|---|---|
| name | path | string | required |
| transactionId | path | string | required |
voidPOST /webhooks/{name}/diverted/{transactionId}/resend| Name | Position | Type | Required |
|---|---|---|---|
| name | path | string | required |
| transactionId | path | string | required |
void