# Custom Scheduled Events



Overview [#overview]

Custom scheduled events are configurable time-based triggers that are not linked to specific workflows, such as delinquency or auto-renewal. You can define policy-specific events ("Policy Events") or events that are more broadly applicable across a tenant ("Tenant Events"). Each of these two types of custom scheduled events has a distinct configuration and set of API endpoints.

Policy Events [#policy-events]

Policy-scoped custom scheduled events can be used to send notifications and trigger tasks such as:

* Processing inflation calculations and other anniversary-based riders
* Triggering notices and reminders to customers a specified number of days prior to the policy anniversary
* Notifying downstream systems that the impact of some mid-term transaction has, or is about to, come into effect

Like other events, these custom scheduled events are emitted to the event stream and, in conjunction with [webhooks](/configuration/general-topics/webhooks), can be used to trigger workflows, send notifications, or update external systems.

Socotra supports the configuration of any number of named event types for each product. However, implementors are encouraged to be thoughtful and deliberate when defining custom events, particularly those that recur on a scheduled basis. Limiting configuration to only essential events helps maintain system clarity, avoids unnecessary processing overhead, and reduces the risk of unintended interactions or noise in downstream systems.

Configuration [#configuration]

Policy-scoped custom scheduled events are configured through the <ApiLink name="CustomEventRef">Custom Events</ApiLink> configuration object found at the top level of the <ApiLink name="ConfigurationRef" />.

<ApiSchema name="CustomEventRef" />

<ApiSchema name="EventScheduleRef" />

<ApiSchema name="EventCadenceRef" />

Options: [#options]

* **anchor:** `policyStart`, `policyEnd`, `termStart`, or `segmentStart`
* **alignment:** *(optional)* `weekStart`, `monthStart`, or `yearStart`
* **offset:** *(optional)* map of [durationBasis](/features/financials/durations) and duration quantity (e.g. `{ "months" : 1 }`)
  * Note: A negative offset schedules the event before the anchor date
* **cadence:** *(optional)* defines the cadence between and max number of occurrences to be scheduled
* **suppressOnStatus:** *(optional)* list of [policy statuses](/features/policy-management/policy-status) that should suppress firing (e.g. `["cancelled" or "expired"]`)

Add scheduled events to the optional `scheduledEvents` array of the <ApiLink name="ProductRef">ProductRef</ApiLink>.

Behavior [#behavior]

Policy-scoped event schedules are created upon issuance of transactions that create a new term, such as new business or renewals, with the exception of `segmentStart`, which may also be scheduled upon issuance of a `change` or `reinstatement` transaction.

An events schedule is controlled based on the provided configuration properties, which work as follows:

* **anchor:** Used to determine where to start the schedule from, i.e. the start of the policy, the term or segment start etc.
* **alignment:** Adjusts the base to the start of a week/month/year relative to the `anchor` selected.
* **offset:** Shifts event date relative to anchor, or realigned anchor if used.
* **cadence:** Creates a recurring event based on a given interval, including a limit on how many times it should recur, if desired. If omitted, the event will only occur once.
* **suppressOnStatus:** Allows control to suppress the event from firing if the policy is in a specific status, such as `cancelled`.

API [#api]

Once scheduled, policy-scoped events can be fetched using the <ApiLink name="fetchScheduledPolicyEvents">Fetch Scheduled Policy Events</ApiLink> API endpoint. This endpoint allows you to retrieve the next scheduled instance of each custom event for a specific policy, including their scheduled dates and types.

<ApiEndpoint name="fetchScheduledPolicyEvents" title="Fetch Scheduled Policy Events" />

<ApiSchema name="ScheduledPolicyEvent" />

Example Use Cases and Configuration [#example-use-cases-and-configuration]

Example #1 - (basic) Single event, some time after policy start [#example-1---basic-single-event-some-time-after-policy-start]

Suppose you want to trigger a one-time customer service survey to be sent to customers 25 days after the policy start date. You can configure a custom event like this:

```json
{
  "customEvents": {
    "CustomerSurvey": {
      "type": "custom.event.type.customerSurvey",
      "schedule": {
        "anchor": "policyStart"
        "offset": {
          "days": 25
        }
      }
    }
  }
}
```

In this case, a policy effective from `2026-01-04` would have the following event(s) scheduled:

| Event Schedule | Event Type                       |
| -------------- | -------------------------------- |
| `2026-10-29`   | custom.event.type.customerSurvey |

Example #2 - (moderate) Recurring event upon every anniversary [#example-2---moderate-recurring-event-upon-every-anniversary]

A 10-year term, where the implementer requires an event each year on the anniversary of the policy effective date.

```json
{
  "customEvents": {
    "Anniversary": {
      "type": "custom.event.type.anniversary",
      "schedule": {
        "anchor": "policyStart"
        "offset": {
          "years": 1
        },
        "cadence": {
          "intervalDuration": 1,
          "durationBasis": "years"
        }
      }
    }
  }
}
```

* The `anchor` is set to `policyStart` so the event will be scheduled from the policy effective date.
* The `offset` is set to one year, so the first event will be scheduled for one year after the policy effective date.
* The `cadence` is set to recur every year, so the event will be scheduled for each anniversary of the policy effective date.

In this case, a policy effective from `2025-05-14` to `2030-05-14` would have the following events scheduled:

| Event Schedule | Event Type                    |
| -------------- | ----------------------------- |
| `2026-05-14`   | custom.event.type.anniversary |
| `2027-05-14`   | custom.event.type.anniversary |
| `2028-05-14`   | custom.event.type.anniversary |
| `2029-05-14`   | custom.event.type.anniversary |
| `2030-05-14`   | custom.event.type.anniversary |

Example #3 - (advanced) Recurring, day of every other month event [#example-3---advanced-recurring-day-of-every-other-month-event]

A 2-year term, where the implementer requires an event on the 5th day of every other month, beginning the 1st full month after the policy is effective, for the first year of the policy.

```json
{
	"customEvents": {
		"Anniversary": {
			"type": "custom.event.type.otherMonthEvent",
			"schedule": {
				"anchor": "policyStart",
				"alignment": "monthStart",
				"offset": {
					"days": 5
				},
				"cadence": {
					"intervalDuration": 2,
					"durationBasis": "months",
					"limit": 6
				}
			}
		}
	}
}
```

In this case, a policy effective from `2026-05-14` to `2028-05-14` would have the following events scheduled:

| Event Schedule | Event Type                        |
| -------------- | --------------------------------- |
| `2026-06-05`   | custom.event.type.otherMonthEvent |
| `2026-08-05`   | custom.event.type.otherMonthEvent |
| `2026-10-05`   | custom.event.type.otherMonthEvent |
| `2026-12-05`   | custom.event.type.otherMonthEvent |
| `2027-02-05`   | custom.event.type.otherMonthEvent |
| `2027-04-05`   | custom.event.type.otherMonthEvent |

<span id="TenantEvents" />

Tenant Events [#tenant-events]

Tenant-scoped custom events are not tied to any specific policy and support tenant-wide activity, accommodating use cases such as:

* Running nightly data synchronization
* Triggering tenant-wide notifications
* Initiating periodic administrative tasks

Unlike policy-scoped events, tenant-scoped events can be <ApiLink name="scheduleTenantEvents">manually triggered (scheduled)</ApiLink> by an API request.

Configuration [#configuration-1]

Tenant-scoped custom scheduled events are configured through the <ApiLink name="TenantCustomEventRef" /> configuration object found at the top level of the <ApiLink name="ConfigurationRef" />.

<ApiSchema name="TenantCustomEventRef" />

* `type` must begin with the prefix `custom` in order to prevent conflicts with internal system events.
* `isPersisted` defaults to `true` and determines whether the event record is stored in the database for later retrieval through the fetch event API endpoints (e.g. <ApiLink name="fetchEvent">single</ApiLink>, <ApiLink name="fetchMultipleEvents">list</ApiLink>)

<ApiSchema name="TenantEventScheduleRef" />

<ApiSchema name="EventCadenceRef" />

Options [#options-1]

* **alignment:** *(required)* `weekStart`, `monthStart`, or `yearStart`
* **offset:** *(optional)* map of [durationBasis](/features/financials/durations) and duration quantity (e.g. `{ "months" : 1 }`)
  * Note: A negative offset schedules the event before the anchor date
* **cadence:** *(required)* defines the cadence between and max number of occurrences to be scheduled

Behavior [#behavior-1]

* **alignment:** Adjusts the base to the start of a week/month/year relative to the `anchor` selected.
* **offset:** Shifts event date relative to the anchor.
* **cadence:** Creates a recurring event based on a given interval, including a limit on how many times it should recur, if desired. If omitted, the event will only occur once.

API [#api-1]

You can manually schedule a tenant-scoped custom event using the <ApiLink name="scheduleTenantEvents" /> API endpoint, supporting the ability to trigger events on-demand from external systems or for ad-hoc administrative tasks.

Use the <ApiLink name="fetchScheduledTenantEvents">Fetch Scheduled Tenant Events</ApiLink> API endpoint to retrieve the next scheduled instance of each custom tenant-scoped event.

<ApiEndpoint name="fetchScheduledTenantEvents" title="Fetch Scheduled Tenant Events" />

<ApiSchema name="ScheduledTenantEvent" />

Sample Request [#sample-request]

```json
{
	"requests": [
		{
			"eventTypeId": "custom.tenant.data_sync",
			"eventTime": "2023-10-27T10:00:00Z",
			"scheduleId": "manual-sync-001",
			"data": {
				"sourceSystem": "externalCRM",
				"forceFullSync": true
			}
		}
	]
}
```

Note that the optional `data` payload allows you to pass information to your event logic.

Examples [#examples]

Example #1 - Manually-Triggered Data Sync Event [#example-1---manually-triggered-data-sync-event]

Suppose a developer needs to create an event that can be called by an external system to initiate a data synchronization process for the tenant.

Here's an example configuration:

```json
"tenantCustomEvents": {
  "tenantDataSync": {
    "type": "custom.tenant.data_sync",
    "isPersisted": false
  }
}
```

No `schedule` is configured since this event will be manually triggered through the <ApiLink name="scheduleTenantEvents" /> API endpoint.

Example #2 - Scheduled Monthly Report Generation [#example-2---scheduled-monthly-report-generation]

For a tenant-wide report to be generated on the first of each month, a developer could configure a tenant event like this:

```json
"tenantCustomEvents": {
  "monthlyReportGenerator": {
    "type": "scheduled.tenant.monthly_report",
    "schedule": {
      "alignment": "monthStart",
      "cadence": {
        "intervalDuration": 1,
        "durationBasis": "months"
      }
    }
  }
}
```

An event listener could be deployed to initiate report production logic.


## API Reference

GET /event/{tenantLocator}/events/schedules/policy/{policyLocator} — fetchScheduledPolicyEvents
Tags: events-controller
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
Responses:
  200 ScheduledPolicyEvent[] — OK

GET /event/{tenantLocator}/events/schedules/tenant — fetchScheduledTenantEvents
Tags: events-controller
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 ScheduledTenantEvent[] — OK

CustomEventRef
Properties:
  type (string, required)
  schedule (EventScheduleRef)

EventScheduleRef
Properties:
  anchor (Enum policyStart | policyEnd | termStart | segmentStart, required)
  alignment (Enum weekStart | monthStart | yearStart)
  offset (map<string, integer>)
  cadence (EventCadenceRef)
  suppressOnStatuses (Enum[])

EventCadenceRef
Properties:
  intervalDuration (integer, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  limit (integer)

ScheduledPolicyEvent
Properties:
  policyLocator (ulid, required)
  transactionLocator (ulid, required)
  customEventId (string, required)
  nextEventTime (datetime)
  triggerState (Enum NONE | NORMAL | PAUSED | COMPLETE | ERROR | BLOCKED, required)

TenantCustomEventRef
Properties:
  type (string, required)
  schedule (TenantEventScheduleRef)
  isPersisted (boolean, required)

TenantEventScheduleRef
Properties:
  alignment (Enum weekStart | monthStart | yearStart)
  offset (map<string, integer>)
  cadence (EventCadenceRef)

ScheduledTenantEvent
Properties:
  scheduledEventId (string, required)
  customEventId (string, required)
  nextEventTime (datetime)
  triggerState (Enum NONE | NORMAL | PAUSED | COMPLETE | ERROR | BLOCKED, required)