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:

Create or Update a Webhook
PUT /webhooks
WebhookRequest
required
name string

optional
alertIntegrationName string
displayName string
enabled boolean
events [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 FailureHandlingRequest
integrationName string
resetAlertIntegrationName boolean
retryStrategy string none | one | three

The alertIntegrationName, if provided, will be used to POST the FailureMessage object. See Failure Handling for details.

WebhookResponse
required
name string
enabled boolean
events [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 FailureHandlingResponse
integrationName string
retryStrategy string none | one | three
suspended boolean

optional
suspendedTimestamp timestamp
alertIntegrationName string
displayName 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 (0 to 9)

  • Latin letters (A to Z, a to z) – and the

  • The 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 name may use, and additionally these characters are allowed:

  • Exclamation points !

  • Periods .

  • Asterisks *

  • Parentheses ( or )

  • Spaces

Get all Webhooks
GET /webhooks
WebhooksResponse
required
webhooks [WebhookResponse]
Get a Webhook
GET /webhooks/{name}
    Request:
    NamePositionTypeRequired
    namepathstringrequired
    Response: WebhookResponse
Delete a Webhook
DELETE /webhooks/{name}
    Request:
    NamePositionTypeRequired
    namepathstringrequired
    Response: void

Note

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.

WebhookPayload
required
id string
timestamp timestamp
transactionId string
type string
username 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.

FailureMessage
required
actualStatus string
eventData EventStreamData
expectedStatus string
url string
webhookName object
FailureHandlingRequest
optional
actOnStatusCodes [string]
actOnTimeout boolean
mode string none | divert | suspend
FailureHandlingResponse
required
actOnStatusCodes [string]
actOnTimeout boolean
mode 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 actOnStatusCodes property takes an array of strings, where each string is three characters long and can have the following values:

    1. 4xx (to act on all 400 Errors)

    2. 5xx (to act on all 500 Errors)

    3. Specific 400 or 500 error codes such as 403, 501, 504

    4. If the actOnStatusCodes property is empty, Socotra will invoke failure-handling for all failures.

  • If actOnTimeout is true, failure handling will be invoked for time outs. Otherwise, if actOnTimeout is false, 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 webhook suspended property will be set to true, and the event stream will emit a webhook.suspended event. The webhook will not receive or process events, and will remain inactive until the webhook is reactivated.

  • divert: The WebhookPayload will be stored for 90 Days and can be retrieved with GET /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:

EventStreamWebhookSuspendedData
required
event 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
integrationName string
webhookName 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:

Enable a suspended Webhook
PATCH /webhooks/{name}/unsuspend
    Request:
    NamePositionTypeRequired
    namepathstringrequired
    Response: WebhookResponse

Diverted events

The WebhookPayload will be stored for 90 Days and can be retrieved with GET /webhooks/{name}/diverted.

Get a paginated list of diverted events
GET /webhooks/{name}/diverted
    Request:
    NamePositionTypeRequired
    limitqueryintegeroptional
    namepathstringrequired
    offsetqueryintegeroptional

The 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).

WebhookDivertedEventsResponse
required
webhookName string
WebhookDivertedEventResponse
required
eventType 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
timestamp timestamp
eventId string
transactionId string

optional
username 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 a diverted event
DELETE /webhooks/{name}/diverted/{transactionId}
    Request:
    NamePositionTypeRequired
    namepathstringrequired
    transactionIdpathstringrequired
    Response: void
Resend a diverted event
POST /webhooks/{name}/diverted/{transactionId}/resend
    Request:
    NamePositionTypeRequired
    namepathstringrequired
    transactionIdpathstringrequired
    Response: void