# Socotra Documentation



Socotra Insurance Suite is the industry's most powerful insurance platform. Socotra’s open platform emphasizes scaling, flexibility, easy configuration, and the ability to handle complex processes with a fine degree of control and power.

This documentation covers everything you need to build, configure, and integrate with the [Socotra Insurance Suite](https://socotra.com).

<Cards>
  <Card title="Getting Started" href="/docs/getting-started/introduction-to-socotra" description="Log in, create a tenant, configure your first product, and make your first API call." />

  <Card title="Feature Guide" href="/docs/features/business-accounts" description="Policies, billing, claims, security, reporting, and more." />

  <Card title="Configuration Guide" href="/docs/configuration/general-topics/deployment" description="Deploy resources, extend data models, and build custom plugins." />

  <Card title="API Reference" href="/docs/api" description="Fully documented REST endpoints for every surface in the platform." />

  <Card title="AI Guide" href="/docs/ai-guide/mcp-server/overview" description="Use the Socotra MCP Server and Socotra Assistant to integrate with AI." />

  <Card title="Release Notes" href="/docs/other-resources/release-notes" description="Latest platform updates, fixes, and changes across the Socotra Insurance Suite." />
</Cards>


# Accounting API



<EndpointIndex
  names={[
  	'fetchAccountingTransaction',
  	'fetchLedgerAccount',
  	'fetchMultipleLedgerCashAccounts',
  	'fetchTenantLevelCashBalance',
  ]}
  titles={{
  	fetchAccountingTransaction: 'Fetch an Accounting Transaction',
  	fetchLedgerAccount: 'Fetch a Ledger Account',
  }}
/>

Accounting Transactions [#accounting-transactions]

Fetch an Accounting Transaction [#fetch-an-accounting-transaction]

<ApiEndpoint name="fetchAccountingTransaction" title="Fetch an Accounting Transaction" />

<ApiSchema name="AccountingTransactionResponse" />

<ApiSchema name="AccountLineItem" />

Accounting T-Accounts [#accounting-t-accounts]

Fetch a Ledger Account [#fetch-a-ledger-account]

<ApiEndpoint name="fetchLedgerAccount" title="Fetch a Ledger Account" />

<ApiSchema name="LedgerAccountResponse" />

<ApiSchema name="LedgerAccountLineItem" />

Cash Accounts [#cash-accounts]

Cash accounts record inflows and outflows of cash from the system. For example, if a payment is received, the payment itself records the credit, and the customer account's cash t-account records the debit.

Fetch Multiple Ledger Cash Accounts [#fetch-multiple-ledger-cash-accounts]

<ApiEndpoint name="fetchMultipleLedgerCashAccounts" />

<ApiSchema name="LedgerAccountListResponse" />

Fetch Tenant Level Cash Balance [#fetch-tenant-level-cash-balance]

<ApiEndpoint name="fetchTenantLevelCashBalance" />

<ApiSchema name="TenantCashBalance" />


## API Reference

GET /billing/{tenantLocator}/accounting/faTransactions/{locator} — fetchAccountingTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AccountingTransactionResponse — OK

GET /billing/{tenantLocator}/accounting/ledgerAccounts/{refType}/{refLocator} — fetchLedgerAccount
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  refType (Enum accountCreditBalance | invoiceCreditBalance | cash | creditCash | charge | credit | installmentItem | invoiceItem | account | policy | accountExpenseBalance, path, required)
  refLocator (ulid, path, required)
  currency (string, query)
  size (integer, query)
Responses:
  200 LedgerAccountResponse — OK

GET /billing/{tenantLocator}/accounting/ledgerAccounts/cash/list — fetchMultipleLedgerCashAccounts
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  currency (string, query)
  size (integer, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 LedgerAccountListResponse — OK

GET /billing/{tenantLocator}/accounting/ledgerAccounts/cash — fetchTenantLevelCashBalance
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  currency (string, query)
Responses:
  200 TenantCashBalance — OK

AccountingTransactionResponse
Properties:
  faTransactionLocator (ulid, required)
  faTransactionTime (datetime, required)
  faTransactionNote (string, required)
  currency (string, required)
  accountLines (AccountLineItem[], required)

AccountLineItem
Properties:
  accountingType (Enum credit | debit, required)
  referenceType (Enum accountCreditBalance | invoiceCreditBalance | cash | creditCash | charge | credit | installmentItem | invoiceItem | account | policy | accountExpenseBalance, required)
  referenceLocator (ulid, required)
  amount (number, required)

LedgerAccountResponse
Properties:
  referenceLocator (ulid, required)
  referenceType (Enum accountCreditBalance | invoiceCreditBalance | cash | creditCash | charge | credit | installmentItem | invoiceItem | account | policy | accountExpenseBalance, required)
  balance (number, required)
  currency (string, required)
  lineItems (LedgerAccountLineItem[], required)

LedgerAccountLineItem
Properties:
  faTransactionLocator (ulid, required)
  faTransactionTime (datetime, required)
  faTransactionNote (string, required)
  accountingType (Enum credit | debit, required)
  amount (number, required)

LedgerAccountListResponse
Properties:
  listCompleted (boolean, required)
  items (LedgerAccountResponse[], required)

TenantCashBalance
Properties:
  balance (number, required)
  currency (string, required)

# Accounts API



<EndpointIndex
  names={[
  	'fetchAccount',
  	'fetchMultipleAccounts',
  	'createAccount',
  	'updateAccount',
  	'updateAccountReplaceData',
  	'validateAccount',
  	'addAccountContact',
  	'deleteAccountContact',
  	'updateAccountContact',
  	'fetchAccountContacts',
  	'fetchPoliciesForAccount',
  	'fetchQuotesForAccount',
  	'fetchPolicySnapshotsForAnAccount',
  	'updateBillingLevelForAnAccount',
  	'fetchAccountsWithNumber',
  	'setAccountNumber',
  	'generateAccountNumber',
  ]}
  titles={{
  	fetchAccount: 'Fetch an Account',
  	createAccount: 'Create an Account',
  	updateAccountReplaceData: 'Update Account and Replace Data',
  	validateAccount: 'Validate an Account',
  	addAccountContact: 'Add contact',
  	deleteAccountContact: 'Delete contact',
  	updateAccountContact: 'Update contact',
  	fetchAccountContacts: 'Fetch contacts',
  	fetchPoliciesForAccount: 'Fetch Policies for an Account',
  	fetchQuotesForAccount: 'Fetch Quotes for an Account',
  }}
/>

Fetch [#fetch]

Fetch an Account [#fetch-an-account]

<ApiEndpoint name="fetchAccount" title="Fetch an Account" />

<ApiSchema name="AccountResponse" />

Fetch Multiple Accounts [#fetch-multiple-accounts]

<ApiEndpoint name="fetchMultipleAccounts" />

<ApiSchema name="AccountListResponse" />

Account Creation [#account-creation]

Create an Account [#create-an-account]

<ApiEndpoint name="createAccount" title="Create an Account" />

<ApiSchema name="AccountCreateRequest" />

<ApiSchema name="ContactRoles" />

Updating [#updating]

Update Account [#update-account]

<ApiEndpoint name="updateAccount" />

<ApiSchema name="AccountUpdateRequest" />

Update Account and Replace Data [#update-account-and-replace-data]

<ApiEndpoint name="updateAccountReplaceData" title="Update Account and Replace Data" />

<Callout>
  This version of `updateAccount` replaces *all* [extension data](/configuration/data-extensions/overview) for the account, rather than just updating individual properties.
</Callout>

<ApiSchema name="AccountUpdateReplaceDataRequest" />

Validation [#validation]

Validate an Account [#validate-an-account]

<ApiEndpoint name="validateAccount" title="Validate an Account" />

<ApiSchema name="ValidationResult" />

<ApiSchema name="ValidationItemResponse" />

Contact Management [#contact-management]

Add contact [#add-contact]

<ApiEndpoint name="addAccountContact" title="Add contact" />

Delete contact [#delete-contact]

<ApiEndpoint name="deleteAccountContact" title="Delete contact" />

Update contact [#update-contact]

<ApiEndpoint name="updateAccountContact" title="Update contact" />

<ApiSchema name="ContactAssociationUpdateRequest" />

Fetch contacts [#fetch-contacts]

<ApiEndpoint name="fetchAccountContacts" title="Fetch contacts" />

Quotes and Policies [#quotes-and-policies]

Fetch Policies for an Account [#fetch-policies-for-an-account]

<ApiEndpoint name="fetchPoliciesForAccount" title="Fetch Policies for an Account" />

<ApiSchema name="PolicyResponse" />

Fetch Quotes for an Account [#fetch-quotes-for-an-account]

<ApiEndpoint name="fetchQuotesForAccount" title="Fetch Quotes for an Account" />

<ApiSchema name="QuoteResponse" />

Fetch Policy Snapshots For An Account [#fetch-policy-snapshots-for-an-account]

<ApiEndpoint name="fetchPolicySnapshotsForAnAccount" />

<ApiSchema name="PolicySnapshotResponse" />

Holds [#holds]

Fetch All Holds For An Account [#fetch-all-holds-for-an-account]

<ApiEndpoint name="fetchAllHoldsForAnAccount" />

<ApiSchema name="HoldResponse" />

Billing [#billing]

Update Billing Level For An Account [#update-billing-level-for-an-account]

<ApiEndpoint name="updateBillingLevelForAnAccount" />

<ApiSchema name="UpdateBillingLevelRequest" />

Numbering [#numbering]

Fetch Accounts With Number [#fetch-accounts-with-number]

<ApiEndpoint name="fetchAccountsWithNumber" />

Set Account Number [#set-account-number]

<ApiEndpoint name="setAccountNumber" />

Generate Account Number [#generate-account-number]

<ApiEndpoint name="generateAccountNumber" />


## API Reference

GET /policy/{tenantLocator}/accounts/{locator} — fetchAccount
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AccountResponse — OK

GET /policy/{tenantLocator}/accounts/list — fetchMultipleAccounts
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 AccountListResponse — OK

POST /policy/{tenantLocator}/accounts — createAccount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (AccountCreateRequest):
Responses:
  200 AccountResponse — OK

PATCH /policy/{tenantLocator}/accounts/{locator} — updateAccount
Updates the account and individual data extensions.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (AccountUpdateRequest):
Responses:
  200 AccountResponse — OK

PUT /policy/{tenantLocator}/accounts/{locator} — updateAccountReplaceData
Updates the account and replaces all existing data extensions with the new data.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (AccountUpdateReplaceDataRequest):
Responses:
  200 AccountResponse — OK

PATCH /policy/{tenantLocator}/accounts/{locator}/validate — validateAccount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AccountResponse — OK

POST /policy/{tenantLocator}/accounts/{accountLocator}/contacts — addAccountContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
Request body (ContactRoles):
Responses:
  200 AccountResponse — OK

DELETE /policy/{tenantLocator}/accounts/{accountLocator}/contacts/{contactLocator} — deleteAccountContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Responses:
  200 AccountResponse — OK

PATCH /policy/{tenantLocator}/accounts/{accountLocator}/contacts/{contactLocator} — updateAccountContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Request body (ContactAssociationUpdateRequest):
Responses:
  200 AccountResponse — OK

GET /policy/{tenantLocator}/accounts/{accountLocator}/contacts — fetchAccountContacts
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
Responses:
  200 ContactRoles[] — OK

GET /policy/{tenantLocator}/accounts/{locator}/policies/list — fetchPoliciesForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  includeStaticData (boolean, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 PolicyListResponse — OK

GET /policy/{tenantLocator}/accounts/{locator}/quotes/list — fetchQuotesForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  includeStaticData (boolean, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 QuoteListResponse — OK

GET /policy/{tenantLocator}/accounts/{locator}/policies/snapshot/list — fetchPolicySnapshotsForAnAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 PolicySnapshotListResponse — OK

GET /billing/{tenantLocator}/holds/accounts/{accountLocator}/list — fetchAllHoldsForAnAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  state (Enum draft | validated | active | discarded | released, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 HoldListResponse — OK

PATCH /policy/{tenantLocator}/accounts/{locator}/billingLevel — updateBillingLevelForAnAccount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateBillingLevelRequest):
Responses:
  200 AccountResponse — OK

GET /policy/{tenantLocator}/accounts/numbers/{accountNumber} — fetchAccountsWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountNumber (string, path, required)
Responses:
  200 AccountResponse[] — OK

POST /policy/{tenantLocator}/accounts/{locator}/number/set — setAccountNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  accountNumber (string, query, required)
Responses:
  200 AccountResponse — OK

POST /policy/{tenantLocator}/accounts/{locator}/number/generate — generateAccountNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AccountResponse — OK

AccountResponse
Properties:
  locator (ulid, required)
  type (string, required) — One of the configured Account Types
  accountState (Enum draft | validated | discarded, required)
  data (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  delinquencyPlanName (string)
  shortfallTolerancePlanName (string)
  autoRenewalPlanName (string)
  excessCreditPlanName (string)
  preferences (Preferences)
  validationResult (ValidationResult)
  billingLevel (Enum account | inherit | policy, required)
  invoicingPlanName (string)
  region (string)
  invoiceDocument (string)
  timezone (string)
  accountNumber (string, required)
  contacts (ContactRoles[], required)
  anonymizedAt (datetime)
  paymentExecutionRetryPlanName (string)
  state (Enum draft | validated | discarded, required) [deprecated]

AccountListResponse
Properties:
  listCompleted (boolean, required)
  items (AccountResponse[], required)

AccountCreateRequest
Properties:
  type (string, required) — One of the configured Account Types
  autoValidate (boolean)
  data (map<string, object>)
  delinquencyPlanName (string)
  shortfallTolerancePlanName (string)
  autoRenewalPlanName (string)
  excessCreditPlanName (string)
  preferences (Preferences)
  billingLevel (Enum account | inherit | policy)
  region (string)
  invoiceDocument (string)
  timezone (string)
  contacts (ContactRoles[])
  invoicingPlanName (string)
  paymentExecutionRetryPlanName (string)

ContactRoles
Properties:
  contactLocator (ulid, required)
  roles (string[], required)

AccountUpdateRequest
Properties:
  type (string, required) — One of the configured Account Types
  delinquencyPlanName (string, required)
  shortfallTolerancePlanName (string, required)
  autoRenewalPlanName (string, required)
  excessCreditPlanName (string, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  preferences (Preferences, required)
  billingLevel (Enum account | inherit | policy, required)
  invoiceDocument (string, required)
  timezone (string, required)
  invoicingPlanName (string, required)
  paymentExecutionRetryPlanName (string, required)
  autoValidate (boolean, required)

AccountUpdateReplaceDataRequest
Properties:
  type (string, required) — One of the configured Account Types
  autoValidate (boolean)
  data (map<string, object>)
  delinquencyPlanName (string)
  shortfallTolerancePlanName (string)
  autoRenewalPlanName (string)
  excessCreditPlanName (string)
  preferences (Preferences)
  billingLevel (Enum account | inherit | policy)
  region (string)
  invoiceDocument (string)
  timezone (string)
  contacts (ContactRoles[])
  invoicingPlanName (string)
  paymentExecutionRetryPlanName (string)

ValidationResult
Properties:
  validationItems (ValidationItemResponse[])
  success (boolean, required)

ValidationItemResponse
Properties:
  elementType (string, required)
  locator (ulid, required)
  errors (string[], required)

ContactAssociationUpdateRequest
Properties:
  addRoles (string[], required)
  removeRoles (string[], required)

PolicyResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  branchHeadTransactionLocators (ulid[]) — The locators of all the top-level transactions on the policy, one per branch
  issuedTransactionLocator (ulid, required) — The locator of the latest issued transaction for the policy.
  productName (string, required)
  timezone (string, required)
  currency (string, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  startTime (datetime, required) — The start time, based on issued transactions only
  endTime (datetime, required) — The end time based on issued transactions only.
  latestTermLocator (ulid, required)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  policyNumber (string)
  latestSegmentLocator (ulid, required) — The last segment on the policy, based on issued transactions only
  contacts (ContactRoles[], required)
  statuses (Enum[], required)
  invoiceFeeAmount (number)
  anonymizedAt (datetime)
  coverageEndTime (datetime)
  moratoriumElections (map<string, string>, required)
  jurisdiction (string)
  producerCode (string)
  producerCodeOfRecord (string)
  proxyPayerLocator (ulid)
  static (map<string, object>, required)
  validationResult (ValidationResult)

QuoteResponse
Properties:
  locator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  productName (string, required)
  accountLocator (ulid, required)
  startTime (datetime)
  endTime (datetime)
  timezone (string)
  currency (string)
  underwritingStatus (string)
  expirationTime (datetime)
  element (ElementResponse, required) — The root element in the hierarchy
  preferences (Preferences) — Plan selections and setting overrides
  policyLocator (ulid)
  delinquencyPlanName (string)
  durationBasis (Enum years | months | weeks | days | hours)
  groupLocator (ulid)
  autoRenewalPlanName (string)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  quoteNumber (string)
  duration (number) — The duration of the prospective policy in units of durationBasis
  acceptedTime (datetime)
  issuedTime (datetime)
  validationResult (ValidationResult)
  quickQuoteLocator (ulid)
  contacts (ContactRoles[], required)
  anonymizedAt (datetime)
  invoiceFeeAmount (number)
  createdBy (uuid)
  createdAt (datetime)
  jurisdiction (string)
  producerCode (string)
  reservedPolicyNumber (string)
  proxyPayerLocator (ulid)
  static (map<string, object>)
  policyNumber (string)

PolicySnapshotResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  productName (string, required)
  timezone (string, required)
  currency (string, required)
  region (string, required)
  transaction (TransactionSnapshotResponse, required)
  delinquencyPlanName (string)
  static (map<string, object>, required)

HoldResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  targetType (Enum invoicing | delinquency, required)
  holdState (Enum draft | validated | active | discarded | released, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  validationResult (ValidationResult)

UpdateBillingLevelRequest
Properties:
  billingLevel (Enum account | inherit | policy, required)

# First Notice of Loss ("FNOL") API



<EndpointIndex
  names={[
  	'addFnol',
  	'validate',
  	'complete',
  	'discard',
  	'reject',
  	'patchFnol',
  	'createClaim',
  	'getFnol',
  	'getFnolByNumber',
  	'getFnolClaimLocators',
  	'listFnol',
  	'listFnolsByPolicyLocator',
  	'listFnolHistory',
  	'setFnolNumber',
  	'generateFnolNumber',
  	'addFnolContact',
  	'deleteFnolContact',
  	'updateFnolContact',
  	'addLosses',
  	'checkLosses',
  	'deleteLosses',
  	'excludeLoss',
  	'includeLoss',
  	'updateLoss',
  	'resetLoss',
  	'fetchClaimEventDefinitions',
  ]}
  titles={{
  	addFnol: 'Create FNOL',
  	validate: 'Validate FNOL',
  	complete: 'Complete FNOL',
  	discard: 'Discard FNOL',
  	reject: 'Reject FNOL',
  	patchFnol: 'Update FNOL',
  	createClaim: 'Create claim from FNOL',
  	getFnol: 'Get FNOL',
  	getFnolByNumber: 'Get FNOL by number',
  	getFnolClaimLocators: 'Get FNOL claim locators',
  	listFnol: 'List FNOLs',
  	listFnolsByPolicyLocator: 'List FNOLs by policy locator',
  	listFnolHistory: 'List FNOL History',
  	setFnolNumber: 'Set FNOL number',
  	generateFnolNumber: 'Generate FNOL number',
  	addFnolContact: 'Add FNOL contact',
  	deleteFnolContact: 'Delete FNOL contact',
  	updateFnolContact: 'Update FNOL contact',
  	addLosses: 'Add losses',
  	checkLosses: 'Check losses',
  	deleteLosses: 'Delete losses',
  	excludeLoss: 'Exclude loss',
  	includeLoss: 'Include loss',
  	updateLoss: 'Update loss',
  	resetLoss: 'Reset loss',
  	fetchClaimEventDefinitions: 'List events',
  }}
/>

Fundamental Operations [#fundamental-operations]

Create FNOL [#create-fnol]

<ApiEndpoint name="addFnol" title="Create FNOL" />

<ApiSchema name="FnolCreateRequest" />

<ApiSchema name="FnolResponse" />

Validate FNOL [#validate-fnol]

<ApiEndpoint name="validate" title="Validate FNOL" />

Complete FNOL [#complete-fnol]

<ApiEndpoint name="complete" title="Complete FNOL" />

Discard FNOL [#discard-fnol]

<ApiEndpoint name="discard" title="Discard FNOL" />

Reject FNOL [#reject-fnol]

<ApiEndpoint name="reject" title="Reject FNOL" />

Update FNOL [#update-fnol]

<ApiEndpoint name="patchFnol" title="Update FNOL" />

<ApiSchema name="FnolPatchRequest" />

Create claim from FNOL [#create-claim-from-fnol]

<ApiEndpoint name="createClaim" title="Create claim from FNOL" />

Data Fetch [#data-fetch]

Get FNOL [#get-fnol]

<ApiEndpoint name="getFnol" title="Get FNOL" />

Get FNOL by number [#get-fnol-by-number]

<ApiEndpoint name="getFnolByNumber" title="Get FNOL by number" />

Get FNOL claim locators [#get-fnol-claim-locators]

<ApiEndpoint name="getFnolClaimLocators" title="Get FNOL claim locators" />

List FNOLs [#list-fnols]

<ApiEndpoint name="listFnol" title="List FNOLs" />

List FNOLs by policy locator [#list-fnols-by-policy-locator]

<ApiEndpoint name="listFnolsByPolicyLocator" title="List FNOLs by policy locator" />

<ApiSchema name="ListPageResponseFnolResponse" />

List FNOL History [#list-fnol-history]

<ApiEndpoint name="listFnolHistory" title="List FNOL History" />

Numbering [#numbering]

Set FNOL number [#set-fnol-number]

<ApiEndpoint name="setFnolNumber" title="Set FNOL number" />

Generate FNOL number [#generate-fnol-number]

<ApiEndpoint name="generateFnolNumber" title="Generate FNOL number" />

Contacts [#contacts]

Add FNOL contact [#add-fnol-contact]

<ApiEndpoint name="addFnolContact" title="Add FNOL contact" />

<ApiSchema name="ContactRoles" />

Delete FNOL contact [#delete-fnol-contact]

<ApiEndpoint name="deleteFnolContact" title="Delete FNOL contact" />

Update FNOL contact [#update-fnol-contact]

<ApiEndpoint name="updateFnolContact" title="Update FNOL contact" />

Loss Management [#loss-management]

Add losses [#add-losses]

<ApiEndpoint name="addLosses" title="Add losses" />

Check losses [#check-losses]

<ApiEndpoint name="checkLosses" title="Check losses" />

Delete losses [#delete-losses]

<ApiEndpoint name="deleteLosses" title="Delete losses" />

Exclude loss [#exclude-loss]

<ApiEndpoint name="excludeLoss" title="Exclude loss" />

<ApiSchema name="FnolLoss" />

Include loss [#include-loss]

<ApiEndpoint name="includeLoss" title="Include loss" />

Update loss [#update-loss]

<ApiEndpoint name="updateLoss" title="Update loss" />

<ApiSchema name="FnolLossPatchRequest" />

Reset loss [#reset-loss]

<ApiEndpoint name="resetLoss" title="Reset loss" />

Events [#events]

{/* TODO: "fetchClaimEventDefinitions" not found in OpenAPI spec */}

<span id="fetchClaimEventDefinitions" />

List events [#list-events]

<ApiSchema name="ClaimServiceEventTypeDefinitions" />

See Also [#see-also]

* [First Notice of Loss Feature Guide](/features/claims/fnol)
* [FNOL Coverage Checks](/features/claims/coverage-checks)


## API Reference

POST /claim/{tenantLocator}/fnols — addFnol
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (FnolCreateRequest):
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator}/validate — validate
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator}/complete — complete
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator}/discard — discard
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator}/reject — reject
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator} — patchFnol
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (FnolPatchRequest):
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator}/createClaim — createClaim
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  markAsComplete (boolean, query)
Responses:
  200 — OK

GET /claim/{tenantLocator}/fnols/{locator} — getFnol
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /claim/{tenantLocator}/fnols/number/{number} — getFnolByNumber
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  number (string, path, required)
Responses:
  200 — OK

GET /claim/{tenantLocator}/fnols/{locator}/claims — getFnolClaimLocators
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /claim/{tenantLocator}/fnols/list — listFnol
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /claim/{tenantLocator}/fnols/policy/{policyLocator}/list — listFnolsByPolicyLocator
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /claim/{tenantLocator}/fnols/{locator}/history/list — listFnolHistory
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

POST /claim/{tenantLocator}/fnols/{locator}/number/set — setFnolNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  fnolNumber (string, query, required)
Responses:
  200 — OK

POST /claim/{tenantLocator}/fnols/{locator}/number/generate — generateFnolNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /claim/{tenantLocator}/fnols/{fnolLocator}/contacts — addFnolContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
Request body (ContactRoles):
Responses:
  200 — OK

DELETE /claim/{tenantLocator}/fnols/{fnolLocator}/contacts/{contactLocator} — deleteFnolContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{fnolLocator}/contacts/{contactLocator} — updateFnolContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Request body (ContactAssociationUpdateRequest):
Responses:
  200 — OK

PUT /claim/{tenantLocator}/fnols/{locator}/losses — addLosses
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (FnolLoss[]):
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{locator}/losses/coverageCheck — checkLosses
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

DELETE /claim/{tenantLocator}/fnols/{locator}/losses — deleteLosses
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{fnolLocator}/losses/{lossLocator}/exclude — excludeLoss
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
  lossLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{fnolLocator}/losses/{lossLocator}/include — includeLoss
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
  lossLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{fnolLocator}/losses/{lossLocator} — updateLoss
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
  lossLocator (ulid, path, required)
Request body (FnolLossPatchRequest):
Responses:
  200 — OK

PATCH /claim/{tenantLocator}/fnols/{fnolLocator}/losses/{lossLocator}/reset — resetLoss
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  fnolLocator (ulid, path, required)
  lossLocator (ulid, path, required)
Responses:
  200 — OK

FnolCreateRequest
Properties:
  type (string, required)
  data (map<string, object>, required)
  losses (FnolLoss[], required)
  accountLocator (ulid)
  policyLocator (ulid)
  incidentTime (datetime)
  incidentTimezone (string)
  incidentSummary (string)
  region (string)
  contacts (ContactRoles[], required)
  autoValidate (boolean, required)

FnolResponse
Properties:
  locator (ulid, required)
  type (string, required)
  data (map<string, object>, required)
  fnolState (Enum draft | validated | onClaim | completed | rejected | discarded, required)
  losses (FnolLoss[], required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid)
  policyLocator (ulid)
  segmentLocator (ulid)
  incidentTime (datetime)
  incidentTimezone (string)
  incidentSummary (string)
  region (string)
  fnolNumber (string)
  updatedAt (datetime)
  updatedBy (uuid)
  validationResult (ValidationResult)
  claims (ulid[], required)
  contacts (ContactRoles[], required)
  anonymizedAt (datetime)

FnolPatchRequest
Properties:
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  incidentTime (datetime)
  incidentTimezone (string)
  incidentSummary (string)
  region (string)
  accountLocator (ulid)
  policyLocator (ulid)

ListPageResponseFnolResponse
Properties:
  listCompleted (boolean, required)
  items (FnolResponse[], required)

ContactRoles
Properties:
  contactLocator (ulid, required)
  roles (string[], required)

FnolLoss
Properties:
  locator (ulid, required)
  type (string, required)
  category (string, required)
  fnolLossState (Enum pending | valid | excluded, required)
  exposureElementLocator (ulid)
  coverageElementLocator (ulid)
  data (map<string, object>, required)
  validationResult (ValidationResult)
  anonymizedAt (datetime)

FnolLossPatchRequest
Properties:
  type (string)
  fnolLossState (Enum pending | valid | excluded)
  exposureElementLocator (ulid)
  coverageElementLocator (ulid)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ClaimServiceEventTypeDefinitions
Properties:
  fnolEvents (FnolEvents, required)

# Contacts API



<EndpointIndex
  names={[
  	'addContact',
  	'getContact',
  	'lookupContact',
  	'listContacts',
  	'updateContact',
  	'validateContact',
  	'mergeContacts',
  ]}
  titles={{
  	addContact: 'Create contact',
  	getContact: 'Fetch contact',
  	lookupContact: 'Lookup contact',
  	listContacts: 'List contacts',
  	updateContact: 'Update contact',
  	validateContact: 'Validate contact',
  	mergeContacts: 'Merge contacts',
  }}
/>

Create contact [#create-contact]

<ApiEndpoint name="addContact" title="Create contact" />

<ApiSchema name="ContactCreateRequest" />

<ApiSchema name="Contact" />

Fetch contact [#fetch-contact]

<ApiEndpoint name="getContact" title="Fetch contact" />

Lookup contact [#lookup-contact]

<ApiEndpoint name="lookupContact" title="Lookup contact" />

List contacts [#list-contacts]

<ApiEndpoint name="listContacts" title="List contacts" />

<ApiSchema name="ListPageResponseContact" />

Update contact [#update-contact]

<ApiEndpoint name="updateContact" title="Update contact" />

<ApiSchema name="ContactUpdateRequest" />

Validate contact [#validate-contact]

<ApiEndpoint name="validateContact" title="Validate contact" />

Merge contacts [#merge-contacts]

<ApiEndpoint name="mergeContacts" title="Merge contacts" />

<ApiSchema name="ContactsMergeRequest" />


## API Reference

POST /contact/{tenantLocator}/contacts — addContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (ContactCreateRequest):
Responses:
  200 — OK

GET /contact/{tenantLocator}/contacts/{locator} — getContact
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /contact/{tenantLocator}/contacts/lookup/{locator} — lookupContact
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /contact/{tenantLocator}/contacts/{staticLocator}/list — listContacts
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  staticLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

PATCH /contact/{tenantLocator}/contacts/{locator} — updateContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ContactUpdateRequest):
Responses:
  200 — OK

PATCH /contact/{tenantLocator}/contacts/{locator}/validate — validateContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /contact/{tenantLocator}/contacts/merge — mergeContacts
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (ContactsMergeRequest):
Responses:
  200 — OK

ContactCreateRequest
Properties:
  type (string, required)
  region (string)
  data (map<string, object>, required)
  autoValidate (boolean, required)

Contact
Properties:
  locator (ulid, required)
  staticLocator (ulid, required)
  contactState (Enum draft | validated | discarded, required)
  type (string, required)
  data (map<string, object>, required)
  region (string)
  createdAt (datetime, required)
  createdBy (uuid, required)
  updatedAt (datetime)
  updatedBy (uuid)
  validationResult (ValidationResult)
  anonymizedAt (datetime)

ListPageResponseContact
Properties:
  listCompleted (boolean, required)
  items (Contact[], required)

ContactUpdateRequest
Properties:
  type (string)
  region (string)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ContactsMergeRequest
Properties:
  contactLocators (ulid[], required)
  mergeToContact (ulid, required)

# Documents API



<EndpointIndex
  names={[
  	'fetchDocument',
  	'fetchDocumentResource',
  	'fetchSourceForDocument',
  	'fetchDocumentsForTerm',
  	'fetchDocumentsForSegment',
  	'fetchDocumentsForTransaction',
  	'fetchDocumentsForQuote',
  	'fetchInvoiceDocument',
  	'copyDocumentsOnIssue',
  	'attachDocument',
  	'replaceDocument',
  	'deleteDocument',
  	'renderDocument',
  	'softRemoveDocument',
  ]}
  titles={{
  	fetchDocument: 'Fetch a Document instance',
  	fetchDocumentResource: 'Fetch the Rendered artifact for a Document',
  	fetchSourceForDocument: 'Fetch the Source for a Document',
  	fetchDocumentsForTerm: 'Fetch Documents for a Policy Term',
  	fetchDocumentsForSegment: 'Fetch Documents for a Policy Segment',
  	fetchDocumentsForTransaction: 'Fetch Documents for a Policy Transaction',
  	fetchDocumentsForQuote: 'Fetch Documents for a Quote',
  	fetchInvoiceDocument: 'Fetch Document for an Invoice',
  	softRemoveDocument: 'Soft-Delete a Document',
  }}
/>

Fetch [#fetch]

Fetch a Document instance [#fetch-a-document-instance]

<ApiEndpoint name="fetchDocument" title="Fetch a Document instance" />

<ApiSchema name="DocumentInstanceResponse" />

Fetch the Rendered artifact for a Document [#fetch-the-rendered-artifact-for-a-document]

<ApiEndpoint name="fetchDocumentResource" title="Fetch the Rendered artifact for a Document" />

Fetch the Source for a Document [#fetch-the-source-for-a-document]

<ApiEndpoint name="fetchSourceForDocument" title="Fetch the Source for a Document" />

Fetch Documents for a Policy Term [#fetch-documents-for-a-policy-term]

<ApiEndpoint name="fetchDocumentsForTerm" title="Fetch Documents for a Policy Term" />

Fetch Documents for a Policy Segment [#fetch-documents-for-a-policy-segment]

<ApiEndpoint name="fetchDocumentsForSegment" title="Fetch Documents for a Policy Segment" />

Fetch Documents for a Policy Transaction [#fetch-documents-for-a-policy-transaction]

<ApiEndpoint name="fetchDocumentsForTransaction" title="Fetch Documents for a Policy Transaction" />

Fetch Documents for a Quote [#fetch-documents-for-a-quote]

<ApiEndpoint name="fetchDocumentsForQuote" title="Fetch Documents for a Quote" />

<ApiSchema name="DocumentListResponse" />

Fetch Document for an Invoice [#fetch-document-for-an-invoice]

<ApiEndpoint name="fetchInvoiceDocument" title="Fetch Document for an Invoice" />

Copy [#copy]

Copy Documents On Issue [#copy-documents-on-issue]

<ApiEndpoint name="copyDocumentsOnIssue" />

Modification [#modification]

Attach Document [#attach-document]

<ApiEndpoint name="attachDocument" />

<Callout>
  In the request, the key name for the file content should be `document`.

  If `referenceType` is `policy`, either a `transactionLocator` or `segmentLocator` must be supplied.
</Callout>

Replace Document [#replace-document]

<ApiEndpoint name="replaceDocument" />

Delete Document [#delete-document]

<ApiEndpoint name="deleteDocument" />

Soft-Delete a Document [#soft-delete-a-document]

<ApiEndpoint name="softRemoveDocument" />

Ad-hoc Rendering [#ad-hoc-rendering]

Render Document [#render-document]

<ApiEndpoint name="renderDocument" />

See Also [#see-also]

* [Documents Configuration Guide](/configuration/resources/documents)
* [Document Resources API](/api/resources/document-resources)


## API Reference

GET /document/{tenantLocator}/documents/{locator} — fetchDocument
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /document/{tenantLocator}/documents/{locator}/document — fetchDocumentResource
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /document/{tenantLocator}/documents/{locator}/source — fetchSourceForDocument
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /document/{tenantLocator}/documents/policy/{policyLocator}/term/{termLocator}/summary — fetchDocumentsForTerm
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  termLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

GET /document/{tenantLocator}/documents/segment/{locator}/list — fetchDocumentsForSegment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

GET /document/{tenantLocator}/documents/transaction/{locator}/list — fetchDocumentsForTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

GET /document/{tenantLocator}/documents/quote/{locator}/list — fetchDocumentsForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

GET /document/{tenantLocator}/documents/invoices/{locator} — fetchInvoiceDocument
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/quote/{locator}/copyOnIssue — copyDocumentsOnIssue
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  deleteAllDocuments (boolean, query)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/attach — attachDocument
Permissions: upload-external
Parameters:
  tenantLocator (uuid, path, required)
  referenceLocator (ulid, query, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, query, required)
  name (string, query, required)
  staticName (string, query)
  documentFormat (Enum csv | doc | docx | eml | html | jpeg | jpg | msg | pdf | text | txt | xls | xlsx | zip, query, required)
  metadata (string, query)
  transactionLocator (ulid, query)
  segmentLocator (ulid, query)
  category (string, query)
  copyOnIssuance (boolean, query)
Responses:
  200 — OK

PATCH /document/{tenantLocator}/documents/{locator} — replaceDocument
Permissions: replace-external
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  metadata (string, query)
  category (string, query)
Responses:
  200 — OK

DELETE /document/{tenantLocator}/documents/{locator} — deleteDocument
Permissions: delete-external
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /document/{tenantLocator}/documents/{locator}/softRemove — softRemoveDocument
Permissions: soft-remove
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/render — renderDocument
Permissions: render-external
Parameters:
  tenantLocator (uuid, path, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, query, required)
  referenceLocator (ulid, query, required)
  productName (string, query)
  templateFormat (Enum liquid | velocity, query)
  documentConfig (string, query)
  staticName (string, query)
  templateName (string, query)
Responses:
  200 — OK

DocumentInstanceResponse
Properties:
  locator (ulid, required)
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  referenceDocumentLocator (ulid)
  transactionLocator (ulid)
  segmentLocator (ulid)
  termLocator (ulid)
  policyLocator (ulid)
  name (string)
  staticName (string)
  documentInstanceState (Enum draft | dataReady | ready | dataError | renderError | conversionError | rendered | removed, required)
  documentFormat (Enum csv | doc | docx | html | jpeg | jpg | pdf | text | txt | xls | xlsx | zip, required)
  metadata (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid)
  readyAt (datetime)
  renderingData (map<string, object>, required)
  processingErrors (string)
  external (boolean, required)
  category (string)
  consolidatedFrom (ulid[], required)
  consolidatedTo (ulid[], required)
  copyOnIssuance (boolean)

DocumentListResponse
Properties:
  listCompleted (boolean, required)
  items (DocumentInstanceResponse[], required)

# Overview



The Socotra API exposes all platform functionality and follows common conventions for resource interaction. Endpoints and types are described in a uniform manner on each API page.

While it is possible to use the [OpenAPI Definition File](/other-resources/open-api-specification) as a source for auto-generated API clients, we recommend using the file primarily as a parsable, comprehensive index of the entire API surface. You may need to tweak clients automatically generated from the OpenAPI definition.

List Endpoints [#list-endpoints]

List endpoints, such as the <ApiLink name="fetchMultipleAccounts" /> API endpoint, follow consistent pagination conventions, allowing you to specify the number of items per page and offsets to navigate the list.

When fetching an entire collection from a list endpoint, you should continue fetching pages until the `listComplete` property returns `true`. Due to features such as [Data Access Controls](/features/security/data-access-controls) and various other factors, the platform may not provide the requester with all possible items in the collection. Therefore, `listComplete: false` should not be interpreted to mean that the requester can always obtain more items on subsequent fetches. The platform will consistently provide `listComplete: true` as a signal to the requester that no additional items can be obtained beyond that page (offset and count).

Here is a JavaScript example of a looping technique that retrieves a complete collection from a list endpoint:

```javascript
// Omitting auth for simplicity
const API_URL = 'https://...';
const tenantLocator = 'abc...';

let offset = 0;
const count = 100; // Page size
const allItems = [];

let listCompleted = false;

do {
	const url = new URL(`/policy/${tenantLocator}/accounts/list`, API_URL);
	url.search = new URLSearchParams({
		count,
		offset,
		extended: true,
	});

	const response = await fetch(url);

	if (!response.ok) {
		throw new Error(`Request failed: ${response.status}`);
	}

	const page = await response.json();

	allItems.push(...page.items);
	listCompleted = page.listCompleted;
	offset += count;
} while (!listCompleted);
```

Additional Notes [#additional-notes]

* When an endpoint request completes successfully, it will return a `200` status, even if the response is the platform informing you of some kind of error. In this fashion, we distinguish between the platform domain and any abnormal results concerning HTTP requests themselves.
* By default, any collection in a request is optional unless particular usage necessitates the provision of a collection (in which case, the platform will return a response to indicate that). If a collection is listed as `required` but you have no apparent need to provide any values for the collection, it is always safe to provide an empty collection, which the platform will ignore.


# Migration API



<EndpointIndex
  names={[
  	'startMigration',
  	'startMigrationForAccount',
  	'resumeMigration',
  	'recoverMigration',
  	'pauseMigration',
  	'patchMigration',
  	'getMigrationSummary',
  	'getMigrationMappings',
  	'getMigrationMappingsForAccount',
  	'getAccountMigrations',
  	'listAccountMigrations',
  	'getMigrationFailures',
  ]}
  titles={{
  	startMigration: 'Start Migration',
  	startMigrationForAccount: 'Start Migrations for an Existing Account',
  	resumeMigration: 'Resume a Paused Migration',
  	recoverMigration: 'Attempt to Recover System Error Items for a Migration',
  	pauseMigration: 'Pause a Running Migration',
  	patchMigration: 'Patch an Existing Migration Request',
  	getMigrationSummary: 'Get Migration Summary',
  	getMigrationMappings: 'Get Migration Mappings',
  	getMigrationMappingsForAccount: 'Get Migration Mappings for Account',
  	getAccountMigrations: 'Get Account Migrations',
  	listAccountMigrations: 'List Account Migrations',
  	getMigrationFailures: 'Get Migration Failures',
  }}
/>

Migration Management [#migration-management]

Start Migration [#start-migration]

<ApiEndpoint name="startMigration" title="Start Migration" />

<Callout>
  See the [migration](/features/migration#idempotency-key-guide) feature guide for more information on idempotency keys.
</Callout>

<ApiSchema name="AccountMigrationRequest" />

<ApiSchema name="PolicyMigrationRequest" />

<ApiSchema name="MigrationPreferences" />

<ApiSchema name="MigrationInstallmentPreferences" />

<ApiSchema name="AuxDataMigrationRequest" />

<ApiSchema name="AuxDataEntryMigrationRequest" />

<ApiSchema name="TransactionMigrationRequest" />

<ApiSchema name="PaymentMigrationRequest" />

<ApiSchema name="AccountMigrationData" />

<ApiSchema name="AccountingMigrationRequest" />

<ApiSchema name="InvoiceMigrationRequest" />

<ApiSchema name="DisbursementMigrationRequest" />

<ApiSchema name="CreditItemMigrationRequest" />

<ApiSchema name="PaymentItemMigrationRequest" />

<ApiSchema name="SegmentMigrationRequest" />

<ApiSchema name="InstallmentMigrationRequest" />

<ApiSchema name="InstallmentItemMigrationRequest" />

<ApiSchema name="ElementMigrationRequest" />

<ApiSchema name="ChargeMigrationRequest" />

<ApiSchema name="TermMigrationRequest" />

<ApiSchema name="MigrationResponse" />

<ApiSchema name="ErrorDetailsResponse" />

Start Migrations for an Existing Account [#start-migrations-for-an-existing-account]

<ApiEndpoint name="startMigrationForAccount" title="Start Migrations for an Existing Account" />

<ApiSchema name="MigrationRequest" />

Resume a Paused Migration [#resume-a-paused-migration]

<ApiEndpoint name="resumeMigration" title="Resume a Paused Migration" />

Attempt to Recover System Error Items for a Migration [#attempt-to-recover-system-error-items-for-a-migration]

<ApiEndpoint name="recoverMigration" title="Attempt to Recover System Error Items for a Migration" />

Pause a Running Migration [#pause-a-running-migration]

<ApiEndpoint name="pauseMigration" title="Pause a Running Migration" />

<Callout>
  In-flight transactions will be completed before the migration pauses.
</Callout>

Patch an Existing Migration Request [#patch-an-existing-migration-request]

<ApiEndpoint name="patchMigration" title="Patch an Existing Migration Request" />

<ApiSchema name="PatchAccountMigrationRequest" />

<ApiSchema name="MigrationFailuresResponse" />

Migration Information [#migration-information]

Get Migration Summary [#get-migration-summary]

<ApiEndpoint name="getMigrationSummary" title="Get Migration Summary" />

Get Migration Mappings [#get-migration-mappings]

<ApiEndpoint name="getMigrationMappings" title="Get Migration Mappings" />

<ApiSchema name="AccountMigrationIdMappingsListResponse" />

<ApiSchema name="ListPageResponseAccountMigrationIdMappings" />

<ApiSchema name="AccountMigrationIdMappingsResponse" />

<ApiSchema name="MappingObject" />

Get Migration Mappings for Account [#get-migration-mappings-for-account]

<ApiEndpoint name="getMigrationMappingsForAccount" title="Get Migration Mappings for Account" />

Get Account Migrations [#get-account-migrations]

<ApiEndpoint name="getAccountMigrations" title="Get Account Migrations" />

<ApiSchema name="AccountMigrationResponse" />

List Account Migrations [#list-account-migrations]

<ApiEndpoint name="listAccountMigrations" title="List Account Migrations" />

<ApiSchema name="ListPageResponseAccountMigrationResponse" />

Get Migration Failures [#get-migration-failures]

<ApiEndpoint name="getMigrationFailures" title="Get Migration Failures" />

<ApiSchema name="ListPageResponseMigrationFailuresResponse" />


## API Reference

POST /migration/{tenantLocator}/migrations — startMigration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  X-Idempotency-Key (string, header)
Request body (AccountMigrationRequest[]):
Responses:
  200 — OK

POST /migration/{tenantLocator}/migrations/accounts/{accountLocator} — startMigrationForAccount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  X-Idempotency-Key (string, header)
Request body (MigrationRequest):
Responses:
  200 — OK

PATCH /migration/{tenantLocator}/migrations/{migrationLocator}/resume — resumeMigration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /migration/{tenantLocator}/migrations/{migrationLocator}/recover — recoverMigration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /migration/{tenantLocator}/migrations/{migrationLocator}/pause — pauseMigration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /migration/{tenantLocator}/migrations/{migrationLocator} — patchMigration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
Request body (PatchAccountMigrationRequest):
Responses:
  200 — OK

GET /migration/{tenantLocator}/migrations/{migrationLocator} — getMigrationSummary
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
Responses:
  200 — OK

GET /migration/{tenantLocator}/migrations/{migrationLocator}/mappings/list — getMigrationMappings
Returns per-account mappings of system locators to original IDs
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /migration/{tenantLocator}/migrations/{migrationLocator}/accounts/{accountLocator}/mappings — getMigrationMappingsForAccount
Fetches mappings of original IDs to system locators for an account
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
  accountLocator (ulid, path, required)
Responses:
  200 — OK

GET /migration/{tenantLocator}/migrations/{migrationLocator}/accounts/{accountLocator} — getAccountMigrations
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
  accountLocator (ulid, path, required)
Responses:
  200 — OK

GET /migration/{tenantLocator}/migrations/{migrationLocator}/accounts/list — listAccountMigrations
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /migration/{tenantLocator}/migrations/{migrationLocator}/failures/list — getMigrationFailures
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  migrationLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

AccountMigrationRequest
Properties:
  defaultCreatedBy (uuid, required)
  accountData (AccountMigrationData, required)
  policies (PolicyMigrationRequest[], required)
  invoices (InvoiceMigrationRequest[], required)
  payments (PaymentMigrationRequest[], required)
  disbursements (DisbursementMigrationRequest[], required)
  accounting (AccountingMigrationRequest, required)

PolicyMigrationRequest
Properties:
  createdBy (uuid, required)
  createdAt (datetime, required)
  id (string, required)
  productName (string, required)
  timezone (string)
  currency (string)
  durationBasis (Enum years | months | weeks | days | hours, required)
  staticData (map<string, object>, required)
  terms (TermMigrationRequest[], required)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  preferences (MigrationPreferences) [deprecated]
  billingLevel (Enum account | inherit | policy)
  auxData (AuxDataMigrationRequest)

MigrationPreferences
Properties:
  installmentPreferences (MigrationInstallmentPreferences)

MigrationInstallmentPreferences
Properties:
  cadence (Enum none | fullPay | weekly | everyOtherWeek | monthly | quarterly | semiannually | annually | thirtyDays | everyNDays)
  anchorMode (Enum generateDay | termStartDay | dueDay)
  generateLeadDays (integer)
  dueLeadDays (integer)
  installmentWeights (number[], required)
  maxInstallmentsPerTerm (integer)
  installmentPlanName (string)
  anchorType (Enum none | dayOfMonth | anchorTime | dayOfWeek | weekOfMonth)
  dayOfMonth (integer)
  dayOfWeek (Enum monday | tuesday | wednesday | thursday | friday | saturday | sunday)
  weekOfMonth (Enum none | first | second | third | fourth | fifth)
  anchorTime (datetime)
  autopayLeadDays (number)

AuxDataMigrationRequest
Properties:
  entries (AuxDataEntryMigrationRequest[], required)
  settingsName (string, required)

AuxDataEntryMigrationRequest
Properties:
  key (string, required)
  value (string, required)

TransactionMigrationRequest
Properties:
  transactionType (string, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  issuedTime (datetime, required)
  segment (SegmentMigrationRequest)
  installments (InstallmentMigrationRequest[], required)
  preferences (MigrationPreferences)

PaymentMigrationRequest
Properties:
  createdBy (uuid)
  id (string, required)
  paymentTime (datetime, required)
  paymentItems (PaymentItemMigrationRequest[], required)
  paymentType (string, required)
  data (map<string, object>, required)
  currency (string)

AccountMigrationData
Properties:
  id (string, required)
  accountType (string, required)
  data (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  excessCreditPlanName (string)
  shortfallTolerancePlanName (string)
  preferences (MigrationPreferences)
  billingLevel (Enum account | inherit | policy)

AccountingMigrationRequest
Properties:
  originalAccountBalances (map<string, number>, required) — Key is a currency code (e.g. USD)

InvoiceMigrationRequest
Properties:
  id (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  generateTime (datetime, required)
  dueTime (datetime, required)
  currency (string)
  timezone (string)
  invoiceState (Enum building | open | settled | discarded)

DisbursementMigrationRequest
Properties:
  id (string, required)
  disbursementType (string, required)
  data (map<string, object>, required)
  disbursementTime (datetime, required)
  sources (CreditItemMigrationRequest[], required)
  currency (string)

CreditItemMigrationRequest
Properties:
  amount (number, required)

PaymentItemMigrationRequest
Properties:
  amount (number, required)
  invoiceId (string, required)

SegmentMigrationRequest
Properties:
  startTime (datetime, required)
  rootElement (ElementMigrationRequest, required)
  segmentType (Enum coverage | gap, required)

InstallmentMigrationRequest
Properties:
  id (string, required)
  invoiceId (string, required)
  startTime (datetime, required)
  generateTime (datetime, required)
  dueTime (datetime, required)

InstallmentItemMigrationRequest
Properties:
  id (string, required)
  amount (number, required)
  installmentNumber (integer, required)

ElementMigrationRequest
Properties:
  id (string, required)
  elementType (string, required)
  data (map<string, object>, required)
  coverageTerms (map<string, object>, required)
  elements (ElementMigrationRequest[], required)
  charges (ChargeMigrationRequest[], required)

ChargeMigrationRequest
Properties:
  rate (number, required)
  referenceRate (number, required)
  chargeType (string, required)
  tag (string, required)
  installmentItems (InstallmentItemMigrationRequest[], required)

TermMigrationRequest
Properties:
  startTime (datetime, required)
  endTime (datetime, required)
  transactions (TransactionMigrationRequest[], required)

MigrationResponse
Properties:
  locator (ulid, required)
  migrationState (Enum submitted | processing | paused | finished | failed | error, required)
  processedAccounts (integer, required)
  totalAccounts (integer, required)

ErrorDetailsResponse
Properties:
  originalId (string, required)
  errors (ValidationResult, required)

MigrationRequest
Properties:
  defaultCreatedBy (uuid, required)
  policies (PolicyMigrationRequest[], required)
  invoices (InvoiceMigrationRequest[], required)
  payments (PaymentMigrationRequest[], required)
  disbursements (DisbursementMigrationRequest[], required)

PatchAccountMigrationRequest
Properties:
  defaultCreatedBy (uuid, required)
  accountLocator (ulid, required)
  accountData (AccountMigrationData)
  policies (map<string, PolicyMigrationRequest>, required)
  invoices (map<string, InvoiceMigrationRequest>, required)
  payments (map<string, PaymentMigrationRequest>, required)
  disbursements (map<string, DisbursementMigrationRequest>, required)

MigrationFailuresResponse
Properties:
  accountLocator (ulid, required)
  accountOriginalId (string, required)
  accountError (ErrorDetailsResponse)
  policies (map<string, ErrorDetailsResponse>, required)
  invoices (map<string, ErrorDetailsResponse>, required)
  payments (map<string, ErrorDetailsResponse>, required)
  disbursements (map<string, ErrorDetailsResponse>, required)

AccountMigrationIdMappingsListResponse
Properties:
  listCompleted (boolean, required)
  items (AccountMigrationIdMappingsResponse[], required)

ListPageResponseAccountMigrationIdMappings
Properties:
  listCompleted (boolean, required)
  items (AccountMigrationIdMappingsResponse[], required)

AccountMigrationIdMappingsResponse
Properties:
  migrationLocator (ulid, required)
  accountLocator (ulid, required)
  originalAccountId (string, required)
  policies (map<string, MappingObject>, required)
  invoices (map<string, MappingObject>, required)
  payments (map<string, MappingObject>, required)
  disbursements (map<string, MappingObject>, required)

MappingObject
Properties:
  originalId (string, required)
  childrenMappings (map<string, object>, required)
  migratedAt (datetime, required)

AccountMigrationResponse
Properties:
  accountLocator (ulid)
  accountMigrationState (Enum pending | processing | error | failed | completed, required)
  processedItems (integer, required)
  errorItems (integer, required)
  totalItems (integer, required)
  lastUpdated (datetime, required)

ListPageResponseAccountMigrationResponse
Properties:
  listCompleted (boolean, required)
  items (AccountMigrationResponse[], required)

ListPageResponseMigrationFailuresResponse
Properties:
  listCompleted (boolean, required)
  items (MigrationFailuresResponse[], required)

# Moratoriums API (Beta)



<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

<EndpointIndex
  names={[
  	'deployMoratoriums',
  	'fetchMoratoriums',
  	'getPolicyMoratoriumsStatuses',
  	'getQuoteMoratoriumsStatuses',
  	'addPolicyMoratoriumElections',
  	'deletePolicyMoratoriumElections',
  ]}
  titles={{
  	deployMoratoriums: 'Create a Moratorium',
  	fetchMoratoriums: 'Fetch Existing Moratoriums',
  	getPolicyMoratoriumsStatuses: "Get a Policy's Moratorium Status",
  	getQuoteMoratoriumsStatuses: "Get a Quote's Moratorium Status",
  }}
/>

Create [#create]

Create a Moratorium [#create-a-moratorium]

<ApiEndpoint name="deployMoratoriums" title="Create a Moratorium" />

Fetch [#fetch]

Fetch Existing Moratoriums [#fetch-existing-moratoriums]

<ApiEndpoint name="fetchMoratoriums" title="Fetch Existing Moratoriums" />

Get a Policy's Moratorium Status [#get-a-policys-moratorium-status]

<ApiEndpoint name="getPolicyMoratoriumsStatuses" title="Get a Policy's Moratorium Status" />

Get a Quote's Moratorium Status [#get-a-quotes-moratorium-status]

<ApiEndpoint name="getQuoteMoratoriumsStatuses" title="Get a Quote's Moratorium Status" />

Make Applicability Election [#make-applicability-election]

Add Policy Moratorium Elections [#add-policy-moratorium-elections]

<ApiEndpoint name="addPolicyMoratoriumElections" />

Delete Applicability Election [#delete-applicability-election]

Delete Policy Moratorium Elections [#delete-policy-moratorium-elections]

<ApiEndpoint name="deletePolicyMoratoriumElections" />

<ApiSchema name="MoratoriumStatusesResponse" />

<ApiSchema name="MoratoriumStatus" />

<ApiSchema name="MoratoriumElectionRequest" />

<ApiSchema name="MoratoriumRef" />

<ApiSchema name="MoratoriumPolicyMatchCriteriaRef" />

<ApiSchema name="MoratoriumProductRuleRef" />

<ApiSchema name="MoratoriumRuleRef" />

<ApiSchema name="PolicyHoldScopeRef" />

<ApiSchema name="BillingHoldScopeRef" />

See Also [#see-also]

* [Moratoriums Feature Guide](/features/moratoriums/moratoriums)


## API Reference

POST /config/{tenantLocator}/moratoriums — deployMoratoriums
Permissions: deploy
Parameters:
  tenantLocator (uuid, path, required)
Request body (ConfigurationRef):
Responses:
  200 — OK

GET /config/{tenantLocator}/moratoriums — fetchMoratoriums
Permissions: deploy, fetch
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 map<string, MoratoriumRef> — OK

GET /policy/{tenantLocator}/policies/{locator}/moratoriums — getPolicyMoratoriumsStatuses
Permissions: moratoriums
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 MoratoriumStatusesResponse — OK

GET /policy/{tenantLocator}/quotes/{locator}/moratoriums — getQuoteMoratoriumsStatuses
Permissions: moratoriums
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 MoratoriumStatusesResponse — OK

PUT /policy/{tenantLocator}/policies/{locator}/moratoriums/elections — addPolicyMoratoriumElections
Permissions: moratoriums
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (MoratoriumElectionRequest[]):
Responses:
  200 PolicyResponse — OK

DELETE /policy/{tenantLocator}/policies/{locator}/moratoriums/elections — deletePolicyMoratoriumElections
Permissions: moratoriums
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (string[]):
Responses:
  200 PolicyResponse — OK

MoratoriumStatusesResponse
Properties:
  locator (ulid, required)
  moratoriums (map<string, MoratoriumStatus>, required)

MoratoriumStatus
Properties:
  applicable (boolean, required)
  eligible (boolean, required)
  inScope (boolean, required)
  applicationMode (Enum optIn | optOut | mandatory, required)

MoratoriumElectionRequest
Properties:
  moratoriumName (string, required)
  election (Enum optIn | optOut, required)

MoratoriumRef
Properties:
  type (string, required)
  description (string)
  applicationMode (Enum optIn | optOut | mandatory, required) — Indicates whether the moratorium applies to all eligible policies or whether there is an option to opt in or out.
  effectiveTime (datetime, required)
  endTime (datetime) — The time the moratorium ends. This can be set after creation and updated to earlier or later.
  policyMatchCriteria (MoratoriumPolicyMatchCriteriaRef, required) — The criteria used to identify which policies are eligible for the moratorium.
  effectiveTimeWaived (boolean) — Indicates whether eligible policies issued after the moratorium effectiveTime are affected.
  policyHoldScope (PolicyHoldScopeRef, required) — Must be at least one of either policyHoldScope or billingHoldScope.
  billingHoldScope (BillingHoldScopeRef, required)
  displayName (string)

MoratoriumPolicyMatchCriteriaRef
Properties:
  criteriaValues (map<string, string[]>, required)
  productsRules (map<string, MoratoriumProductRuleRef>, required)

MoratoriumProductRuleRef
Properties:
  product (string, required)
  operator (Enum AND | OR, required)
  rules (MoratoriumRuleRef[], required)
  displayName (string)

MoratoriumRuleRef
Properties:
  path (string, required)
  criteriaKey (string, required)
  notIn (boolean, required)

PolicyHoldScopeRef
Properties:
  transactionCategory (Enum[], required)
  transactionType (string[], required)
  allowStaticData (boolean, required)
  displayName (string)

BillingHoldScopeRef
Properties:
  policyInvoicingHold (boolean, required)
  policyDelinquencyHold (boolean, required)
  autopayHold (boolean, required)
  deferredInvoiceDueOffsetDays (number, required)
  displayName (string)

# Producer Management API



<EndpointIndex
  names={[
  	'fetchProducer',
  	'fetchProducers',
  	'fetchProducerHierarchy',
  	'createProducer',
  	'updateProducer',
  	'replaceProducer',
  	'validateProducer',
  	'discardProducer',
  	'suspendProducer',
  	'unsuspendProducer',
  	'retireProducer',
  	'fetchProducerCode',
  	'fetchProducerCodes',
  	'fetchProducerCodeByCode',
  	'createProducerCode',
  	'updateProducerCode',
  	'replaceProducerCode',
  	'validateProducerCode',
  	'discardProducerCode',
  	'suspendProducerCode',
  	'unsuspendProducerCode',
  	'retireProducerCode',
  	'generateCodeByNumber',
  	'setCodeByNumber',
  	'fetchProducerLicense',
  	'fetchProducerLicenses',
  	'createProducerLicense',
  	'updateProducerLicense',
  	'replaceProducerLicense',
  	'validateProducerLicense',
  	'discardProducerLicense',
  	'fetchProducerAppointment',
  	'fetchProducerAppointments',
  	'createProducerAppointment',
  	'updateProducerAppointment',
  	'replaceProducerAppointment',
  	'validateProducerAppointment',
  	'discardProducerAppointment',
  ]}
/>

Producers [#producers]

Fetch Producer [#fetch-producer]

<ApiEndpoint name="fetchProducer" />

Fetch Producers [#fetch-producers]

<ApiEndpoint name="fetchProducers" />

Fetch Producer Hierarchy [#fetch-producer-hierarchy]

<ApiEndpoint name="fetchProducerHierarchy" />

Create Producer [#create-producer]

<ApiEndpoint name="createProducer" />

Update Producer [#update-producer]

<ApiEndpoint name="updateProducer" />

Replace Producer [#replace-producer]

<ApiEndpoint name="replaceProducer" />

Validate Producer [#validate-producer]

<ApiEndpoint name="validateProducer" />

Discard Producer [#discard-producer]

<ApiEndpoint name="discardProducer" />

Suspend Producer [#suspend-producer]

<ApiEndpoint name="suspendProducer" />

Unsuspend Producer [#unsuspend-producer]

<ApiEndpoint name="unsuspendProducer" />

Retire Producer [#retire-producer]

<ApiEndpoint name="retireProducer" />

Producer Codes [#producer-codes]

Fetch Producer Code [#fetch-producer-code]

<ApiEndpoint name="fetchProducerCode" />

Fetch Producer Codes [#fetch-producer-codes]

<ApiEndpoint name="fetchProducerCodes" />

Fetch Producer Code By Code [#fetch-producer-code-by-code]

<ApiEndpoint name="fetchProducerCodeByCode" />

Create Producer Code [#create-producer-code]

<ApiEndpoint name="createProducerCode" />

Update Producer Code [#update-producer-code]

<ApiEndpoint name="updateProducerCode" />

Replace Producer Code [#replace-producer-code]

<ApiEndpoint name="replaceProducerCode" />

Validate Producer Code [#validate-producer-code]

<ApiEndpoint name="validateProducerCode" />

Discard Producer Code [#discard-producer-code]

<ApiEndpoint name="discardProducerCode" />

Suspend Producer Code [#suspend-producer-code]

<ApiEndpoint name="suspendProducerCode" />

Unsuspend Producer Code [#unsuspend-producer-code]

<ApiEndpoint name="unsuspendProducerCode" />

Retire Producer Code [#retire-producer-code]

<ApiEndpoint name="retireProducerCode" />

Generate Code By Number [#generate-code-by-number]

<ApiEndpoint name="generateCodeByNumber" />

Set Code By Number [#set-code-by-number]

<ApiEndpoint name="setCodeByNumber" />

Licenses [#licenses]

Fetch Producer License [#fetch-producer-license]

<ApiEndpoint name="fetchProducerLicense" />

Fetch Producer Licenses [#fetch-producer-licenses]

<ApiEndpoint name="fetchProducerLicenses" />

Create Producer License [#create-producer-license]

<ApiEndpoint name="createProducerLicense" />

Update Producer License [#update-producer-license]

<ApiEndpoint name="updateProducerLicense" />

Replace Producer License [#replace-producer-license]

<ApiEndpoint name="replaceProducerLicense" />

Validate Producer License [#validate-producer-license]

<ApiEndpoint name="validateProducerLicense" />

Discard Producer License [#discard-producer-license]

<ApiEndpoint name="discardProducerLicense" />

Appointments [#appointments]

Fetch Producer Appointment [#fetch-producer-appointment]

<ApiEndpoint name="fetchProducerAppointment" />

Fetch Producer Appointments [#fetch-producer-appointments]

<ApiEndpoint name="fetchProducerAppointments" />

Create Producer Appointment [#create-producer-appointment]

<ApiEndpoint name="createProducerAppointment" />

Update Producer Appointment [#update-producer-appointment]

<ApiEndpoint name="updateProducerAppointment" />

Replace Producer Appointment [#replace-producer-appointment]

<ApiEndpoint name="replaceProducerAppointment" />

Validate Producer Appointment [#validate-producer-appointment]

<ApiEndpoint name="validateProducerAppointment" />

Discard Producer Appointment [#discard-producer-appointment]

<ApiEndpoint name="discardProducerAppointment" />

<ApiSchema name="ProducerResponse" />

<ApiSchema name="ListPageResponseProducerResponse" />

<ApiSchema name="ProducerHierarchyResponse" />

<ApiSchema name="ProducerCreateRequest" />

<ApiSchema name="ProducerUpdateRequest" />

<ApiSchema name="ProducerCodeResponse" />

<ApiSchema name="ListPageResponseProducerCodeResponse" />

<ApiSchema name="ProducerCodeCreateRequest" />

<ApiSchema name="ProducerCodeUpdateRequest" />

<ApiSchema name="ProducerCodeReplaceRequest" />

<ApiSchema name="ProducerLicenseResponse" />

<ApiSchema name="ListPageResponseProducerLicenseResponse" />

<ApiSchema name="ProducerLicenseCreateRequest" />

<ApiSchema name="ProducerLicenseUpdateRequest" />

<ApiSchema name="ProducerLicenseReplaceRequest" />

<ApiSchema name="ProducerAppointmentResponse" />

<ApiSchema name="ListPageResponseProducerAppointmentResponse" />

<ApiSchema name="ProducerAppointmentCreateRequest" />

<ApiSchema name="ProducerAppointmentUpdateRequest" />

<ApiSchema name="ProducerAppointmentReplaceRequest" />


## API Reference

GET /producers/{tenantLocator}/producers/{producerLocator} — fetchProducer
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerResponse — OK

GET /producers/{tenantLocator}/producers/list — fetchProducers
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseProducerResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/producerHierarchy — fetchProducerHierarchy
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerHierarchyResponse — OK

POST /producers/{tenantLocator}/producers — createProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (ProducerCreateRequest):
Responses:
  200 ProducerResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator} — updateProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Request body (ProducerUpdateRequest):
Responses:
  200 ProducerResponse — OK

PUT /producers/{tenantLocator}/producers/{producerLocator} — replaceProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Request body (ProducerCreateRequest):
Responses:
  200 ProducerResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/validate — validateProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/discard — discardProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/suspend — suspendProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/unsuspend — unsuspendProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/retire — retireProducer
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Responses:
  200 ProducerResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator} — fetchProducerCode
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/codes/list — fetchProducerCodes
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseProducerCodeResponse — OK

GET /producers/{tenantLocator}/producers/codes/{code} — fetchProducerCodeByCode
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  code (string, path, required)
Responses:
  200 ProducerCodeResponse — OK

POST /producers/{tenantLocator}/producers/{producerLocator}/codes — createProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Request body (ProducerCodeCreateRequest):
Responses:
  200 ProducerCodeResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator} — updateProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Request body (ProducerCodeUpdateRequest):
Responses:
  200 ProducerCodeResponse — OK

PUT /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator} — replaceProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Request body (ProducerCodeReplaceRequest):
Responses:
  200 ProducerCodeResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/validate — validateProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/discard — discardProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/suspend — suspendProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/unsuspend — unsuspendProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/retire — retireProducerCode
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

POST /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/number/generate — generateCodeByNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
Responses:
  200 ProducerCodeResponse — OK

POST /producers/{tenantLocator}/producers/{producerLocator}/codes/{producerCodeLocator}/number/set — setCodeByNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerCodeLocator (ulid, path, required)
  code (string, query, required)
Responses:
  200 ProducerCodeResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/licenses/{producerLicenseLocator} — fetchProducerLicense
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerLicenseLocator (ulid, path, required)
Responses:
  200 ProducerLicenseResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/licenses/list — fetchProducerLicenses
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseProducerLicenseResponse — OK

POST /producers/{tenantLocator}/producers/{producerLocator}/licenses — createProducerLicense
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Request body (ProducerLicenseCreateRequest):
Responses:
  200 ProducerLicenseResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/licenses/{producerLicenseLocator} — updateProducerLicense
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerLicenseLocator (ulid, path, required)
Request body (ProducerLicenseUpdateRequest):
Responses:
  200 ProducerLicenseResponse — OK

PUT /producers/{tenantLocator}/producers/{producerLocator}/licenses/{producerLicenseLocator} — replaceProducerLicense
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerLicenseLocator (ulid, path, required)
Request body (ProducerLicenseReplaceRequest):
Responses:
  200 ProducerLicenseResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/licenses/{producerLicenseLocator}/validate — validateProducerLicense
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerLicenseLocator (ulid, path, required)
Responses:
  200 ProducerLicenseResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/licenses/{producerLicenseLocator}/discard — discardProducerLicense
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerLicenseLocator (ulid, path, required)
Responses:
  200 ProducerLicenseResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/appointments/{producerAppointmentLocator} — fetchProducerAppointment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerAppointmentLocator (ulid, path, required)
Responses:
  200 ProducerAppointmentResponse — OK

GET /producers/{tenantLocator}/producers/{producerLocator}/appointments/list — fetchProducerAppointments
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseProducerAppointmentResponse — OK

POST /producers/{tenantLocator}/producers/{producerLocator}/appointments — createProducerAppointment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
Request body (ProducerAppointmentCreateRequest):
Responses:
  200 ProducerAppointmentResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/appointments/{producerAppointmentLocator} — updateProducerAppointment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerAppointmentLocator (ulid, path, required)
Request body (ProducerAppointmentUpdateRequest):
Responses:
  200 ProducerAppointmentResponse — OK

PUT /producers/{tenantLocator}/producers/{producerLocator}/appointments/{producerAppointmentLocator} — replaceProducerAppointment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerAppointmentLocator (ulid, path, required)
Request body (ProducerAppointmentReplaceRequest):
Responses:
  200 ProducerAppointmentResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/appointments/{producerAppointmentLocator}/validate — validateProducerAppointment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerAppointmentLocator (ulid, path, required)
Responses:
  200 ProducerAppointmentResponse — OK

PATCH /producers/{tenantLocator}/producers/{producerLocator}/appointments/{producerAppointmentLocator}/discard — discardProducerAppointment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  producerLocator (ulid, path, required)
  producerAppointmentLocator (ulid, path, required)
Responses:
  200 ProducerAppointmentResponse — OK

ProducerResponse
Properties:
  locator (ulid, required)
  type (string, required)
  producerState (Enum draft | validated | suspended | discarded | retired, required)
  parentLocator (ulid)
  data (map<string, object>)
  createdAt (datetime, required)
  createdBy (uuid, required)
  validationResult (ValidationResult)

ListPageResponseProducerResponse
Properties:
  listCompleted (boolean, required)
  items (ProducerResponse[], required)

ProducerHierarchyResponse
Properties:
  locator (ulid, required)
  type (string, required)
  producerState (Enum draft | validated | suspended | discarded | retired, required)
  parentLocator (ulid)
  data (map<string, object>)
  createdAt (datetime, required)
  createdBy (uuid, required)
  validationResult (ValidationResult)
  childProducers (ProducerHierarchyResponse[], required)

ProducerCreateRequest
Properties:
  type (string, required)
  parentLocator (ulid)
  data (map<string, object>)

ProducerUpdateRequest
Properties:
  type (string)
  parentLocator (ulid)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ProducerCodeResponse
Properties:
  locator (ulid, required)
  type (string, required)
  producerCodeState (Enum draft | validated | suspended | discarded | retired, required)
  producerLocator (ulid, required)
  code (string)
  data (map<string, object>)
  createdAt (datetime, required)
  createdBy (uuid, required)
  validationResult (ValidationResult)

ListPageResponseProducerCodeResponse
Properties:
  listCompleted (boolean, required)
  items (ProducerCodeResponse[], required)

ProducerCodeCreateRequest
Properties:
  type (string, required)
  code (string)
  data (map<string, object>)

ProducerCodeUpdateRequest
Properties:
  type (string)
  producerLocator (ulid)
  code (string)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ProducerCodeReplaceRequest
Properties:
  producerLocator (ulid, required)
  type (string, required)
  code (string)
  data (map<string, object>)

ProducerLicenseResponse
Properties:
  locator (ulid, required)
  type (string, required)
  producerLicenseState (Enum draft | validated | discarded, required)
  producerLocator (ulid, required)
  licenseNumber (string)
  producerCodes (string[], required)
  jurisdictions (string[], required)
  products (string[], required)
  effectiveTime (datetime)
  expirationTime (datetime)
  data (map<string, object>)
  createdAt (datetime, required)
  createdBy (uuid, required)
  validationResult (ValidationResult)

ListPageResponseProducerLicenseResponse
Properties:
  listCompleted (boolean, required)
  items (ProducerLicenseResponse[], required)

ProducerLicenseCreateRequest
Properties:
  type (string, required)
  licenseNumber (string)
  producerCodes (string[], required)
  jurisdictions (string[], required)
  products (string[], required)
  effectiveTime (datetime)
  expirationTime (datetime)
  data (map<string, object>)

ProducerLicenseUpdateRequest
Properties:
  producerLocator (ulid)
  type (string)
  licenseNumber (string)
  producerCodes (string[])
  jurisdictions (string[])
  products (string[])
  effectiveTime (datetime)
  expirationTime (datetime)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ProducerLicenseReplaceRequest
Properties:
  producerLocator (ulid, required)
  type (string, required)
  licenseNumber (string)
  producerCodes (string[], required)
  jurisdictions (string[], required)
  products (string[], required)
  effectiveTime (datetime)
  expirationTime (datetime)
  data (map<string, object>)

ProducerAppointmentResponse
Properties:
  locator (ulid, required)
  type (string, required)
  producerAppointmentState (Enum draft | validated | discarded, required)
  producerLocator (ulid, required)
  appointmentNumber (string)
  producerCodes (string[], required)
  jurisdictions (string[], required)
  products (string[], required)
  licenses (ulid[], required)
  effectiveTime (datetime)
  expirationTime (datetime)
  data (map<string, object>)
  createdAt (datetime, required)
  createdBy (uuid, required)
  validationResult (ValidationResult)

ListPageResponseProducerAppointmentResponse
Properties:
  listCompleted (boolean, required)
  items (ProducerAppointmentResponse[], required)

ProducerAppointmentCreateRequest
Properties:
  type (string, required)
  appointmentNumber (string)
  producerCodes (string[], required)
  jurisdictions (string[], required)
  products (string[], required)
  licenses (ulid[], required)
  effectiveTime (datetime)
  expirationTime (datetime)
  data (map<string, object>)

ProducerAppointmentUpdateRequest
Properties:
  producerLocator (ulid)
  type (string)
  appointmentNumber (string)
  producerCodes (string[])
  jurisdictions (string[])
  products (string[])
  licenses (ulid[])
  effectiveTime (datetime)
  expirationTime (datetime)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ProducerAppointmentReplaceRequest
Properties:
  producerLocator (ulid, required)
  type (string, required)
  appointmentNumber (string)
  producerCodes (string[], required)
  jurisdictions (string[], required)
  products (string[], required)
  licenses (ulid[], required)
  effectiveTime (datetime)
  expirationTime (datetime)
  data (map<string, object>)

# Quick Quotes API



<EndpointIndex
  names={[
  	'createQuickQuote',
  	'validateQuickQuote',
  	'fetchQuickQuote',
  	'fetchMultipleQuickQuotes',
  	'priceAQuickQuote',
  	'fetchPricingForQuickQuote',
  	'quickQuoteValidatePreview',
  	'quickQuotePricePreview',
  	'updateQuickQuote',
  	'addElementsToQuickQuote',
  	'deleteElementsFromQuickQuote',
  	'createQuoteFromQuickQuote',
  	'copyQuickQuote',
  	'resetQuickQuote',
  	'discardQuickQuote',
  	'addQuickQuoteContact',
  	'deleteQuickQuoteContact',
  	'fetchQuickQuoteContacts',
  	'updateQuickQuoteContact',
  ]}
  titles={{
  	quickQuoteValidatePreview:
  		'Get a stateless validation preview for a quick quote',
  	quickQuotePricePreview: 'Get a stateless price preview for a quick quote',
  	addQuickQuoteContact: 'Add quick quote contact',
  	deleteQuickQuoteContact: 'Delete quick quote contact',
  	fetchQuickQuoteContacts: 'Fetch quick quote contacts',
  	updateQuickQuoteContact: 'Update quick quote contact',
  }}
/>

Create Quick Quote [#create-quick-quote]

<ApiEndpoint name="createQuickQuote" />

<ApiSchema name="QuickQuoteCreateRequest" />

Validate Quick Quote [#validate-quick-quote]

<ApiEndpoint name="validateQuickQuote" />

Fetch Quick Quote [#fetch-quick-quote]

<ApiEndpoint name="fetchQuickQuote" />

<ApiSchema name="QuickQuoteResponse" />

Fetch Multiple Quick Quotes [#fetch-multiple-quick-quotes]

<ApiEndpoint name="fetchMultipleQuickQuotes" />

<ApiSchema name="QuickQuoteListResponse" />

Price AQuick Quote [#price-aquick-quote]

<ApiEndpoint name="priceAQuickQuote" />

<ApiSchema name="QuickQuotePriceResponse" />

Fetch Pricing For Quick Quote [#fetch-pricing-for-quick-quote]

<ApiEndpoint name="fetchPricingForQuickQuote" />

Get a stateless validation preview for a quick quote [#get-a-stateless-validation-preview-for-a-quick-quote]

<ApiEndpoint name="quickQuoteValidatePreview" title="Get a stateless validation preview for a quick quote" />

Get a stateless price preview for a quick quote [#get-a-stateless-price-preview-for-a-quick-quote]

<ApiEndpoint name="quickQuotePricePreview" title="Get a stateless price preview for a quick quote" />

<Callout>
  The <ApiLink name="priceAQuickQuote" /> endpoint differs from <ApiLink name="fetchPricingForQuickQuote" /> in that the former will advance the quick quote to `priced` state, and the latter will not change the state.
</Callout>

Update Quick Quote [#update-quick-quote]

<ApiEndpoint name="updateQuickQuote" />

<ApiSchema name="QuickQuoteUpdateRequest" />

Add Elements To Quick Quote [#add-elements-to-quick-quote]

<ApiEndpoint name="addElementsToQuickQuote" />

Delete Elements From Quick Quote [#delete-elements-from-quick-quote]

<ApiEndpoint name="deleteElementsFromQuickQuote" />

Create Quote From Quick Quote [#create-quote-from-quick-quote]

<ApiEndpoint name="createQuoteFromQuickQuote" />

<ApiSchema name="QuickQuoteQuoteResponse" />

<ApiSchema name="QuickQuoteQuoteDetails" />

Copy Quick Quote [#copy-quick-quote]

<ApiEndpoint name="copyQuickQuote" />

Reset Quick Quote [#reset-quick-quote]

<ApiEndpoint name="resetQuickQuote" />

Discard Quick Quote [#discard-quick-quote]

<ApiEndpoint name="discardQuickQuote" />

Contacts [#contacts]

Add quick quote contact [#add-quick-quote-contact]

<ApiEndpoint name="addQuickQuoteContact" title="Add quick quote contact" />

<ApiSchema name="ContactRoles" />

Delete quick quote contact [#delete-quick-quote-contact]

<ApiEndpoint name="deleteQuickQuoteContact" title="Delete quick quote contact" />

Fetch quick quote contacts [#fetch-quick-quote-contacts]

<ApiEndpoint name="fetchQuickQuoteContacts" title="Fetch quick quote contacts" />

Update quick quote contact [#update-quick-quote-contact]

<ApiEndpoint name="updateQuickQuoteContact" title="Update quick quote contact" />

See Also [#see-also]

* [Quick Quotes Feature Guide](/features/policy-quotation/quick-quotes)


## API Reference

POST /policy/{tenantLocator}/quickquotes — createQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuickQuoteCreateRequest):
Responses:
  200 QuickQuoteResponse — OK

PATCH /policy/{tenantLocator}/quickquotes/{locator}/validate — validateQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuickQuoteResponse — OK

GET /policy/{tenantLocator}/quickquotes/{locator} — fetchQuickQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuickQuoteResponse — OK

GET /policy/{tenantLocator}/quickquotes/list — fetchMultipleQuickQuotes
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 QuickQuoteListResponse — OK

PATCH /policy/{tenantLocator}/quickquotes/{locator}/price — priceAQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuickQuotePriceResponse — OK

GET /policy/{tenantLocator}/quickquotes/{locator}/price — fetchPricingForQuickQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuickQuotePriceResponse — OK

POST /policy/{tenantLocator}/quickquotes/validatePreview — quickQuoteValidatePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuickQuoteCreateRequest):
Responses:
  200 QuickQuoteResponse — OK

POST /policy/{tenantLocator}/quickquotes/pricePreview — quickQuotePricePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuickQuoteCreateRequest):
Responses:
  200 QuickQuotePriceResponse — OK

PATCH /policy/{tenantLocator}/quickquotes/{locator} — updateQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (QuickQuoteUpdateRequest):
Responses:
  200 QuickQuoteResponse — OK

PUT /policy/{tenantLocator}/quickquotes/{locator}/elements — addElementsToQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ElementResponse[]):
Responses:
  200 QuickQuoteResponse — OK

DELETE /policy/{tenantLocator}/quickquotes/{locator}/elements — deleteElementsFromQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 QuickQuoteResponse — OK

POST /policy/{tenantLocator}/quickquotes/{locator}/quote/{accountLocator} — createQuoteFromQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  accountLocator (ulid, path, required)
  markAsQuoted (boolean, query)
Responses:
  200 QuickQuoteQuoteResponse — OK

POST /policy/{tenantLocator}/quickquotes/{locator}/copy — copyQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (QuoteGroupAssignmentRequest):
Responses:
  200 QuickQuoteResponse — OK

PATCH /policy/{tenantLocator}/quickquotes/{locator}/reset — resetQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuickQuoteResponse — OK

PATCH /policy/{tenantLocator}/quickquotes/{locator}/discard — discardQuickQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuickQuoteResponse — OK

POST /policy/{tenantLocator}/quickquotes/{quoteLocator}/contacts — addQuickQuoteContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
Request body (ContactRoles):
Responses:
  200 QuickQuoteResponse — OK

DELETE /policy/{tenantLocator}/quickquotes/{quoteLocator}/contacts/{contactLocator} — deleteQuickQuoteContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Responses:
  200 QuickQuoteResponse — OK

GET /policy/{tenantLocator}/quickquotes/{quoteLocator}/contacts — fetchQuickQuoteContacts
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
Responses:
  200 ContactRoles[] — OK

PATCH /policy/{tenantLocator}/quickquotes/{quoteLocator}/contacts/{contactLocator} — updateQuickQuoteContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Request body (ContactAssociationUpdateRequest):
Responses:
  200 QuickQuoteResponse — OK

QuickQuoteCreateRequest
Properties:
  productName (string, required)
  startTime (datetime)
  endTime (datetime)
  expirationTime (datetime)
  currency (string)
  timezone (string)
  jurisdiction (string)
  coverageTerms (map<string, object>)
  data (map<string, object>, required)
  elements (ElementCreateRequest[])
  durationBasis (Enum years | months | weeks | days | hours)
  contacts (ContactRoles[], required)

QuickQuoteResponse
Properties:
  locator (ulid, required)
  quickQuoteState (Enum draft | validated | priced | quoted | discarded, required)
  productName (string, required)
  accountLocator (ulid)
  startTime (datetime)
  endTime (datetime)
  duration (number)
  expirationTime (datetime)
  timezone (string)
  currency (string)
  durationBasis (Enum years | months | weeks | days | hours)
  groupLocator (ulid)
  element (ElementResponse, required)
  validationResult (ValidationResult)
  contacts (ContactRoles[], required)
  createdBy (uuid)
  createdAt (datetime)
  anonymizedAt (datetime)
  jurisdiction (string)

QuickQuoteListResponse
Properties:
  listCompleted (boolean, required)
  items (QuickQuoteResponse[], required)

QuickQuotePriceResponse
Properties:
  tenantLocator (uuid, required)
  quickQuoteLocator (ulid, required)
  accountLocator (ulid)
  quickQuoteState (Enum draft | validated | priced | quoted | discarded, required)
  productName (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  duration (number, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  items (PolicyChargeResponse[], required)
  validationResult (ValidationResult)
  state (Enum draft | validated | priced | quoted | discarded, required) [deprecated]

QuickQuoteUpdateRequest
Properties:
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  setCoverageTerms (map<string, object>, required)
  removeCoverageTerms (map<string, object>, required)
  currency (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  expirationTime (datetime, required)
  elements (ElementUpdateRequest[], required)
  setContacts (ContactRoles[], required)
  removeContacts (ulid[], required)
  jurisdiction (string)

QuickQuoteQuoteResponse
Properties:
  tenantLocator (uuid, required)
  quickQuoteLocator (ulid, required)
  accountLocator (ulid)
  quickQuoteState (Enum draft | validated | priced | quoted | discarded, required)
  productName (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  duration (number, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  quote (QuickQuoteQuoteDetails)
  validationResult (ValidationResult)

QuickQuoteQuoteDetails
Properties:
  locator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  productName (string, required)
  accountLocator (ulid, required)
  startTime (datetime)
  endTime (datetime)
  timezone (string)
  currency (string)
  underwritingStatus (string)
  expirationTime (datetime)
  element (ElementResponse, required)
  preferences (Preferences)
  policyLocator (ulid)
  delinquencyPlanName (string)
  durationBasis (Enum years | months | weeks | days | hours)
  groupLocator (ulid, required)
  autoRenewalPlanName (string)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  quoteNumber (string)
  duration (number)
  acceptedTime (datetime)
  issuedTime (datetime)
  validationResult (ValidationResult)
  quickQuoteLocator (ulid)
  contacts (ContactRoles[], required)
  anonymizedAt (datetime)
  invoiceFeeAmount (number)
  createdBy (uuid)
  createdAt (datetime)
  jurisdiction (string)
  producerCode (string)
  reservedPolicyNumber (string)
  proxyPayerLocator (ulid)

ContactRoles
Properties:
  contactLocator (ulid, required)
  roles (string[], required)

# Search API



<EndpointIndex
  names={[
  	'fetchSearchResults',
  	'fetchAdditionalSearchResultsByToken',
  	'fetchSearchStats',
  	'fetchFieldsMapping',
  	'fetchIgnoredFields',
  ]}
/>

Data Search [#data-search]

<Callout type="warn">
  In addition to the `read` permission, you will need the `policies.list`, `quotes.list`, or `accounts.list` permission to be able to execute a search on the respective entity type.
</Callout>

Fetch Search Results [#fetch-search-results]

<ApiEndpoint name="fetchSearchResults" />

Fetch Additional Search Results By Token [#fetch-additional-search-results-by-token]

<ApiEndpoint name="fetchAdditionalSearchResultsByToken" />

Fetch Search Stats [#fetch-search-stats]

<ApiEndpoint name="fetchSearchStats" />

Fetch Fields Mapping [#fetch-fields-mapping]

<ApiEndpoint name="fetchFieldsMapping" />

Fetch Ignored Fields [#fetch-ignored-fields]

<ApiEndpoint name="fetchIgnoredFields" />

Search Request and Response Objects [#search-request-and-response-objects]

<ApiSchema name="SearchRequest" />

<ApiSchema name="SearchTermRequest" />

<ApiSchema name="SearchServiceResponse" />

<ApiSchema name="SearchResultResponse" />

<ApiSchema name="SearchStatsResponse" />

<ApiSchema name="SearchStatsResult" />

<ApiSchema name="FieldsRequest" />

<ApiSchema name="FieldsMappingResponse" />

<ApiSchema name="Field" />

See Also [#see-also]

* [Search Feature Guide](/features/search)


## API Reference

POST /search/{tenantLocator}/search — fetchSearchResults
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Request body (SearchRequest):
Responses:
  200 SearchServiceResponse — OK

GET /search/{tenantLocator}/search — fetchAdditionalSearchResultsByToken
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  searchToken (string, query, required) — The token returned from the initial search
Responses:
  200 SearchServiceResponse — OK

POST /search/{tenantLocator}/search/searchStats — fetchSearchStats
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Request body (SearchRequest):
Responses:
  200 SearchStatsResponse — OK

GET /search/{tenantLocator}/search/fieldsMapping — fetchFieldsMapping
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  request (FieldsRequest, query, required)
Responses:
  200 FieldsMappingResponse[] — OK

GET /search/{tenantLocator}/search/ignoredFields — fetchIgnoredFields
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  request (FieldsRequest, query, required)
Responses:
  200 FieldsMappingResponse[] — OK

SearchRequest
Properties:
  searchString (string, required)
  searchEntityType (Enum unspecified | account | quote | policy | fnol | contact | diary | payment | task | userAssociation, required)
  searchTerms (SearchTermRequest[], required)
  startCreationTime (datetime)
  endCreationTime (datetime)
  sortField (string)
  sortOrder (Enum Asc | Desc, required)
  fields (string[], required)

SearchTermRequest
Properties:
  searchTerm (string, required)
  fieldName (string, required)
  match (Enum fuzzy | exact | startsWith | lessThan | greaterThan, required)
  absolute (Enum none | required | excluded, required)

SearchServiceResponse
Properties:
  searchToken (string, required)
  offset (integer, required)
  count (integer, required)
  results (SearchResultResponse[], required)

SearchResultResponse
Properties:
  score (number, required)
  searchEntityType (Enum unspecified | account | quote | policy | fnol | contact | diary | payment | task | userAssociation, required)
  searchEntityLocator (ulid, required)
  productName (string, required)
  accountLocator (string, required)
  configVersionLocator (string, required)
  searchSummary (map<string, object>, required)
  highlights (string[], required)

SearchStatsResponse
Properties:
  searchToken (string, required)
  results (SearchStatsResult[], required)

SearchStatsResult
Properties:
  searchEntityType (Enum unspecified | account | quote | policy | fnol | contact | diary | payment | task | userAssociation, required)
  recordCount (integer, required)

FieldsRequest
Properties:
  searchEntityType (Enum unspecified | account | quote | policy | fnol | contact | diary | payment | task | userAssociation, required)

FieldsMappingResponse
Properties:
  index (string, required)
  fields (Field[], required)

Field
Properties:
  name (string, required)
  type (Enum TEXT | DATE | OTHER, required)

# Work Management API



<EndpointIndex
  names={[
  	'getTask',
  	'addTask',
  	'updateTask',
  	'activateTask',
  	'assignTask',
  	'unassignTask',
  	'cancelTask',
  	'completeTask',
  	'fetchTasksWithNumber',
  	'generateTaskNumber',
  	'listTasks',
  	'listAllTasks',
  	'listAssignedTasks',
  	'listTaskHistory',
  	'searchTasks',
  	'setTaskNumber',
  	'getUserAssociation',
  	'makeUserAssociation',
  	'completeUserAssociation',
  	'uncompleteUserAssociation',
  	'disassociateUserAssociation',
  	'listUserAssociationHistory',
  	'listUserUserAssociationsHistory',
  	'getQualifications',
  	'fetchUsersQualifications',
  	'getUserQualifications',
  	'updateUserQualifications',
  	'createWorkgroup',
  	'getWorkgroup',
  	'listWorkgroups',
  	'patchWorkgroup',
  	'discardWorkgroup',
  	'autoAssign',
  	'createWorkplan',
  	'getWorkplan',
  	'listWorkplans',
  	'patchWorkplan',
  	'discardWorkplan',
  ]}
  titles={{
  	fetchUsersQualifications: 'Fetch Users for a Qualification',
  	autoAssign: 'Auto-Assign',
  }}
/>

Tasks [#tasks]

Get Task [#get-task]

<ApiEndpoint name="getTask" />

<ApiSchema name="Task" />

Add Task [#add-task]

<ApiEndpoint name="addTask" />

<ApiSchema name="TaskCreateRequest" />

<ApiSchema name="TaskCreationResponse" />

Update Task [#update-task]

<ApiEndpoint name="updateTask" />

<ApiSchema name="TaskUpdateRequest" />

Activate Task [#activate-task]

<ApiEndpoint name="activateTask" />

Assign Task [#assign-task]

<ApiEndpoint name="assignTask" />

Unassign Task [#unassign-task]

<ApiEndpoint name="unassignTask" />

Cancel Task [#cancel-task]

<ApiEndpoint name="cancelTask" />

Complete Task [#complete-task]

<ApiEndpoint name="completeTask" />

Fetch Tasks With Number [#fetch-tasks-with-number]

<ApiEndpoint name="fetchTasksWithNumber" />

Generate Task Number [#generate-task-number]

<ApiEndpoint name="generateTaskNumber" />

List Tasks [#list-tasks]

<ApiEndpoint name="listTasks" />

List All Tasks [#list-all-tasks]

<ApiEndpoint name="listAllTasks" />

List Assigned Tasks [#list-assigned-tasks]

<ApiEndpoint name="listAssignedTasks" />

<ApiSchema name="ListPageResponseTask" />

List Task History [#list-task-history]

<ApiEndpoint name="listTaskHistory" />

Search Tasks [#search-tasks]

<ApiEndpoint name="searchTasks" />

Set Task Number [#set-task-number]

<ApiEndpoint name="setTaskNumber" />

<ApiSchema name="TaskReference" />

User Associations [#user-associations]

Get User Association [#get-user-association]

<ApiEndpoint name="getUserAssociation" />

<ApiSchema name="UserAssociation" />

Make User Association [#make-user-association]

<ApiEndpoint name="makeUserAssociation" />

<ApiSchema name="UserAssociationCreateRequest" />

Complete User Association [#complete-user-association]

<ApiEndpoint name="completeUserAssociation" />

Uncomplete User Association [#uncomplete-user-association]

<ApiEndpoint name="uncompleteUserAssociation" />

Disassociate User Association [#disassociate-user-association]

<ApiEndpoint name="disassociateUserAssociation" />

List User Association History [#list-user-association-history]

<ApiEndpoint name="listUserAssociationHistory" />

<ApiSchema name="ListPageResponseUserAssociation" />

List User User Associations History [#list-user-user-associations-history]

<ApiEndpoint name="listUserUserAssociationsHistory" />

User Qualifications [#user-qualifications]

Get Qualifications [#get-qualifications]

<ApiEndpoint name="getQualifications" />

Fetch Users for a Qualification [#fetch-users-for-a-qualification]

<ApiEndpoint name="fetchUsersQualifications" title="Fetch Users for a Qualification" />

<ApiSchema name="UserQualification" />

Get User Qualifications [#get-user-qualifications]

<ApiEndpoint name="getUserQualifications" />

Update User Qualifications [#update-user-qualifications]

<ApiEndpoint name="updateUserQualifications" />

<ApiSchema name="QualificationsUpdateRequest" />

Workgroups [#workgroups]

Create Workgroup [#create-workgroup]

<ApiEndpoint name="createWorkgroup" />

Get Workgroup [#get-workgroup]

<ApiEndpoint name="getWorkgroup" />

List Workgroups [#list-workgroups]

<ApiEndpoint name="listWorkgroups" />

Patch Workgroup [#patch-workgroup]

<ApiEndpoint name="patchWorkgroup" />

Discard Workgroup [#discard-workgroup]

<ApiEndpoint name="discardWorkgroup" />

Auto-Assign [#auto-assign]

<ApiEndpoint name="autoAssign" title="Auto-Assign" />

<ApiSchema name="WorkgroupCreateRequest" />

<ApiSchema name="WorkgroupResponse" />

<ApiSchema name="ListPageResponseWorkgroupResponse" />

<ApiSchema name="WorkgroupPatchRequest" />

<ApiSchema name="AutoAssignmentCreateRequest" />

<ApiSchema name="AutoAssignmentResponse" />

Workplans [#workplans]

Create Workplan [#create-workplan]

<ApiEndpoint name="createWorkplan" />

Get Workplan [#get-workplan]

<ApiEndpoint name="getWorkplan" />

List Workplans [#list-workplans]

<ApiEndpoint name="listWorkplans" />

Patch Workplan [#patch-workplan]

<ApiEndpoint name="patchWorkplan" />

Discard Workplan [#discard-workplan]

<ApiEndpoint name="discardWorkplan" />

<ApiSchema name="WorkplanCreateRequest" />

<ApiSchema name="Workplan" />

<ApiSchema name="WorkplanItem" />

<ApiSchema name="ListPageResponseWorkplan" />

<ApiSchema name="WorkplanPatchRequest" />

<ApiSchema name="WorkplanItemRequest" />


## API Reference

GET /work-management/{tenantLocator}/tasks/{locator} — getTask
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /work-management/{tenantLocator}/tasks — addTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (TaskCreateRequest):
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/tasks/{locator} — updateTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (TaskUpdateRequest):
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/tasks/{locator}/activate — activateTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/tasks/{locator}/assign/{userLocator} — assignTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  userLocator (uuid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/tasks/{locator}/unassign — unassignTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/tasks/{locator}/cancel — cancelTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/tasks/{locator}/complete — completeTask
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/tasks/numbers/{taskNumber} — fetchTasksWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  taskNumber (string, path, required)
Responses:
  200 — OK

POST /work-management/{tenantLocator}/tasks/{locator}/number/generate — generateTaskNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/tasks/list — listTasks
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/tasks/all/list — listAllTasks
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/tasks/user/{userLocator}/list — listAssignedTasks
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  userLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/tasks/{locator}/history/list — listTaskHistory
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/tasks/{referenceType}/{referenceLocator}/list — searchTasks
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, path, required)
  referenceLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

POST /work-management/{tenantLocator}/tasks/{locator}/number/set — setTaskNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  taskNumber (string, query, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/userAssociations/{locator} — getUserAssociation
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /work-management/{tenantLocator}/userAssociations — makeUserAssociation
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (UserAssociationCreateRequest):
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/userAssociations/{userAssociationLocator}/complete — completeUserAssociation
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  userAssociationLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/userAssociations/{userAssociationLocator}/uncomplete — uncompleteUserAssociation
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  userAssociationLocator (ulid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/userAssociations/{userAssociationLocator}/disassociate — disassociateUserAssociation
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  userAssociationLocator (ulid, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/userAssociations/{locator}/history/list — listUserAssociationHistory
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/userAssociations/user/{userLocator}/history/list — listUserUserAssociationsHistory
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  userLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/qualifications — getQualifications
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/qualifications/{category}/{level} — fetchUsersQualifications
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  category (string, path, required)
  level (string, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/qualifications/{userLocator} — getUserQualifications
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  userLocator (uuid, path, required)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/qualifications/{userLocator} — updateUserQualifications
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  userLocator (uuid, path, required)
Request body (QualificationsUpdateRequest):
Responses:
  200 — OK

POST /work-management/{tenantLocator}/workgroups — createWorkgroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (WorkgroupCreateRequest):
Responses:
  200 — OK

GET /work-management/{tenantLocator}/workgroups/{workgroupLocator} — getWorkgroup
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  workgroupLocator (ulid, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/workgroups/list — listWorkgroups
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  user (uuid, query)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/workgroups/{workgroupLocator} — patchWorkgroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  workgroupLocator (ulid, path, required)
Request body (WorkgroupPatchRequest):
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/workgroups/{workgroupLocator}/discard — discardWorkgroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  workgroupLocator (ulid, path, required)
Responses:
  200 — OK

POST /work-management/{tenantLocator}/assignments — autoAssign
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (AutoAssignmentCreateRequest):
Responses:
  200 — OK

POST /work-management/{tenantLocator}/workplans — createWorkplan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (WorkplanCreateRequest):
Responses:
  200 — OK

GET /work-management/{tenantLocator}/workplans/{locator} — getWorkplan
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /work-management/{tenantLocator}/workplans/list — listWorkplans
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/workplans/{locator} — patchWorkplan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (WorkplanPatchRequest):
Responses:
  200 — OK

PATCH /work-management/{tenantLocator}/workplans/{locator}/discard — discardWorkplan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

Task
Properties:
  locator (ulid, required)
  category (string, required)
  type (string, required)
  taskState (Enum active | pastDeadline | completed | cancelled, required)
  references (TaskReference[], required)
  underwritingFlagLocators (ulid[], required)
  deadlineTime (datetime)
  assignedTo (uuid)
  createdBy (uuid, required)
  createdAt (datetime, required)
  updatedBy (uuid)
  updatedAt (datetime)
  description (string)
  taskNumber (string)
  completedAt (datetime)
  completedBy (uuid)
  source (string)
  tag (string)
  labels (string[], required)

TaskCreateRequest
Properties:
  type (string, required)
  deadlineTime (datetime)
  references (TaskReference[], required)
  underwritingFlagLocators (ulid[], required)
  assignedTo (uuid)
  description (string)
  source (string)
  tag (string)
  labels (string[], required)

TaskCreationResponse
Properties:
  taskLocator (ulid, required)
  status (Enum succeeded | failed, required)

TaskUpdateRequest
Properties:
  deadlineTime (datetime)
  addReferences (TaskReference[], required)
  removeReferences (TaskReference[], required)
  addUnderwritingFlags (ulid[], required)
  removeUnderwritingFlags (ulid[], required)
  description (string)
  source (string)
  tag (string)
  addLabels (string[], required)
  removeLabels (string[], required)

ListPageResponseTask
Properties:
  listCompleted (boolean, required)
  items (Task[], required)

TaskReference
Properties:
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)

UserAssociation
Properties:
  locator (ulid, required)
  userLocator (uuid, required)
  userAssociationRole (string, required)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)
  userAssociationState (Enum active | completed | disassociated | discarded, required)
  createdBy (uuid, required)
  createdAt (datetime, required)
  updatedBy (uuid)
  updatedAt (datetime)

UserAssociationCreateRequest
Properties:
  userLocator (uuid, required)
  userAssociationRole (string, required)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)

ListPageResponseUserAssociation
Properties:
  listCompleted (boolean, required)
  items (UserAssociation[], required)

UserQualification
Properties:
  userLocator (uuid, required)
  category (string, required)
  level (string, required)

QualificationsUpdateRequest
Properties:
  removeQualifications (map<string, string>, required)
  addQualifications (map<string, string>, required)

WorkgroupCreateRequest
Properties:
  name (string, required)
  subgroups (ulid[], required)
  users (uuid[], required)
  parentLocator (ulid)
  region (string)
  tag (string)

WorkgroupResponse
Properties:
  locator (ulid, required)
  name (string, required)
  workgroupState (Enum active | discarded, required)
  subgroups (WorkgroupResponse[], required)
  users (uuid[], required)
  entities (ulid[], required)
  tasks (ulid[], required)
  parent (ulid)
  region (string)
  tag (string)
  createdBy (uuid, required)
  createdAt (datetime, required)

ListPageResponseWorkgroupResponse
Properties:
  listCompleted (boolean, required)
  items (WorkgroupResponse[], required)

WorkgroupPatchRequest
Properties:
  name (string)
  setSubgroups (ulid[], required)
  removeSubgroups (ulid[], required)
  setUsers (uuid[], required)
  removeUsers (uuid[], required)
  parentLocator (ulid)
  region (string)
  tag (string)
  empty (boolean, required)

AutoAssignmentCreateRequest
Properties:
  taskLocator (ulid)
  task (TaskCreateRequest)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)
  associationRole (string)
  workgroupLocator (ulid)
  traversal (Enum depthFirst | breadthFirst | none)
  assignToGroup (Enum never | ifNotAssigned | always)

AutoAssignmentResponse
Properties:
  taskLocator (ulid, required)
  assignedUserLocator (uuid, required)
  assignedWorkgroupLocator (ulid, required)
  associationLocator (ulid, required)

WorkplanCreateRequest
Properties:
  name (string, required)
  items (WorkplanItemRequest[], required)
  defaultGroup (string)

Workplan
Properties:
  locator (ulid, required)
  name (string, required)
  workplanState (Enum active | discarded, required)
  items (WorkplanItem[], required)
  defaultGroup (string)
  createdBy (uuid, required)
  createdAt (datetime, required)

WorkplanItem
Properties:
  locator (ulid, required)
  associationRole (string)
  task (TaskCreateRequest)
  defaultGroup (string)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)
  traversal (Enum depthFirst | breadthFirst | none, required)
  assignToGroup (Enum never | ifNotAssigned | always, required)

ListPageResponseWorkplan
Properties:
  listCompleted (boolean, required)
  items (Workplan[], required)

WorkplanPatchRequest
Properties:
  name (string)
  addItems (WorkplanItemRequest[], required)
  removeItems (ulid[], required)
  defaultGroup (string)

WorkplanItemRequest
Properties:
  associationRole (string, required)
  task (TaskCreateRequest)
  defaultGroup (string, required)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)
  traversal (Enum depthFirst | breadthFirst | none, required)
  assignToGroup (Enum never | ifNotAssigned | always, required)

# Accounts



<span id="accounts" />

This article provides an **overview of accounts** in the Socotra Insurance Suite.

Overview [#overview]

In the Socotra Insurance Suite, an **account** is a data object that represents a third-party entity (a person or a business) that is capable of being quoted for and being issued a policy for an insurance product. An account can also represent a payer or another external party.

Accounts associate individuals or businesses with the insurance products they’re covered by. Invoicing and payments can be managed at the account level.

A tenant's configuration defines the overall structure of accounts and how they must be configured, including which parameters are required or optional and which data types are permitted.

Configuring accounts [#configuring-accounts]

An important part of tenant configuration is defining what types of accounts you want to make available.

<Callout>
  Accounts are extensible with data in a similar way to other entities. For more information, see: [Data extensions](/configuration/data-extensions/overview).
</Callout>

The directory tree below shows an example of how the `accounts` directory of a tenant configuration could be set up to allow for multiple account types.

```
├── accounts
│   ├── BaseAccount
│   │   └── config.json
│   ├── CommercialAccount
│   │   └── config.json
│   └── ConsumerAccount
│       └── config.json
```

The example above shows three configured account types:

* `BaseAccount`
* `CommercialAccount`
* `ConsumerAccount`

Let's examine the differences between each of these accounts in their `config.json` files.

Example: BaseAccount [#example-baseaccount]

In the example below, the `BaseAccount` configuration is defined as a basis for all other accounts. We know this because its `abstract` parameter is set to `true`. The intent of this account is not to be used directly, but rather to be extended by other account definitions.

Notice that in the `CommercialAccount` and `ConsumerAccount` examples there is a property called `extend` that points to the BaseAccount. This means that those accounts also include the parameters defined in the BaseAccount.

```json
{
	"defaultSearchable": false,
	"data": {
		"tier": {
			"type": "string",
			"maxLength": 20000,
			"options": ["Gold", "Silver", "Bronze"],
			"searchable": true
		}
	},
	"abstract": true
}
```

Example: CommercialAccount [#example-commercialaccount]

In the example below, the `CommercialAccount` is configured specifically to meet the needs of a commercial insurance customer (as opposed to an individual consumer).

```json
{
	"extend": "BaseAccount",
	"numberingPlan": "numberingPlan2",
	"invoiceNumberingPlan": "numberingPlan3",
	"data": {
		"companyName": {
			"displayName": "Company Name",
			"type": "string",
			"maxLength": 20000
		}
	},
	"abstract": false
}
```

Example: ConsumerAccount [#example-consumeraccount]

In the example below, the `ConsumerAccount` is configured specifically to meet the needs of an individual consumer (as opposed to a commercial entity).

```json
{
	"displayName": "Personal",
	"extend": "BaseAccount",
	"numberingPlan": "numberingPlan2",
	"invoiceNumberingPlan": "numberingPlan3",
	"data": {
		"firstName": {
			"displayName": "First Name",
			"type": "string",
			"maxLength": 20000,
			"searchable": true
		},
		"middleName": {
			"displayName": "Middle Name",
			"type": "string?",
			"maxLength": 20000,
			"searchable": false
		},
		"lastName": {
			"displayName": "Last Name",
			"type": "string",
			"minLength": 2,
			"maxLength": 20000,
			"searchable": true
		}
	},
	"abstract": false
}
```

Account states [#account-states]

An account can exist in one of two states. The table below list the two states and whether they can be used to validate [quotes](/features/policy-quotation/quotes) and/or [quick quotes](/features/policy-quotation/quick-quotes).

| Account state | Description                                                                                                                                                                                                                                                                                                                                                                 | Can quote? | Can quick quote? |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------- |
| `draft`       | A `draft` account is mutable without restriction.                                                                                                                                                                                                                                                                                                                           | No         | Yes              |
| `validated`   | A `validated` account is an account that's been validated according to the tenant configuration and any other custom validation rules. Once an account is validated, it can't revert to a `draft` state. It's possible to update an account, but the updates must also be validated according to the tenant configuration. If validation fails, the changes won't be saved. | Yes        | Yes              |

Limiting products to certain account types [#limiting-products-to-certain-account-types]

On an insurance product, the `eligibleAccountTypes` property can be configured to restrict its usage to certain account types.

For example, an insurance product intended only for individual consumers could be limited to a `ConsumerAccount`.

<Callout>
  If the `eligibleAccountTypes` for an insurance product is left unspecified, all account types are considered eligible for the product.
</Callout>

Extension data [#extension-data]

Accounts are extensible with data in a similar way to other entities. See the [Data Extensions](/configuration/data-extensions/overview) topic for more details.

See also [#see-also]

* [Account API](/api/accounts)


# Business Accounts



This article provides an **overview of business accounts**.

Overview [#overview]

In the Socotra Insurance Suite, a **business account** is a representation of your organization. It provides a logical grouping of tenants and users in a Socotra environment. Users with adequate privileges can perform administrative functions (e.g. user and tenant management).

In other words, a business account is your unique instance of Socotra, where you can configure and customize to the needs of your business.

Socotra can create one or more business accounts for your organization depending on your unique needs. You’ll receive login credentials to access your business account through secure channels to contacts you authorize.

Your Socotra representative will guide you through the process of making a business account and receiving credentials.

See also [#see-also]

* [Tenant Management API](/api/business-accounts/tenant-management)
* [Roles and Permissions Guide](/features/security/roles-and-permissions)
* [User Management API](/api/business-accounts/user-management)
* [Authentication API](/api/business-accounts/authentication)


# Contact Management



Overview [#overview]

Socotra allows you to define contacts that can be managed in association with a variety of entities:

* Accounts
* Policies
* Quotes and Quick Quotes
* FNOLs

Configuring Contacts [#configuring-contacts]

You define contacts at the <ApiLink name="ConfigurationRef">top level of your configuration</ApiLink>, associating a `contacts` property with a map of key-value pairs, where the key is the Pascal-cased contact type name and the value is a `ContactRef`:

<ApiSchema name="ContactRef" />

You must also define contact roles, which provide more context around how various contact types should be associated with a given entity. To define these, simply list them in an array assigned to the top-level `contactRoles` property.

See the [contacts tutorial](#contacts-tutorial) below for details on practical use.

Contact States [#contact-states]

Contacts may be in `draft`, `validated`, or `discarded` state. Contacts first enter the `draft` state on creation and can be explicitly validated, or set with `autoValidate` on creation. Versioning history is only kept for `validated` contacts.

Contacts may be `discarded` by the [merge feature](#merging-contacts).

<Callout>
  Customized contact validation will be enabled in a future plugin.
</Callout>

<span id="contacts-tutorial" />

Tutorial [#tutorial]

Suppose you would like to have an agent optionally associated with every account. You could start by defining a "Person" contact in your top-level configuration like the following, and declare "agent" as one of the recognized `contactRoles`:

```javascript
{
    // ...,
    contacts: {
        "Person": {
            "data": {
                "firstName": {
                    "type": "string"
                },
                "lastName": {
                    "type": "string"
                }
            }
        }
    },
    contactRoles: ["agent"]
}
```

Next, update your account configuration to specify what contact roles can or must be associated with the entity, and their associated types. For example, here is a simple `ConsumerAccount` definition that references the `agent` contact role:

```javascript
{
    "displayName" : "Consumer Account",
    "data" : {
        // ...
    },
    "contacts": {
        "agent?": ["Person"]
    }
}
```

In this case, we use [quantifiers](/configuration/general-topics/quantifiers) to indicate that an association with an `agent` is optional.

The value is an array so that other types of contacts could also be specified as valid types for that role in association with the entity.

After deployment, you can use the [Contacts API](/api/contacts) to create the contact, and then reference the `locator` or `staticLocator` when you create an account that should be associated with the agent. The following is a sample account creation request with a contact reference:

```javascript
{
    "type": "ConsumerAccount",
    "delinquencyPlanName": "Standard",
    "data": {
        "firstName": "Smitham",
        "lastName": "Lowell"
    },
    "contacts": [{
        "contactLocator": "{contactLocator}",
        "roles": ["agent"]
    }]
}
```

Contacts follow the same distinction between instance locators and static locators as elsewhere in the system. When you update a contact, its static locator remains constant, but the updated version obtains a new instance locator. Use static locators for contact associations if you don't need to associate specific contact versions with an entity; else, use instance locators. When you use static locators for contact associations, the static locator points to the latest instance of the contact.

<Callout>
  When <ApiLink name="getContact">fetching a contact</ApiLink>, you need to supply a locator, not a static locator. If you only have a static locator and want more information for a contact, use the static locator with the <ApiLink name="listContacts">list contacts</ApiLink> endpoint, which contains full contact entries for all versions of the contact.
</Callout>

Of course, you can associate your new contact with an existing account. There are contact management endpoints in the [Accounts API](/api/accounts), such as the ability to <ApiLink name="addAccountContact">add an account contact</ApiLink>.

<Callout>
  Validation of the account entity will be blocked if associated agent contacts have not been validated.
</Callout>

<span id="merging-contacts" />

Merging Contacts [#merging-contacts]

The <ApiLink name="mergeContacts" /> endpoint is available to facilitate duplicate contact cleanup. Simply provide the set of static locators for the duplicate contacts in the `contactLocators` array, and a target `mergeToContact` static locator for the set. When executed,

* All the contacts in `contactLocators` will be `discarded`.
* Discarded contact locators will be remapped to the new contact, so that contact lookups by discarded locator will return the new `mergeToContact` target. Contact references using instance locators will point to the latest contact revision with the `mergeToContact` static locator at the time of merging.

Searchability [#searchability]

By default, contacts are not searchable. To enable searches for a contact type, set the `defaultSearchable` property to `true`. Contact search configuration follows the same standards as for other entities; see the [Search Feature Guide](/features/search) for details.


## API Reference

ContactRef
Properties:
  abstract (boolean)
  extend (string)
  defaultSearchable (boolean)
  data (map<string, PropertyRef>, required)

# Jurisdictions



Jurisdictions represent areas governed by distinct government entities, such as U.S. states. Insurance product details may vary by jurisdiction based on government regulations or market characteristics.

To support this differentiation, quotes, policies, and resources can be associated with jurisdictions.

Resource Selection [#resource-selection]

Jurisdictions affect [resource selection](/configuration/resources/versioned-resource-selection) logic. The system executes the following logic when selecting resources:

1. Given a quote or policy, and the `staticName` of a resource, for each [resource group](/configuration/resources/versioned-resource-selection#key_concepts) with a `selectionStartTime` equal to or earlier than the current time:
   * The system will identify the resource instance associated with the jurisdiction that matches the jurisdiction associated with the quote or policy, if it exists in the resource group, and add it to a temporary list.
   * If no such resource instance exists in the resource group, the system will identify the resource instance that is not associated with any jurisdiction, if it exists in the resource group, and add it to the temporary list.

2. The system will then select the resource instance with the most recent `selectionStartTime` from the temporary list.

The [Resource Selector](/configuration/plugins/overview#resource_selector), [Document Selection Plugin](/configuration/plugins/document-selection), and the default document selection flow all execute the resource selection logic described above.

<Callout>
  Jurisdictions will be incorporated into future features, including producer management and tax management.
</Callout>

Configuration [#configuration]

Jurisdictions must be defined in the `jurisdictions` configuration object before they can be associated with quotes, policies, or resources. Each jurisdiction is represented by a map between the jurisdiction name and an optional <ApiLink name="JurisdictionRef" /> object, which can be used to specify the display name and display order.

For example:

```json
{
	"jurisdictions": {
		"CA": {
			"displayHints": {
				"displayName": "California",
				"displayOrder": 1
			}
		},
		"FL": {}
	}
}
```

<Callout type="warn">
  Once a new jurisdiction has been deployed, it will be permanently added to the system.
</Callout>

You can force a product to be associated with a jurisdiction by setting the `requiresJurisdiction` flag to `true` in the <ApiLink name="ProductRef" /> object. Enabling this flag will cause validation requests for quotes and policy transactions without an associated jurisdiction to fail.

For example:

```json
{
	"requiresJurisdiction": true
}
```

Implementation [#implementation]

Quotes and Policies [#quotes-and-policies]

Once your configuration changes have been deployed, you can specify the name of a jurisdiction to associate with a quote or policy in the `jurisdiction` field when using the Socotra API to create or update [quotes](/api/quotes/quotes) and policies. Quotes and policies can only be associated with a maximum of one jurisdiction.

Here's an example of the `jurisdiction` field when sending a request to the <ApiLink name="createQuote">Create a Quote</ApiLink> API endpoint:

```json
{
	"jurisdiction": "CA"
}
```

The <ApiLink name="updatePolicyJurisdiction">Update Policy Jurisdiction</ApiLink> API endpoint can be used to update the jurisdiction associated with a policy directly.

Resources [#resources]

You can specify the name of one or more jurisdictions to associate with resources such as [documents](/api/resources/document-resources), [tables](/api/resources/tables), and [secrets](/api/resources/secrets) when using the Socotra API to create or update resources.

Here's an example of the `jurisdiction` query parameter when sending a request to the <ApiLink name="createDocumentResource">Create a New Document Resource</ApiLink> API endpoint:

```
jurisdiction=CA&jurisdiction=FL
```

<Callout type="warn">
  No jurisdiction can appear more than once across resource instances with the same `staticName` within the same resource group.
</Callout>

See Also [#see-also]

* [Versioned Resource Selection](/configuration/resources/versioned-resource-selection)
* [Resource Selector](/configuration/plugins/overview#resource_selector)
* [Document Selection Plugin](/configuration/plugins/document-selection)
* <ApiLink name="JurisdictionRef" />
* <ApiLink name="ProductRef" />
* [Quotes API](/api/quotes/quotes)
* [Policies API](/api/policy-management/policies)
* [Resources API Index](/api/resources/resource-service)


# Migration



import Image from 'next/image';

Overview [#overview]

With Socotra Insurance Suite's dedicated migration service, you can put your entire book of business into the system in a precise, efficient way.

The basic migration process looks like this:

1. Deploy a configuration to the target tenant that will receive migrated data.
2. Convert your source data to the form specified in the <ApiLink name="AccountMigrationRequest" /> or <ApiLink name="MigrationRequest" />.
3. Upload your data to the appropriate migration service endpoint.
4. If necessary, address any errors reported during migration and resubmit problematic entities.

Migration Structure [#migration-structure]

You can easily import policies, accounts, invoices, payments, and disbursements from other systems by providing those entities in a form natural to the Socotra data model.

These are the top-level entities that you can provide in a migration request:

* Accounts
* Policies
* Invoices
* Payments
* Disbursements

<Callout>
  At this time, the migration service does not support importing quotes or unissued transactions. Such provisional business can be created via the usual API endpoints following migration. Additionally, transactions must be presented in order. To import policies with out-of-sequence (OOS) transactional history, first transform the data to eliminate OOS, presenting the migration service with your desired state sequence.
</Callout>

A policy is the atomic unit for a migration request: when you supply a policy, you should supply all necessary transaction history, along with any applicable invoices, payments, and disbursements. Once a policy has been migrated, it is a full-fledged policy in Socotra, and cannot be altered further through the migration service.

Since you may wish to import accounts, or already have accounts in the target tenant for which you would like to import data, the service offers two distinct entry points:

1. <ApiLink name="startMigration">Start Migration</ApiLink>: takes an
   <ApiLink name="AccountMigrationRequest" />
2. <ApiLink name="startMigrationForAccount">
     Start Migrations for an Existing Account
   </ApiLink>
   : takes a <ApiLink name="MigrationRequest" />

In either case, the migration request contains all information required for Socotra to create supplied entities in the platform. Where possible, essential relationships are conveyed in Socotra's natural hierarchy: a policy contains one or more terms, each of which contains one or more transactions, each of which may have one or more installments, and so on. This essential structure is reflected in the <ApiLink name="PolicyMigrationRequest" />. Likewise, <ApiLink name="InvoiceMigrationRequest" />, <ApiLink name="PaymentMigrationRequest" />, and <ApiLink name="DisbursementMigrationRequest" /> allow you to specify related sub-entities as children of the parent entity.

<Image src="/images/migration-guide/migration-request-overview.png" alt="migration request overview" width={747} height={618} unoptimized />

Billing Entities [#billing-entities]

Invoices, payments, and disbursements are not required for a migration request. If you specify installments but do not assign them to invoices provided in the migration request, the system will generate invoices for those installments, following typical system behavior for unbilled installments.

<ApiLink name="InvoiceMigrationRequest">Invoice migration requests</ApiLink>
with an `invoiceState` of `settled` will result in a settled invoice, even if
payments assigned to the invoice do not sum to the total amount due on the
invoice. The outstanding amount on any such invoice will be written off. As in
normal platform operation, payment amounts in excess of the total amount due
will go to the account balance.

If your target config has the [Auto Credit Application](/features/billing/auto-credit-application) feature enabled, you can use <ApiLink name="AccountingMigrationRequest" /> to tell the platform what the expected account balance is following migration, so that the platform takes the following actions automatically:

* Issuing a negative invoice if the post-migration balance is lower than expected.
* Issuing a positive invoice, paid with funds from the account balance, if the post-migration balance is higher than expected.

An <ApiLink name="AccountingMigrationRequest" /> expecting the result balance to be `$0` would look like this, in its <ApiLink name="AccountMigrationRequest" /> context:

```json
{
	// ...,
	"accounting": {
		"originalAccountBalances": {
			"USD": 0
		}
	}
	// ...,
}
```

<Callout>
  We recommend that you limit migration requests to 50 megabytes, which ensures rapid completion for a range of scenarios, such as "many policies with few transactions" or "few policies with many transactions". Contact your Socotra representative for performance and request size limit details relevant to your specific needs.
</Callout>

Bring Your Own Identifiers [#bring-your-own-identifiers]

Most migration request entities allow you the option to assign your own identifier to an `id` property. To specify a relationship that cannot be inferred from the migration hierarchy, such as an installment (contained in a transaction on a policy) that should be assigned to an invoice (a peer of policies in the migration request), you can assign your own identifiers to entities and refer to them elsewhere in the request. Socotra will convert custom identifiers to platform identifiers, maintaining referential integrity. Two migration endpoints expose the mappings from your own identifiers to Socotra identifiers:

* <ApiLink name="getMigrationMappings">
    Get Migration Mappings
  </ApiLink>
* <ApiLink name="getMigrationMappingsForAccount">
    Get Migration Mappings for Account
  </ApiLink>

Migration Management [#migration-management]

A migration request to <ApiLink name="startMigration" /> or <ApiLink name="startMigrationForAccount" /> will receive a <ApiLink name="MigrationResponse" /> with information that can be used to track the status of the migration, which is processed asynchronously. You can check on migration progress using the <ApiLink name="getMigrationSummary" /> endpoint.

<Callout>
  A forthcoming release will allow you to fetch migration events in the event stream and set up webhooks to listen for key events, eliminating the need for status polling.
</Callout>

If a migration is `processing`, you may pause it with <ApiLink name="pauseMigration" /> and resume it with <ApiLink name="resumeMigration" />. Any in-flight transactions will be fully processed before the pause takes effect, and you may interact with accounts and policies that had already been migrated prior to the pause. To view detailed lists of migrated entities, use the migration mappings endpoints.

Remediation [#remediation]

The migration service distinguishes between `failure` and `error` states: if any migrated entity in the request set fails validation -- for example, you supply an account to be migrated with some data that violates some rule in your validation plugin -- then the migration service will have a `migrationState` of `failed`. If a system error causes the migration to fail, then the `migrationState` will be `error`.

You can attempt to recover from an `error` state with the `recoverMigration` endpoint. For migration failures due to invalid data, you can follow this procedure:

1. Determine which specific elements failed, and why, with <ApiLink name="getMigrationFailures" />.
2. <ApiLink name="patchMigration">Patch the migration request</ApiLink>,
   supplying updated versions of the entities that failed validation.
3. Issue a `recoverMigration` request.

<Callout>
  Migration recovery for a `failure` state will return the same `failure` result if no <ApiLink name="patchMigration">patch</ApiLink> attempt has been made. This is true even if, after a failure due to validation errors, you deploy a configuration that removes validation rules that caused the failure. The [Migration Client](#migration-client) is especially helpful for failure recovery scenarios since it [automatically writes patch files to disk](#migration-client-patch-files), which you can modify or simply resubmit.
</Callout>

<span id="idempotency-key-guide" />

Idempotency Key [#idempotency-key]

Purpose [#purpose]

The migration service supports idempotent requests via the optional `X-Idempotency-Key` header. When you include an idempotency key, the first request starts a new migration as usual. Subsequent requests that use the same key (for that tenant) will reuse the existing migration instead of creating a new one.

In this way, the key allows you to safely retry a request after timeouts or network issues without duplicating work or double‑migrating data.

The header is **case-insensitive**: for example, `"test"` and `"TEST"` are treated as the same key.

Recommendation [#recommendation]

Use `X-Idempotency-Key` whenever your client might retry a migration request, especially for scenarios like these:

* The client times out waiting for a response from the migration service.
* The connection drops partway through a large payload.
* You are running migrations in an automated pipeline that can rerun failed jobs.

In all of these cases, re-sending the request body with the **same idempotency key** makes the operation safe: the service either continues the existing migration or returns its completed status **without starting a new migration**.

Example: Safely Retrying a Large Migration [#example-safely-retrying-a-large-migration]

Suppose you send a large file of account data, and your client times out. If the client never receives a response, you can retry with the same payload and the same `X-Idempotency-Key` value. The service will not create a second, duplicate migration; instead, it will treat it as the same logical request.

If you change the payload, you should also change the key so that the new migration is treated as a distinct operation.

Generating an Idempotency Key [#generating-an-idempotency-key]

The migration service does **not** generate keys for you. It is the **client’s responsibility** to:

* Generate a unique idempotency key value.
* Supply it on the **first** `POST` for a given logical migration.
* Reuse **exactly the same value** for any retries of that same logical migration.

Guidelines [#guidelines]

* Treat the key as an opaque token scoped to a single logical request (for example, "this specific input file to this endpoint on this tenant").
* Use a value that is resistant to collisions (such as a UUIDv4 or ULID) and easy for your tooling to log and correlate.
* Do not reuse the same key for different migration payloads. If the input data or target account set changes, generate a new key.

Because comparison is **case-insensitive**, you should either:

* Always generate lowercase (recommended), or
* Always normalize casing before sending, to avoid accidental mismatches in your own code.

Migration Tutorial [#migration-tutorial]

We'll walk through a simple case, showcasing the [Migration API](/api/migration) endpoints.

Prerequisites [#prerequisites]

1. Access to a Socotra environment, with configuration deployment and migration privileges
2. A [personal access token (PAT)](/api/business-accounts/authentication)

Get the sample config and source data [#get-the-sample-config-and-source-data]

You can find a sample configuration and source data for migration in this GitHub repository: [https://github.com/socotra/migration-tutorial](https://github.com/socotra/migration-tutorial).

The configuration is based on the "Blank" model you'll find in Configuration Studio. Deploy it to a tenant and record the tenant locator for subsequent API calls.

Make a migration request and check results [#make-a-migration-request-and-check-results]

You'll see a `convertedSource.json` file in the `converted` directory of the tutorial repository. Use it as the body of a <ApiLink name="startMigration">Start Migration</ApiLink> request.

After making the request, check the status with the <ApiLink name="getMigrationSummary">Get Migration Summary</ApiLink> endpoint. You'll see a result like this:

```json
{
	"locator": "01K04P56E46KN3DDY6695M2T9P",
	"migrationState": "finished",
	"processedAccounts": 1,
	"totalAccounts": 1
}
```

The migration has completed successfully. You can use the `locator` to fetch additional details, such as the mappings of source data to Socotra equivalents. If you submit a request to <ApiLink name="getMigrationMappings">Get Migration Mappings</ApiLink>, you'll see a result like this:

```json
{
	"listCompleted": true,
	"items": [
		{
			"migrationLocator": "01K04P56E46KN3DDY6695M2T9P",
			"accountLocator": "01K04P5750Z06AEMZN0XAT5SQF",
			"originalAccountId": "1234",
			"policies": {
				"01K04P576TNEFFR6R6N9W8GEGP": {
					"originalId": "policy_1000",
					"childrenMappings": {
						"01K04P576TNEFFR6R6N9W8GEGP": {
							"transactions": ["01K04P576TNEFFR6R6N9W8GEGP"]
						}
					},
					"migratedAt": "2025-07-14T14:41:54.681829Z"
				},
				"01K04P57H8RK5CV0STSH3CBDG9": {
					"originalId": "policy_1001",
					"childrenMappings": {
						"01K04P57H8RK5CV0STSH3CBDG9": {
							"transactions": [
								"01K04P57H8RK5CV0STSH3CBDG9",
								"01K04P57Q13EGHXWDJ72SAB9BF"
							]
						}
					},
					"migratedAt": "2025-07-14T14:41:54.975834Z"
				},
				"01K04P57SAXDE057CHYSS2MDZG": {
					"originalId": "policy_1002",
					"childrenMappings": {
						"01K04P57SAXDE057CHYSS2MDZG": {
							"transactions": [
								"01K04P57SAXDE057CHYSS2MDZG",
								"01K04P57SFMS0PJT9SZSTNPGR4",
								"01K04P57SFJFZ51GNN745KQGPG"
							]
						}
					},
					"migratedAt": "2025-07-14T14:41:55.229591Z"
				}
			}
		}
	]
}
```

Note how key entities such as accounts and policies are shown with their original IDs from the source data, with a clear indication of the corresponding locator in Socotra. For example, `policy_1002` was mapped to policy locator `01K04P57SAXDE057CHYSS2MDZG`. This makes it easy to understand how the source data maps to the Socotra rendition.

Handle a failed migration [#handle-a-failed-migration]

The migration API allows you to recover from errors and failures. An `error` `migrationState` arises if an issue arises on the platform side -- you can retry the migration without modifying the input data. A `failed` `migrationState` indicates that there was an issue with the input data.

The Migration API exposes <ApiLink name="getMigrationFailures">failure fetch</ApiLink>, <ApiLink name="patchMigration">patch</ApiLink>, and <ApiLink name="recoverMigration">recover</ApiLink> endpoints to address a "failed" `migrationState`. To see this sequence in action, we'll introduce a data error, make the migration request, fetch failure details, patch our data, and issue a recover request.

Remove the `firstName` entry from the `accountData` in the original migration request, leaving the account with just a `lastName`. Submit the migration request. When you get the migration summary, you should see a `failed` state:

```json
{
	"locator": "01K04V1HK97GYPWHP48PNDQQRT",
	"migrationState": "failed",
	"processedAccounts": 1,
	"totalAccounts": 1
}
```

To see details, make a request to <ApiLink name="getMigrationFailures">Get Migration Failures</ApiLink>. You should see that the supplied data failed to pass validation, with enough information to identify the problematic account:

```json
{
	"listCompleted": true,
	"items": [
		{
			"accountLocator": "01K04V1J98ED34S2DRDBZMCTD1",
			"accountOriginalId": "1234",
			"accountError": {
				"originalId": "1234",
				"errors": {
					"validationItems": [
						{
							"elementType": "SampleAccount",
							"errors": [
								"Non optional property 'sampleAccount.firstName' is missing"
							]
						}
					],
					"success": false
				}
			}
		}
	]
}
```

In order to rectify this issue so that the account migrates successfully, you'll use the <ApiLink name="patchMigration">Patch an Existing Migration Request</ApiLink> endpoint. Even though the account has not been migrated, it has been assigned a provisional locator: `01K04V1J98ED34S2DRDBZMCTD1`. We will use this locator to indicate to the system which account is to be patched. Here's the patch body:

```json
{
	"defaultCreatedBy": "dc68c494-6918-487a-bf08-58c2983175dc", // update with your uuid
	"accountLocator": "01K04V1J98ED34S2DRDBZMCTD1", // update with your account locator
	"accountData": {
		"id": "1234",
		"accountType": "SampleAccount",
		"data": {
			"firstName": "Ambrose",
			"lastName": "Bierce"
		},
		"billingLevel": "policy",
		"createdAt": "2024-08-29T22:40:11.538Z"
	}
}
```

After submitting the patch request and once again checking the migration status, you will see that the errors list is now empty:

```json
{
	"listCompleted": true,
	"items": []
}
```

Next, submit a <ApiLink name="recoverMigration">Recover Migration</ApiLink> request. **Staged updates via data patches will not be applied to a migration until you issue a migration recovery request.**

Upon checking migration status, you will see it has succeeded:

```json
{
	"locator": "01K04V1HK97GYPWHP48PNDQQRT",
	"migrationState": "finished",
	"processedAccounts": 1,
	"totalAccounts": 1
}
```

And that's it! So far, you've

* Learned about the primary migration endpoints
* Submitted an account migration request
* Submitted an erroneous migration request, examined the reason for failure, fixed the data, and "recovered" the migration

Using a converter [#using-a-converter]

Of course, in a typical migration scenario, you'll have raw data that needs to be converted to the Migration API input format. In the tutorial GitHub repository, you'll see these directories:

* `source`: a sample set of raw data from a hypothetical policy administration service
* `apps/converter`: a sample converter, written in Python, that converts the source data to the Socotra Migration API format

You can run the converter to transform the source data into a format ready for input into the Migration API, and also execute the checker (`apps/checker`) to validate results in Socotra. Since such tasks -- fetching data from a source system, transforming it, sending it to the Migration API, and performing any post-migration tests and related tasks -- follow a predictable pattern, we have created a Migration Client to coordinate those steps. Read on to learn more about the Migration Client and how it works.

<span id="migration-client" />

Migration Client [#migration-client]

We publish a Migration Client that orchestrates common migration pipeline tasks, helping you to get your data into Socotra as quickly as possible. Here's how it looks from a high-level perspective:

<Image src="/images/migration-guide/migration-client-diagram.png" alt="migration client diagram" width={746} height={571} unoptimized />

* A: **Raw data source on disk**. *We may augment the client with connectors to fetch from other source types, as demand warrants*.
* B: **Migration Client**, serving as an orchestrator that fetches raw source data, shepherds it through conversion and input into the migration API, and optionally calls post-migration checks.
* C: **Converter**, a custom application that turns raw source data into the format expected by the Migration API, and which conforms to the target tenant configuration.
* D: **Coda**, a custom application capable of performing post-migration activities, such as inspecting data after migration to ensure expected results. While we depict checks as interacting with the EC API, it could conceivably connect to other services, such as [Data Lake](/features/reporting/datalake), to perform tasks.

The Migration Client abstracts common migration patterns, isolating necessary custom logic to specific components. As long as your converter and coda apps are exposed as callable binaries, placing results on disk, they can be used with the migration client.

Obtaining the Client [#obtaining-the-client]

The Migration Client can be downloaded as a [package ](https://github.com/socotra/config-sdk-template/packages/2312294) from our [Config SDK Template repository ](https://github.com/socotra/config-sdk-template):

<Image src="/images/migration-guide/migration-client-package-location.png" alt="migration client package location" width={600} height={763} unoptimized />

On the package page, you'll just need `migration-client-[version]-distribution.zip`, listed under "Assets".

After unzipping the archive, you should be able to confirm that you can run the client by navigating to the `bin` directory and running the `./migrate` command:

```bash
(.venv) alice@machine1 bin % ./migrate
Usage: ./migrate <path-to-config-file>

Options:
<path-to-config-file>   Specify the location of the configuration YAML file.
help                    Show this help message.

Configuration file help:
help pipeline            Show configuration details for the Migration Pipeline.
help service-api         Show configuration details for the Service API.
help converter           Show configuration details for the Migration Request Converter.
help processor           Show configuration details for the Request Processor.
help patcher             Show configuration details for Patch Migration Failures.
help coda                Show configuration details for the Post Migration.
```

As you can see from the default screen, the client takes a YAML configuration file as input. The YAML file tells the migration client which components should be run, and what the command-line arguments to those components are. Follow the tutorial below for a complete example of a working migration.

<Callout>
  The Migration Client requires a Java 17+ runtime. If you encounter an error while attempting to execute the launch script, make sure that you have a JRE installed on your system.
</Callout>

Migration Client Tutorial [#migration-client-tutorial]

In this tutorial, we'll set up a migration to Socotra, pretending we have raw source data from another system that needs to be converted to the Socotra format and sent to the Migration API.

Prerequisites [#prerequisites-1]

* Migration Client
* Python 3.x for the sample converter and checker apps

After you've obtained the Migration Client package and confirmed that you can run it, clone or download this repository: [https://github.com/socotra/migration-tutorial](https://github.com/socotra/migration-tutorial). This repository contains a basic sample config, mock source data from a chimerical policy administration system, a converter app, and a coda app.

```text
├── apps
│   ├── coda
│   └── converter
├── config
└── source
```

The configuration is based on our simple "Blank Config", available in Configuration Studio.

After deploying the configuration, you're ready to start configuring the Migration Client.

Configuring the Migration Client [#configuring-the-migration-client]

The Migration Client package contains the following configuration template in `migrate-properties.yaml`:

```yaml
migration:
  pipeline:
    converter-enabled: true
    processor-enabled: true
    patcher-enabled: true
    coda-enabled: true
  converter:
    application:
    command: # a command-line statement; in the example below, a primary "app" has two subcommands, "analyze" and "convert"
      - <absolute path>/path/to/app
      - analyze
      - <absolute path>/path/to/sample/data
      - convert
      - '-o<absolute path>/path/to/converter/output' # example of passing an arguments to a subcommand
      - '<absolute path>/path/to/data'
  service-api:
    url: https://api-ec-sandbox.socotra.com
    personal-access-token: <PAT>
    tenant-locator: <tenant_locator>
  processor:
    concurrency: 10 # number of concurrent requests
    poll-interval-duration: 5s # max time to wait on migration API response to a migration request
    input-requests-folder: <absolute path>/path/to/converter/output
    output-summary-folder: <absolute path>/path/to/processor-summary
  patcher:
    input-requests-folder: <absolute path>/path/to/converter/output
    input-summary-file: <absolute path>/path/to/processor-summary/migration-result.csv # default result name is "migration-result.csv"
    output-patch-requests-folder: <absolute path>/path/to/output-patch-summary/
  coda:
    application:
    command:
      - <absolute path>/path/to/checker
      -  # other args for checker...
```

Copy this configuration template to a preferred location.

First, we'll set up the converter. In a terminal, go to the `apps/converter` directory, and perform the usual steps to ready a Python script for execution, like this:

```bash
python3 -m venv .venv     # create a virtual environment
source .venv/bin/activate # activate the environment
```

Since this converter implementation only uses facilities from the Python standard library, there's no need to install any requirements. **You should operate within this active environment for the remainder of this tutorial**.

You can verify that the converter is ready for work by typing `python converter.py`. You should see the following:

```bash
usage: convert.py [-h] --defaultCreatedBy DEFAULTCREATEDBY input_dir output_file
convert.py: error: the following arguments are required: input_dir, output_file, --defaultCreatedBy
```

While we could execute the converter on the command line, we'll set up the Migration Client to call the converter for us in the context of a complete migration pipeline. To do so, let's first make sure we have all the values we need:

1. `DEFAULTCREATEDBY`: this is the UUID of a user who will be treated as the default creator of a migration record if another is not specified. For testing purposes, just issue a <ApiLink name="fetchMyUserDetails">Fetch My User Details</ApiLink> request and use your UUID.
2. `input_dir`: this is the source data directory. In our case, it'll be the absolute path to the `source` directory in your local copy of the tutorial repository.
3. `output_file`: the absolute path to a file where the converter should write its output. The output is what the migration client will send to the Migration API.

With this information, you're ready to run the Migration Client and have it call the converter on your behalf. Suppose the argument values are as follows:

1. `DEFAULTCREATEDBY`: `dc68c494-6918-487a-bf08-58c2983175dc`
2. `input_dir`: `/Users/alice/projects/migration-tutorial/source`
3. `output_file`: `/Users/alice/projects/migration-tutorial/converted-data.json`

Then we can update the first portion of the Migration Client YAML as follows:

```yaml
migration:
  pipeline:
    converter-enabled: true
    processor-enabled: false
    patcher-enabled: false
    coda-enabled: false
  converter:
    application:
    command: # a command-line statement; in the example below, a primary "app" has two subcommands, "analyze" and "convert"
      - python
      - /Users/alice/projects/migration-tutorial/apps/converter/convert.py
      - '--defaultCreatedBy=dc68c494-6918-487a-bf08-58c2983175dc'
      - '/Users/alice/projects/migration-tutorial/source'
      - '/Users/alice/projects/migration-tutorial/converted-data.json'
```

Note that we have disabled the other parts of the pipeline (processor, patcher, coda) for now. When you run the Migration client from the command line (`./migrate` in `bin`), passing it the path to your YAML configuration, you should see something like this:

```bash
(.venv) alice@machine1 bin % ./migrate /Users/alice/migration-tutorial-config-demo/migrate-properties.yaml
2025-07-15 17:27:53.443 [main] INFO  c.s.m.c.s.pipeline.MigrationPipeline - Executing step ApplicationConverter
2025-07-15 17:27:53.445 [main] INFO  c.s.m.client.services.CommandRunner - building external process from [python, /Users/alice/projects/migration-tutorial/apps/converter/convert.py, --defaultCreatedBy=dc68c494-6918-487a-bf08-58c2983175dc, /Users/alice/projects/migration-tutorial/source, /Users/alice/projects/migration-tutorial/converted.json]
2025-07-15 17:27:53.455 [main] INFO  c.s.m.client.services.CommandRunner - started process  for command [python, /Users/alice/projects/migration-tutorial/apps/converter/convert.py, --defaultCreatedBy=dc68c494-6918-487a-bf08-58c2983175dc, /Users/alice/projects/migration-tutorial/source, /Users/alice/projects/migration-tutorial/converted.json]
Wrote 1 account records to /Users/alice/projects/migration-tutorial/converted.json
2025-07-15 17:27:53.575 [main] INFO  c.s.m.client.services.CommandRunner - process completed
```

If you check `converted.json`, you'll see the expected converter output.

Next, let's have a look at the processor.

Configuring the processor [#configuring-the-processor]

The processor component sends converted migration input files to the Migration API. It can be configured to make concurrent requests, cutting down on migration time, and can optionally create "patch" files automatically for records that failed migration and which can be resubmitted with corrected data.

Under the `service-api` portion of the client configuration, you'll need to specify the base API URL, a personal access token with appropriate privileges, and the target tenant locator. Then specify the location of your converted data in `input-requests-folder`, and the output location for processor records in `output-summary-folder`. Finally, enable the processor by setting `processor-enabled` to `true` (you can also set `converter-enabled: false` since, if you are following this tutorial in order, you already have converted files ready for import to Socotra).

Once you have taken these steps, run the Migration Client again. You should see output like the following:

```bash
2025-07-16 10:02:48.942 [main] INFO  c.s.m.c.s.pipeline.MigrationPipeline - Executing step RequestsProcessor
2025-07-16 10:02:48.946 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Processing file: converted-data.json
2025-07-16 10:02:50.021 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Migration[01K09RQ3AQAVXYPX4C2QCZ4YQ5] started for file converted-data.json
2025-07-16 10:02:50.113 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Migration[01K09RQ3AQAVXYPX4C2QCZ4YQ5] in progress totalAccounts=1 processedAccounts=0
2025-07-16 10:02:55.210 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Migration[01K09RQ3AQAVXYPX4C2QCZ4YQ5] completed with state: finished
2025-07-16 10:02:55.213 [main] INFO  c.s.m.c.s.p.RequestsProcessor - All tasks completed
2025-07-16 10:02:55.213 [main] INFO  c.s.m.c.s.p.RequestsProcessor - Processed 1 files
```

You should also see a `migration-result.csv` in the directory you specified for processor output. This file will contain contents like the following:

```text
converted-data.json,01K09RQ3AQAVXYPX4C2QCZ4YQ5,finished
```

The first column is the converted file name, the second is the migration locator corresponding to that input, and the third column is the status. The `finished` status indicates that this migration was successful. From here, you can <ApiLink name="getMigrationMappings">fetch mappings</ApiLink> to identify the equivalent entity locators on the tenant.

<span id="migration-client-patch-files" />

Using patch files [#using-patch-files]

To demonstrate the use of patch files, we'll introduce a minor error in our source data, and have the Migration Client run a new conversion and migration processing step.

First, in the configuration YAML, set `converter-enabled`, `processor-enabled`, and `patcher-enabled` to `true`. In the `patcher` section, set `input-requests-folder` to the absolute path of the converted data directory, the `input-summary-file` to the absolute path to `migration-result.csv`, and `output-summary-folder` to the location to place patch files.

Next, in the source data, remove the `lastName` from the account record (`source/accounts/account-1234.json`).

Rerun the Migration Client. Towards the end of the run, you should see entries like this indicating that patch files have been written to help address the migration failure:

```bash
2025-07-16 10:20:21.793 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Processing file: converted-data.json
2025-07-16 10:20:22.398 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Migration[01K09SQ7BBJGFZRXHYYZVSAR66] started for file converted-data.json
2025-07-16 10:20:22.493 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Migration[01K09SQ7BBJGFZRXHYYZVSAR66] in progress totalAccounts=1 processedAccounts=1
2025-07-16 10:20:27.592 [pool-2-thread-1] INFO  c.s.m.c.s.p.RequestsProcessor - Migration[01K09SQ7BBJGFZRXHYYZVSAR66] completed with state: failed
2025-07-16 10:20:27.596 [main] INFO  c.s.m.c.s.p.RequestsProcessor - All tasks completed
2025-07-16 10:20:27.597 [main] INFO  c.s.m.c.s.p.RequestsProcessor - Processed 1 files
2025-07-16 10:20:27.597 [main] INFO  c.s.m.c.s.pipeline.MigrationPipeline - Executing step RequestsPatcher
2025-07-16 10:20:27.606 [main] INFO  c.s.m.c.s.patcher.RequestsPatcher - Processing failed migration 01K09SQ7BBJGFZRXHYYZVSAR66 with request file converted-data.json
2025-07-16 10:20:27.751 [main] INFO  c.s.m.c.s.patcher.RequestsPatcher - Saving patch failures for 01K09SQ7BBJGFZRXHYYZVSAR66/01K09SQ7H0M7QCZ1Q02DQ45G10
2025-07-16 10:20:27.763 [main] INFO  c.s.m.c.s.patcher.RequestsPatcher - Saving patch request for 01K09SQ7BBJGFZRXHYYZVSAR66/01K09SQ7H0M7QCZ1Q02DQ45G10
```

You'll see two files in the patch directory: an `<entityLocator>-failures.json`, and `<entityLocator>.json`. Note that in this case, the entity locator is for the problematic account locator record. The `-failures.json` file details reasons for migration failure, and the corresponding `<entityLocator>.json` file is a ready-made template that you can feed back into the Migration API to get the record to succeed.

Let's have a look at `<entityLocator>-failures.json`:

```json
{
	"accountLocator": "01K09SQ7H0M7QCZ1Q02DQ45G10",
	"accountOriginalId": "1234",
	"accountError": {
		"originalId": "1234",
		"errors": {
			"validationItems": [
				{
					"elementType": "SampleAccount",
					"errors": [
						"Non optional property 'sampleAccount.lastName' is missing"
					]
				}
			]
		}
	}
}
```

No surprises here. Let's enter the last name into the corresponding patch JSON:

```json
{
	"defaultCreatedBy": "dc68c494-6918-487a-bf08-58c2983175dc",
	"accountLocator": "01K09SQ7H0M7QCZ1Q02DQ45G10",
	"accountData": {
		"id": "1234",
		"accountType": "SampleAccount",
		"data": {
			"firstName": "Ambrose",
			"lastName": "Bierce"
		},
		"createdAt": "2024-08-29T22:40:11.538Z"
	}
}
```

Now you can use this as the body of a <ApiLink name="patchMigration">patch migration request</ApiLink>. When you do so, you'll get this response:

```json
{
	"accountLocator": "01K09SQ7H0M7QCZ1Q02DQ45G10"
}
```

After staging patches, you must explicitly attempt a migration recovery with the <ApiLink name="recoverMigration">Recover Migration</ApiLink>. When you issue this request, you should get a `204` response. You can then affirm that the migrated account has succeeded by checking the <ApiLink name="getMigrationSummary">Get Migration Summary</ApiLink> endpoint:

```json
{
	"locator": "01K09SQ7BBJGFZRXHYYZVSAR66",
	"migrationState": "finished",
	"processedAccounts": 1,
	"totalAccounts": 1
}
```

Using Coda [#using-coda]

The Migration Client can also optionally call an application to run after migration. You just need to configure the `coda` portion of the configuration, in much the same way that you configured the `converter`. This can be useful to run custom validation checks and to perform any post-migration tasks via the Socotra API.

To use the sample post-migration application in the tutorial (`apps/checks/checks.py`), you'll need to install the Python prerequisites (`pip install -r requirements.txt` from the `apps/checks` directory). After you've done that, you can update the `coda` config like this:

```yaml
coda:
  application:
  command:
    - python
    - /alice/projects/migration-tutorial/apps/checks/checks.py
    - '--tenant-locator=516...'
    - '--auth-token=SOCP_01...'
    - '--source-data=/alice/projects/migration-tutorial/source'
    - '--base-url=https://api-kernel-dev.socotra.com/'
    - '-o/alice/projects/migration-tutorial/checksreport.txt'
    - '/alice/projects/migration-tutorial/processor-summary/migration-result.csv'
```

If you run the entire migration attempt again, you'll see this line appear:

```bash
All migrations passed checks successfully.
```

The sample checks app simply writes success to the console, after making some comparisons between source data and the migration results. In order to do so, it fetches mappings from the Migration API; check the source code for details.

In this Migration Client tutorial, you have completed the primary migration tasks:

1. Setting up the configuration and toggling pipeline components
2. Calling a converter and passing arguments via the configuration
3. Using the processor and patch files for error remediation
4. Calling a post-migration application for follow-up tasks, such as result verification

Note that the Migration Client is agnostic with respect to the `converter` and `coda` interfaces: if you have an application and can pass it some arguments, you can configure the Migration Client to call it as part of the migration pipeline.


# Previews



Socotra enables users to preview the outcome of certain key operations without committing to the changes.

Overview [#overview]

As detailed in the feature guides for [Quotes](/features/policy-quotation/quotes) and [Policy Transactions](/features/policy-management/policy-transactions), the results of data validation, pricing, and underwriting are persisted once the entity is successfully transitioned to that step of the lifecycle.
For many entities in the system, once they have transitioned to or beyond the `validated` state, their extension data becomes immutable, which may prove too rigid for certain quoting experiences.

To provide implementers with flexibility in developing tailored experiences for selling and servicing policies, Socotra enables **previews** of the results of certain key **Quote** and **Policy Transaction** operational functions, including:

* Validation
* Pricing
* Underwriting
* Invoicing

In most cases, this preview can be executed in both a `stateful` or `stateless` fashion.

Stateful Preview [#stateful-preview]

In this context, "stateful preview" refers to a request that the system produce what the result of some state transition **will be**, for **an entity (quote or transaction) that has already been created and stored in the system**. This is achieved by setting the `stateless` boolean query parameter to `true`.

**Example**

Request a preview of the validation result for an existing quote that is in a draft state, without advancing to the validated state:

```
PATCH /policy/{tenantLocator/quotes/{quoteLocator}/validate?stateless=true
```

<span id="StatelessPreview" />

Stateless Preview [#stateless-preview]

"Stateless preview" refers to a request that the system produce what the result of some key function **would be**, for **an entity (quote or transaction) that has not yet been created in the system**.

For example, before asking the system to persist a draft quote via a <ApiLink name="createQuote">Create Quote</ApiLink> request, a user can use the same <ApiLink name="QuoteCreateRequest">request payload</ApiLink> to have the system show what the price for the hypothetical quote would be, without having to create and store the entity or the price.

In order for the system to produce a preview of a hypothetical policy transaction, the underlying base policy must exist, and be specified in the stateless preview request.

**Example**

Request a price preview for a hypothetical quote that has not yet been created in the system:

```
POST /policy/{tenantLocator}/quotes/pricePreview
```

Request a preview of the underwriting result for a hypothetical transaction that has not yet been created in the system:

```
POST /policy/{tenantLocator}/policies/{policyLocator}/{transactionType}/underwritePreview
```

<Callout>
  In order for the system to produce either a `stateful` or `stateless` preview result for pricing or underwriting, it is necessary that the request entity would pass validation.
</Callout>

<span id="billing-previews" />

Billing Previews [#billing-previews]

Often insureds will want to know the specific details of payments they will be required to make, given a prospective quote or policy transaction. Socotra enables this by extending the preview capability to the billing service in both a `stateful` and `stateless` manner.

A `stateful` preview of prospective invoices may be generated for a prospective quote or policy transaction, given that the quote or policy transaction has been created and is in a `priced` state. See the <ApiLink name="previewInvoicesForQuote" /> and <ApiLink name="previewInvoicesForTransaction" /> endpoints in the [Invoices API](/api/billing/invoices) for details.

A `stateless` preview of prospective installments or invoices may be generated for a hypothetical quote by providing the results of its stateless pricing preview in the request. See the <ApiLink name="previewInstallmentsForStatelessQuote" /> endpoint in the [Installments API](/api/billing/installments) and the <ApiLink name="previewInvoicesForStatelessQuote" /> endpoint in the [Invoices API](/api/billing/invoices) for details.


# Producer Management



import Image from 'next/image';

Producer management refers to a set of features within Socotra designed to support producers such as brokers and agents.

A producer can refer to an individual or an organization, including individuals within an organization. Each producer is associated with one or more producer codes, which can be used to categorize the work performed by a producer. Only one producer can be associated with a given producer code. Each producer can specify a parent producer, forming a producer hierarchy.

Quotes and policies can be associated with a maximum of one producer code at a time.

Producers and producer codes can contain extension [data](/configuration/data-extensions/overview). Extension data for producers and producer codes support [media](/features/work-management/media) data.

This feature set is under development and will eventually support features such as licensing, appointments, and jurisdictions.

The following functionality is currently supported:

* Creating and modifying producers and producer codes via API requests
* Modifying producers and producer codes within the [Precommit Plugin](/configuration/plugins/precommit)
* Validating producers and producer codes within the [Validation Plugin](/configuration/plugins/validation)

Lifecycle [#lifecycle]

The following diagram illustrates the lifecycle for both producers and producer codes:

<Image src="/images/producer-management/lifecycle.png" alt="Producer and producer code lifecycle" width={500} height={279} unoptimized />

Producers and producer codes begin in the `draft` state after creation and will move to the `validated` state following a successful validation request.

Producers and producer codes can be moved to the `suspended` state to temporarily prevent them from being used until they are moved back to the `validated` state following a successful unsuspend request. Once producers and producer codes are moved to the `retired` or `discarded` state, they cannot be moved back to the `validated` state and cannot be used again.

<Callout>
  Producer codes cannot be discarded if they are currently associated with a quote that has advanced beyond the `draft` state or a policy.
</Callout>

Configuration [#configuration]

Before producers and producer codes can be created, they must be defined within the `producerManagement` <ApiLink name="ConfigurationRef">configuration</ApiLink> object.

For example:

```json
{
	"producerManagement": {
		"producers": {
			"ExampleProducer": {
				"abstract": true,
				"extend": "AnotherProducer",
				"data": {},
				"defaultSearchable": false
			}
		},
		"producerCodes": {
			"ExampleProducerCode": {
				"abstract": true,
				"extend": "AnotherProducerCode",
				"numberingPlan": "ExampleNumberingPlan",
				"numberingString": "ExampleText",
				"data": {},
				"defaultSearchable": false
			}
		}
	}
}
```

Producers and producer codes can be defined as `abstract`, meaning they cannot be created directly. Producers and producer codes can inherit data from the producer or producer code specified in the `extend` field.

Producer codes can be automatically generated based on the `numberingPlan` and `numberingString` specified in the configuration. We strongly recommend using a separate numbering plan for each producer code type to avoid potential duplication of producer codes. See the [Entity Numbering](/configuration/general-topics/entity-numbering) feature guide for more information.

Extension [data](/configuration/data-extensions/overview) can be defined in the `data` field.

The `defaultSearchable` field can be used to modify [search](/features/search) behavior.

Create a Producer [#create-a-producer]

Once your configuration changes have been deployed, create a producer using the <ApiLink name="createProducer">Create Producer</ApiLink> API endpoint.

For example:

```json
{
	"type": "ExampleProducer"
}
```

The `type` field refers to the name of a producer defined in the configuration. The `parentLocator` field can be used to specify a parent producer, forming a producer hierarchy.

For example:

```json
{
	"type": "ExampleProducer",
	"parentLocator": "01CH383XHA23A"
}
```

Producer details can be updated by using the <ApiLink name="updateProducer">Update Producer</ApiLink> API endpoint.

Use the <ApiLink name="validateProducer">Validate Producer</ApiLink> API endpoint to validate a producer.

Refer to the [Producer Management API](/api/producer-management) index for additional API endpoints.

Create a Producer Code [#create-a-producer-code]

The <ApiLink name="createProducerCode">Create Producer Code</ApiLink> API endpoint can be used to create a producer code.

For example:

```json
{
	"type": "ExampleProducerCode",
	"code": "9217262"
}
```

The `producerLocator` request parameter identifies the producer that will be associated with the producer code. Producer code details can be updated by using the <ApiLink name="updateProducerCode">Update Producer Code</ApiLink> API endpoint.

The `type` field refers to the name of a producer code defined in the configuration. The optional `code` field refers to the producer code. The producer code must be unique. If no producer code is specified, a producer code will be automatically generated based on the [numbering plan](/configuration/general-topics/entity-numbering) specified in the configuration for the producer code `type`.

Use the <ApiLink name="validateProducerCode">Validate Producer Code</ApiLink> API endpoint to validate a producer code.

Refer to the [Producer Management API](/api/producer-management) index for additional API endpoints.

Associate a Producer Code with a Quote or Policy Transaction [#associate-a-producer-code-with-a-quote-or-policy-transaction]

You can associate a producer code with a quote by adding the following field to the top level of the request object when <ApiLink name="createQuote">creating a quote</ApiLink> or <ApiLink name="updateQuote">updating a quote</ApiLink>:

```json
{
	"producerCode": "9217262"
}
```

The `producerCode` value refers to the `code` value that was used when creating the producer code.

Producer codes associated with a policy can be updated through the <ApiLink name="changePolicy">Create a Policy Change Transaction</ApiLink> API endpoint or any endpoint that accepts a <ApiLink name="ProducersChangeInstructionCreateRequest" /> request object.

Here's an example of a request for the Create a Policy Change Transaction API endpoint:

```json
[
	{
		"action": "producers",
		"setProducerCode": "Example Code 2", // Optional - Update the producer code
		"clearProducerCode": false // Optional - Clear the producer code
	}
]
```

Producer Code of Record [#producer-code-of-record]

If a policy has an associated producer code, the policy will also be associated with a producer code of record, which refers to the original producer code for a term. The producer code of record will be set to the current producer code when a renewal transaction is <ApiLink name="issueTransaction">issued</ApiLink>.

The producer code of record associated with a policy can be updated manually through the <ApiLink name="changePolicy">Create a Policy Change Transaction</ApiLink> API endpoint or any endpoint that accepts a <ApiLink name="ProducersChangeInstructionCreateRequest" /> request object. Changes will be applied to a policy once a transaction is <ApiLink name="issueTransaction">issued</ApiLink>.

Here's an example of a request for the Create a Policy Change Transaction API endpoint:

```json
[
	{
		"action": "producers",
		"setProducerCodeOfRecord": "Example Code 3", // Optional - Update the producer code of record
		"revertProducerCodeOfRecord": false // Optional - Set the producer code of record to the current producer code
	}
]
```

<Callout>
  If the `setProducerCodeOfRecord` value is set to the current producer code value, the system will instead process the request as if the `revertProducerCodeOfRecord` value was set to `true` once the transaction is issued.
</Callout>

Producer Code History [#producer-code-history]

The <ApiLink name="fetchPolicySnapshot" /> API endpoint can be used to view the producer code and producer code of record values associated with a policy at a specified point in time. These snapshots account for [out-of-sequence transactions](/features/policy-management/out-of-sequence-transactions) and the reapplication of policy renewals.

Here's an example of the `date` query parameter:

```text
2025-01-01T00:00:00Z
```

Add an Underwriting Flag if the Producer or Producer Code is Invalid [#add-an-underwriting-flag-if-the-producer-or-producer-code-is-invalid]

If a producer code is associated with a quote or policy transaction, but the producer code, its associated producer, or any of the producer's parent producers are not in the `validated` state, <ApiLink name="underwriteQuote">underwriting</ApiLink> requests for the quote or policy transaction will fail, and the system will automatically add an [underwriting](/features/underwriting) flag to the quote or policy transaction. This underwriting flag can be customized through the `underwritingFlag` <ApiLink name="UnderwritingFlagRef">configuration</ApiLink> object.

For example:

```json
{
	"producerManagement": {
		"producers": {
			"ExampleProducer": {
				"abstract": true,
				"extend": "AnotherProducer",
				"data": {},
				"defaultSearchable": false
			}
		},
		"producerCodes": {
			"ExampleProducerCode": {
				"abstract": true,
				"extend": "AnotherProducerCode",
				"numberingPlan": "ExampleNumberingPlan",
				"numberingString": "ExampleText",
				"data": {},
				"defaultSearchable": false
			}
		},
		"underwritingFlag": {
			"level": "none", // none | block | reject | decline | info
			"tag": "Example tag", // Default is "Invalid Producer Qualification"
			"note": "Example note"
		}
	}
}
```

This underwriting flag can be removed from a quote or policy transaction like any other flag. This allows you to complete the underwriting process even if the producer or producer code is invalid.

If an `underwritingFlag` configuration is not provided, the system will automatically generate a configuration with `level` set to `info`.

See the [Underwriting](/features/underwriting) and [Underwriting Plugin](/configuration/plugins/underwriting) feature guides for more information on underwriting flags.

Plugins [#plugins]

Precommit Plugin [#precommit-plugin]

The Precommit Plugin can be used to modify the value of a producer or producer code before saving it to the database. See the [Precommit Plugin](/configuration/plugins/precommit) feature guide for more information.

For example:

```java
public class PreCommitPluginImpl implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(PreCommitPluginImpl.class);

    @Override
    public AgencyProducer preCommit(AgencyProducerRequest request) {
        AgencyProducer producer = request.producer();

        return request.producer().toBuilder()
            .data(producer.data().toBuilder().email("first.agency@socotra.com").build())
            .build();
    }

    @Override
    public SubAgencyProducer preCommit(SubAgencyProducerRequest request) {
        SubAgencyProducer producer = request.producer();

        return request.producer().toBuilder()
            .data(producer.data().toBuilder().email("first.subagency@socotra.com").build())
            .build();
    }

    @Override
    public CaliforniaProducerCode preCommit(CaliforniaProducerCodeRequest request) {
        CaliforniaProducerCode producerCode = request.producerCode();

        return request.producerCode().toBuilder()
            .data(producerCode.data().toBuilder().description("added by preCommit").build())
            .build();
    }
}
```

Validation Plugin [#validation-plugin]

The Validation Plugin can be used to execute custom validation logic on a producer or producer code. See the [Validation Plugin](/configuration/plugins/validation) feature guide for more information.

For example:

```java
public class ValidationPluginImpl implements ValidationPlugin {
    private static final Logger log = LoggerFactory.getLogger(ValidationPluginImpl.class);

    @Override
    public ValidationItem validate(AgencyProducerRequest request) {
        AgencyProducer producer = request.producer();

        if (!producer.data().status().equalsIgnoreCase("active")) {
            return ValidationItem.builder()
                .locator(producer.locator())
                .elementType(producer.type())
                .addError("producer must be active")
                .build();
        }

        return ValidationItem.builder().build();
    }

    @Override
    public ValidationItem validate(CaliforniaProducerCodeRequest request) {
        CaliforniaProducerCode producerCode = request.producerCode();

        if (!producerCode.data().status().equalsIgnoreCase("active")) {
            return ValidationItem.builder()
                .locator(producerCode.locator())
                .elementType(producerCode.type())
                .addError("producer code must be active")
                .build();
        }

        return ValidationItem.builder().build();
    }
}
```

See Also [#see-also]

* [Producer Management API](/api/producer-management)
* <ApiLink name="ProducerManagementRef" />
* [Data Extensions](/configuration/data-extensions/overview)
* [Precommit Plugin](/configuration/plugins/precommit)
* [Validation Plugin](/configuration/plugins/validation)
* [Underwriting](/features/underwriting)
* [Underwriting Plugin](/configuration/plugins/underwriting)


# Schedules (Beta)



<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

Overview [#overview]

Schedules are purpose-built to support insurance products that need to manage very large lists of like-typed items such as fleets of vehicles, property inventories, or collections of valuable articles. These lists can contain tens or even hundreds of thousands of items. Schedules allow insurers to efficiently collect, manage, and rate these items as part of the policy record, without sacrificing performance or clarity.

Schedules are especially relevant for:

* Commercial Auto (e.g., listing 10,000+ fleet vehicles)
* Homeowners (e.g., scheduled personal property)
* Commercial Property (e.g., inventories of buildings or contents)

Each item in a schedule is structured, ratable (if needed), and independently addressable, while being logically grouped under a parent policy element (such as a `Fleet` or `Location`).

Use Cases [#use-cases]

* **Fleet Management**: Commercial Auto policies can include a schedule of hundreds of thousands of vehicles, each individually priced and editable.
* **Property Schedules**: Warehouses or commercial buildings can manage long lists of insured contents with granular data capture.
* **Non-ratable Schedules**: Policies can include schedules of beneficiaries, dependents, or other tracked data that doesn't influence premium, but needs to be persisted and auditable.

<Callout>
  Similar use cases can also be implemented leveraging conventional `elements` for the data structure. However, these are not as performant, and we strongly recommend using `schedules` for lists exceeding 2,000 items. A system-imposed limitation is likely in a future release. Such changes will be announced in advance to allow for migration.
</Callout>

Key Capabilities [#key-capabilities]

* Add schedules to any policy element, of any category and type, and at any level (e.g., per `Fleet` or `Location` as modeled using `policyLines`, `exposureGroups`, or `exposures`)

* Each schedule supports:
  * Arbitrary numbers of schedule items (tested up to 500,000 per policy)
  * Custom structured data per schedule type
  * Multiple like-type and/or unique schedule types per policy
  * Automatic generation of unique item identifiers (locators)
  * Addition, modification, and removal of items, individually or in bulk
  * Persisting and accessing granular rates for multiple charge types on each schedule item

* Schedule item types are fully configurable and can be reused across products

* High-performance API support for pricing, quoting, and data extraction

Configuration [#configuration]

Schedules are associated with an element within the product data model.
To configure a schedule, the element definition includes a `schedule` entry identifying the type of items the schedule will contain:

```json
"Fleet": {
  "charges": ["CollisionPremium", "LiabilityPremium"],
  "schedule": "Vehicle"
}
```

Schedule item types are defined globally in the configuration schema:

```json
"schedules": {
  "Vehicle": {
   "data": {
     "year": {},
     "make": {},
     "model": {}
   }
   "resetOnRenewal" : true // Optional, defaults to false, used to ensure that the schedule is cleared on renewal
  }
}
```

Only one schedule instance per element instance on a quote or policy is supported. As a result, the schedule type will be consistent across all instances of a given element type. Multiple unique schedule types can be defined and leveraged as long as the parent element type is also unique.

Data Structure [#data-structure]

Schedule types leverage extension data, and just like elements can support deeply nested structures and inheritance. However, for performance reasons, the bulk upload of schedule items via CSV is limited to flat data structures with primitive typed fields.

Charges and Pricing [#charges-and-pricing]

Each schedule item can be rated independently. As the rating process executes, the following steps are performed:

* A `RatingRegistry` persists the pre-aggregation rating data for each schedule item for future reference (via method within the rating plugin)
* All schedule item rates aggregated per charge type (via method within the rating plugin)
  * A "whole schedule" rate is computed as the sum of all individual item rates by charge type and from this a single synthetic charge is created (automatically by the system)
  * If both schedule and element-level charges of the same type exist, they are summed into a single synthetic charge (automatically by the system)

Example: If a `Fleet` contains 10,000 scheduled vehicles, each with a rate of 23.5 for the `collisionPremium` charge type, the synthetic charge applied to the `Fleet` post rating will have a rate equal to the sum of the individual scheduled item's rates:

```json
{ "collisionPremium": { "rate": 235000.0 } }
```

Only the synthetic (aggregated) charges are submitted to billing, not each individual scheduled item, ensuring optimal billing performance even for large schedules.

Plugin Interfaces [#plugin-interfaces]

Given the complexity and performance requirements of schedules, the system provides specific plugin interfaces to handle the rating and data management:

**Schedule Stream**: The schedule itself is not passed to the plugin as part of the quote or transaction request. Instead the plugin can access the schedule via the `SchedulesFactory` and generate a stream of items for processing using the `.stream()` method.

<Callout>
  Use the `updateScheduleItems` API to update the schedule items in the schedule and trigger a re-rating of the schedule items that have changed. If no changes are detected, the `SchedulesFactory.getQuoteSchedule()` and `SchedulesFactory.getTransactionSchedule()` will not return schedule items during the rating process.
</Callout>

```java
// Quote Request
// Fetch locator for the fleet element in the quote
ULID fleetElementLocator = request.quote().element().elements().stream()
                    .filter(e -> "FleetQuote".equals(e.type()))
                    .map(Element::staticLocator)
                    .findFirst().orElseThrow();

Schedule schedule = SchedulesFactory.getQuoteSchedule(request.quote(), fleetElementLocator);
Stream<VehicleScheduleItem> vehiclesStream = schedule.stream();

// Transaction Request
// Fetch locator for the fleet element in the transaction
ULID fleetElementLocator = segment.element().elements().stream()
                    .filter(e -> "FleetPolicy".equals(e.type()))
                    .map(Element::staticLocator)
                    .findFirst().orElseThrow();
Schedule schedule = SchedulesFactory.getTransactionSchedule(request.transaction(), fleetElementLocator)
Stream<VehicleScheduleItem> vehiclesStream = schedule.stream();
```

**Rating Registry**: The rating plugin can create a `RatingRegistry` to provide a granular view of the rating items for each charge type, of each item in the schedule;

* The registry is instantiated via the `RatingRegistryFactory` class by passing the quote or transaction and the desired `Chargeable` (the element schedule of interest is associated with) to the `createFor` method.
* Once created, the registry's input parameter is a `RatingItem`, the same as is used for other rating operations.

```java
// Create a rating registry for the quote
RatingRegistry registry = RatingRegistryFactory.createFor(quote, fleet);

// Create a rating registry for the transaction
RatingRegistry registry = RatingRegistryFactory.createFor(request.transaction(), fleet);
```

**Consuming Schedule Stream**: The stream of schedule items can be processed using the standard Java Stream API which allows for efficient processing of large datasets without loading everything into memory at once. Here a lambda expression is used to process each item:

```java
vehiclesStream.map(vehicle -> rateVehicle(vehicle))
        .filter(Objects::nonNull)
        .flatMap(List::stream)
        .forEach(registry::register);
```

Here, the following happens:

1. Each vehicle in the stream is processed by the `rateVehicle` method, which returns a list of `RatingItem` objects.
2. The `filter` operation removes any null results from the rating.
3. The `flatMap` operation flattens the list of lists into a single stream
4. Finally, each `RatingItem` is registered in the `RatingRegistry` via the `register` method.

**Aggregating Schedule Items Rates**: Once rating for schedule items has completed, the rating registry can be used to aggregate the rates for each charge type across all items in the schedule.

```java
// Aggregate rates for each charge type, stream to a list and add to the RatingItems list to be returned from the rating plugin
ratingItems.addAll(registry.aggregate().stream().toList());
```

<span id="CustomScheduleItemProcessing" />

Custom Schedule Item Processing [#custom-schedule-item-processing]

The Deserialization Plugin can be used to define asynchronous processing logic for large lists of schedule items.

When you upload a file to add schedule items to a quote or transaction, you'll receive a job identifier to track progress. The target quote or policy transaction will be locked for modification while the platform is executing the plugin code and deserializing records in the file. The <ApiLink name="DeserializationJob" /> API response allows you to track job progress.

The <ApiLink name="uploadDeserializedScheduleItems">Upload Quote Schedule Items for Deserialization</ApiLink> API endpoint can be used to upload a file for a quote, and the <ApiLink name="uploadDeserializedTransactionSchedule">Upload Transaction Schedule Items for Deserialization</ApiLink> API endpoint can be used to upload a file for a policy transaction.

Here's an example configuration with a `FleetTrip` schedule:

```json
{
	"FleetTrip": {
		"data": {
			"date": {
				"type": "date",
				"displayName": "Start Date"
			},
			"distance": {
				"type": "int"
			},
			"note": {
				"type": "string",
				"displayName": "Note"
			}
		}
	}
}
```

The `DeserializationPlugin` interface defines methods corresponding to each schedule item type defined in your data model. Each method returns a `ScheduleItemData` record corresponding to the schedule item type.

Here's an example implementation:

<Callout>
  The columns of the CSV file must be in the same order (date, distance, note).
</Callout>

```java
public class DeserializationPluginImpl implements DeserializationPlugin {

    private static final Logger log = LoggerFactory.getLogger(DeserializationPluginImpl.class);

    @Override
    public FleetTripScheduleItem.FleetTripScheduleItemData deserializeFleetTripScheduleItemData(DeserializationRequest request) {
        log.info("In DeserializationPluginImpl.deserializeFleetTripScheduleItemData(), with params: {} and {} record: ", request.requestParams(), request.record());
        String[] parts = request.record().split(",");
        return FleetTripScheduleItem.FleetTripScheduleItemData
                .builder()
                .date(LocalDate.parse(parts[0]))
                .distance(Integer.parseInt(parts[1]))
                .note(parts[2])
                .build();
    }
}
```

API Usage [#api-usage]

Schedules are fully supported across all policy lifecycle stages and are subject to the same data governance as other policy elements.

Quotes [#quotes]

<ApiEndpoint name="addScheduleItems" title="Add items to schedule" />

<ApiSchema name="AddScheduleItemRequest" />

API requests to add items to a schedule are limited to 500 items

<ApiEndpoint name="uploadScheduleItems" title="Upload a CSV of schedule items" />

CSV uploads of schedule items only support flat item data structures; i.e., no nested objects in the schedule definition.

<ApiEndpoint name="deleteScheduleItems" title="Delete an item from schedule" />

Delete individual items from a schedule by specifying their locator within the string array of the request.

<ApiEndpoint name="updateScheduleItems" title="Update a schedule item" />

<ApiSchema name="PatchScheduleItemRequest" />

Transactions [#transactions]

<ApiEndpoint name="addTransactionSchedule" title="Add items to schedule" />

<ApiSchema name="AddScheduleItemRequest" />

API requests to add items to a schedule are limited to 500 items

<ApiEndpoint name="uploadTransactionSchedule" title="Upload a CSV of schedule items" />

CSV uploads of schedule items only support flat item data structures; i.e., no nested objects in the schedule definition.

<ApiEndpoint name="deleteTransactionSchedule" title="Delete an item from schedule" />

Delete individual items from a schedule by specifying their locator within the string array of the request.

<ApiEndpoint name="updateTransactionSchedule" title="Update a schedule item" />

<ApiSchema name="PatchScheduleItemRequest" />

Upload a schedule file for asynchronous processing on a quote [#upload-a-schedule-file-for-asynchronous-processing-on-a-quote]

<ApiEndpoint name="uploadDeserializedScheduleItems" title="Upload Quote Schedule Items for Deserialization" />

<ApiSchema name="DeserializationResponse" />

Upload a schedule file for asynchronous processing on a transaction [#upload-a-schedule-file-for-asynchronous-processing-on-a-transaction]

<ApiEndpoint name="uploadDeserializedTransactionSchedule" title="Upload Transaction Schedule Items for Deserialization" />

<ApiSchema name="DeserializationResponse" />

Deserialization jobs can be listed, fetched, terminated, and restarted. See the [deserialization jobs section of the Jobs API](/api/configuration-and-development/jobs#deserialization-jobs) for details.

Data & Reporting [#data--reporting]

API [#api]

Rating registries can be retrieved in CSV format via the API to access the pre-aggregation rating data for each schedule item.

<ApiEndpoint name="getRatingRegistry" title="Get Rating Registry" />

Data Lake [#data-lake]

An upcoming release of the Data Lake will include Schedules and Rating Registries.

See Also [#see-also]

* [Quote Schedule API](/api/quotes/quotes-schedules)
* [Transaction Schedule API](/api/policy-management/policy-transactions-schedules)


## API Reference

PUT /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — addScheduleItems
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (AddScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

POST /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — uploadScheduleItems
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Responses:
  200 ValidationResult — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — deleteScheduleItems
Permissions: write, schedule-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — updateScheduleItems
Permissions: write, schedule-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (PatchScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

PUT /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — addTransactionSchedule
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (AddScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

POST /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — uploadTransactionSchedule
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Responses:
  200 ValidationResult — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — deleteTransactionSchedule
Permissions: write, schedule-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — updateTransactionSchedule
Permissions: write, schedule-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (PatchScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

POST /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator}/deserialize — uploadDeserializedScheduleItems
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  params (map<string, string>, query, required)
Responses:
  200 DeserializationResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator}/deserialize — uploadDeserializedTransactionSchedule
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  params (map<string, string>, query, required)
Responses:
  200 DeserializationResponse — OK

GET /plugin/{tenantLocator}/ratingregistries/{category}/{locator}/{elementLocator} — getRatingRegistry
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  Accept-Encoding (string, header)
  category (Enum quote | transaction, path, required)
  locator (ulid, path, required)
  elementLocator (ulid, path, required)
Responses:
  200 — OK

AddScheduleItemRequest
Properties:
  data (map<string, object>, required)

PatchScheduleItemRequest
Properties:
  locator (ulid, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

DeserializationResponse
Properties:
  jobLocator (ulid, required)

# Search



Socotra's search allows you to find the following entities quickly and easily:

* Policies
* Quotes
* Accounts
* Contacts
* Diaries
* First Notice of Loss ("FNOL")
* Payments
* Tasks
* User Associations

Overview [#overview]

You can search against locators, static data, and data extensions of type `string`. For entities supporting [numbering](/configuration/general-topics/entity-numbering), you can also search by number. If there is a match with some degree of relevancy, the corresponding entity will be returned for that match. Results are ordered by relevancy score, from highest to lowest. Relevancy scores are boosted for matches on locators, static data, and entity numbers, helping to ensure that such results emerge towards the top of the results.

Example [#example]

If you have an account configured with a [data extension](/configuration/data-extensions/overview) field `lastName`, and there is at least one account with last name "Swerski" in your set of accounts, a search query for `Swerski` will return at least one result: the account record for "Swerski", with a high relative score.

Request [#request]

`POST` request body:

```json
{
	"searchString": "Swerski"
}
```

Response [#response]

```json
{
	"searchToken": "eyJzZWFyY2hSZXF1ZXN0Ijp7InNlYXJjaFN0cmluZyI6IlN3ZXJza2kifX0=",
	"offset": 0,
	"count": 10,
	"results": [
		{
			"score": 2.0,
			"searchEntityType": "account",
			"searchEntityLocator": "01JSH3DEPHHTRE6SQE8F9JH0J3",
			"searchSummary": {
				"account_number": "A223455",
				"data": {
					"firstName": "Bill",
					"lastName": "Swerski"
				},
				"name": "ConsumerAccount",
				"state": "validated"
			},
			"highlights": [
				"Score:2.0 ,Document: 01JSH3DEPHHTRE6SQE8F9JH0J3,Highlight: {entity.data.lastName=[<em>Swerski</em>]}"
			]
		},
		{
			"score": 0.85714287,
			"searchEntityType": "account",
			"searchEntityLocator": "01JSH3E88RHZJTTVJNQX9XCAGK",
			"searchSummary": {
				"account_number": "B229455",
				"data": {
					"firstName": "Bill",
					"lastName": "Swersky"
				},
				"name": "ConsumerAccount",
				"state": "validated"
			},
			"highlights": [
				"Score:0.85714287 ,Document: 01JSH3E88RHZJTTVJNQX9XCAGK,Highlight: {entity.data.lastName=[<em>Swersky</em>]}"
			]
		}
	]
}
```

<Callout>
  A similar name, "Swersky", appears in the results, but with lower relevance than the more exact match on "Swerski". An exact match request with "Swerski" wrapped in (escaped) quotes would only return the "Swerski" account. Read on for details about search behavior and search string syntax.
</Callout>

Requests [#requests]

Requests can be sent as a single `searchString` or as a `searchTerm` array. See the [API reference](/api/search) for details.

Search String Syntax [#search-string-syntax]

A search request comprises search terms - an array of `searchTerm` items - and can be expressed as a `searchString`. `searchString` syntax allows you to express a complete query in a single string, such as one passed through a typical search form box.

A search string follows these rules:

* A sequence one or more `searchTerm` strings, separated by whitespace.

* Each `searchTerm` string has the following form:
  * Form: `[+|-][fieldName:]string[*]`
    * The `fieldName` slug determines whether the match should be against a specific field name or any field.

    * The `fieldName` can be qualified by the full path of the element to which it belongs, which allows for greater specificity in your query. For example, a top-level `lastName` data extension `string` on an account can be searched like this: `+data.lastName:Swerski`, while a `firstName` data extension on an exposure "insured" under some product can be searched as `+insuredQuote.firstName:Veronica` (for quotes) or `+insuredPolicy.firstName:Veronica` (for policies).

    * Term relevance scoring:
      * If the term is prefixed with a `+`, the term is required for search result relevance.
      * If the term is prefixed with a `-`, the term must be excluded for search result relevance.
      * Absence of `+` or `-` before a term is interpreted as a suggestion: the presence of the term increases the relevance score, but does not require that the term be present or absent from a match candidate.

  * The default match behavior is fuzzy.
    * Appending `*` to the term sets matching to `startsWith`.
    * Enclosing the term in double quotes sets matching to `exact`. Searches with spaces cannot be fuzzy searches.
    * Only `exact` matching is case-sensitive.

Entity Numbering [#entity-numbering]

[Entity numbers](/configuration/general-topics/entity-numbering) have dedicated indexing to provide improved search performance for these key identifiers. The searchable entities that support numbering at this time are:

* Accounts
* Quotes
* Policies
* FNOLs
* Tasks

To match against a specific [entity number](/configuration/general-topics/entity-numbering) using `fieldName`, the `fieldName` must be set to `entity_number`, regardless of the entity type. For example, a `policyNumber` or `quoteNumber` can be searched like this: `entity_number:A00000-PA-SD`.

Entity numbers may contain any number of non-alphanumeric symbols. To make searching for these numbers more flexible, all such symbols are ignored during `fuzzy` or `startsWith` searches. This enables users to find entities whether or not symbols are included in their search request. For example, `A00000-PA-SD` can be searched as `A00000-PA-SD`, `A00000PA-SD`, `A00000-PASD` or `A00000PASD`.

Relevancy scores are boosted for matches on entity numbers.

`POST` request body example:

```json
{
	"searchString": "entity_number:A00000-PA-SD"
}
```

Filtering [#filtering]

You may restrict results to a creation time range using the optional `endCreationTime` or `startCreationTime` <ApiLink name="SearchRequest" /> parameters.

Sorting [#sorting]

Results may be sorted using the `sortField` property. This may only be used for system-defined fields already returned in search results for a particular entity.

The order of search results may be controlled using the `sortOrder` property. To sort ascending, use a value of `asc`, and to sort descending, use a value of `desc`.

For example:

```json
{
	"searchString": "deadline_time:<2026-12-29T19:12:27+0000",
	"searchEntityType": "task",
	"sortField": "entity.deadline_time",
	"sortOrder": "asc"
}
```

Date Field Operators for Tasks [#date-field-operators-for-tasks]

Time-based operators are supported for a select group of searchable, non-data extension Task entity fields of type `date`. This can be used to answer questions such as "What is the list of tasks that are due within the next 5 days?".

These operators can be used via `>` and `<` for `searchString` and `greaterThan` and `lessThan` for `searchTerms`. The value to be compared against may be in date (2027-12-29) or datetime (2026-12-29T19:09:26Z) format; a value in date format will resolve to midnight.

The following `date` fields are currently supported:

* `created_time` for the `task` entity
* `deadline_time` for the `task` entity

Field types can be retrieved using the <ApiLink name="fetchFieldsMapping" /> API. Fields with type `date` are timestamps in the format `YYYY-MM-DDT00:00:00Z`.

Search matching of `exact`, `fuzzy`, and `startsWith` are not supported for `date` fields.

Note that data extension fields of type `date` and `datetime` are not searchable; only entity system fields are supported.

Highlights will not be returned in results for `searchString` using `<` or `>`.

`POST` request body example using `searchTerms`:

```json
{
	"searchEntityType": "task",
	"searchTerms": [
		{
			"searchTerm": "2026-10-01T12:09:26Z",
			"fieldName": "entity.deadline_time",
			"match": "greaterThan",
			"absolute": "required"
		},
		{
			"searchTerm": "2026-10-02T16:09:26Z",
			"fieldName": "entity.deadline_time",
			"match": "lessThan",
			"absolute": "required"
		}
	]
}
```

`POST` request body example using `searchTerms`:

```json
{
	"searchString": "deadline_time:<2026-12-01",
	"searchEntityType": "task"
}
```

Null Values [#null-values]

For the `assigned_to` field in the `task` entity, if the value is set to `null`, search results will display the string value `"null"`.

Responses [#responses]

The <ApiLink name="SearchServiceResponse" /> provides a list of <ApiLink name="SearchResultResponse" /> `results`, along with properties to assist in paging through results.

You can fetch up to 100 results at a time, and use the `count`, `offset`, and `searchToken` values to control pagination. If no `count` is set for the initial search request, it will be set to `100`. The `searchToken` should be used in subsequent `GET` requests to page through the results, with `count` serving as the number of results to be returned in the page and `offset` as the starting index (beginning at `0`) in the result list. For example, if you perform a search with a total of 70 results, and want to page through 25 results at a time, you can do it with three requests, all setting `count` to `25`:

1. The initial query
2. A second query, along with the `searchToken` and `offset` as `25`
3. A final query , along with the `searchToken` and `offset` as `50`

You'll know that you have exhausted the result set when the length of the result list is less than `count`. If there are no results beginning at some `offset` index, the service will return an empty result list. You can set the `count` to another value when fetching results; following the example above, if you decided you wanted all the results in a single response, just provide the `searchToken` with `count` at least `70`. A provided `count` greater than `100` will be set to `100`.

Relevance [#relevance]

The `highlights` and `score` properties provide additional context about the match. In `highlights` you will find one or more excerpts from text that matched the query, while `score` indicates the relative numerical value assigned for ranking. You'll see very high `score` values for certain cases, such as exact matches on locator values.

Search Summary [#search-summary]

The `searchSummary` object serves as a digest about the entity, reducing the need for subsequent data fetches from the API in order to understand which entity is being referred to, or to display the search result in an effective way. The contents of `searchSummary` depends on the result entity type:

* Quotes and policies will have all static data fields in a `static` property.
* Quotes will also have a `state` property.
* All other searchable entities will include all string-type data extension field values in the `data` property.

"`<entity>`\_number" will also appear as a search summary property if the entity supports numbering, and a number is assigned. The account results shown in this guide include `account_number`, for example, even though any search request for that number using `fieldName` must refer to `entity_number` rather than `account_number`.

<span id="search-request-fields" />

Field Augmentation [#field-augmentation]

You can augment the `searchSummary` by supplying string values in the `fields` array of the <ApiLink name="SearchRequest" />. Any field (data extension) whose name matches one of the strings in `fields` will appear as an entry in the `searchSummary` map, with the full field name and dot-delimited path as the key.

For example, a search request with `"fields": ["model", "vin"]` could yield a `searchSummary` with entries like this:

```json
{
	// ...,
	"searchSummary": {
		"entity1.elements1.PersonalVehicleQuote.VIN": "4T1R11AK5MU610710",
		"entity1.elements1.PersonalVehicleQuote.model": "Camry",
		"entity1.elements2.PersonalVehicleQuote.VIN": "WAUV2AF20KN111732",
		"entity1.elements2.PersonalVehicleQuote.model": "A7",
		"state": "draft"
	}
	// ...
}
```

Sample Responses [#sample-responses]

A <ApiLink name="SearchResultResponse" /> for a "ConsumerAccount" account (search query was simply "Evans"):

```json
{
	"score": 2.0,
	"searchEntityType": "account",
	"searchEntityLocator": "01JSH42HR5MYXAZQSCR13WNJ5P",
	"searchSummary": {
		"account_number": "C229458",
		"data": {
			"firstName": "Bill",
			"lastName": "Evans"
		},
		"name": "ConsumerAccount",
		"state": "validated"
	},
	"highlights": [
		"Score:2.0 ,Document: 01JSH42HR5MYXAZQSCR13WNJ5P,Highlight: {entity.data.lastName=[<em>Evans</em>]}"
	]
}
```

A <ApiLink name="SearchResultResponse" /> for a quote result when searched by locator -- note the high relevancy score, since the search service boosts relevancy for exact matches on locators:

```json
{
	"score": 101.0,
	"searchEntityType": "account",
	"searchEntityLocator": "01JSH42HR5MYXAZQSCR13WNJ5P",
	"searchSummary": {
		"account_number": "C229458",
		"data": {
			"firstName": "Bill",
			"lastName": "Evans"
		},
		"name": "ConsumerAccount",
		"state": "validated"
	},
	"highlights": [
		"Score:101.0 ,Document: 01JSH42HR5MYXAZQSCR13WNJ5P,Highlight: {entity.locator.keyword=[<em>01JSH42HR5MYXAZQSCR13WNJ5P</em>]}"
	]
}
```

Configuration [#configuration]

Search is enabled by default, indexing locators, some entity numbers, and data extension fields of type `string`. String field indexing includes data fields contained within [Custom Data Types](/configuration/data-extensions/custom-data-types) and in static data.

Locator indexing makes it possible to search for quotes, policies, and accounts by locator, along with elements by locator or static locator.

Entity number indexing makes it possible to search for quotes, policies, accounts, and FNOLs by entity number.

You may use the `defaultSearchable` and `searchable` configuration properties to more precisely control which string fields are indexed for search. `defaultSearchable` is available at the top level of the configuration, in addition to configuration for accounts, products, and elements. If `defaultSearchable` is not explicitly provided at the top level of the configuration, it is set to a default value of `true`. When `defaultSearchable` is `true`, all string fields at that level and below are indexed. When `defaultSearchable` is `false`, then a string field must have `searchable` set to `true` in order to be indexed for search. For a given field, the nearest `defaultSearchable` value when going up the configuration hierarchy applies.

<Callout>
  While Socotra allows you to create draft entities with fields not specified in the configuration, the search service will only index fields on draft entities that are actually present in the configuration.
</Callout>

See Also [#see-also]

* [Search API reference](/api/search)


# Underwriting



import Image from 'next/image';

This article provides an **overview of underwriting** in the Socotra Insurance Suite.

Overview [#overview]

<Image src="/images/underwriting_flow.png" alt="Infographic depicting the underwriting step of a transaction in the Socotra Insurance Suite." width={700} height={184} unoptimized />

In the Socotra Insurance Suite, **underwriting** is a process that determines whether a quote or policy transaction is worthwhile from a business standpoint.

Typically, underwriting utilizes an **underwriting plugin**. The underwriting plugin uses custom logic (written in Java) to analyze a transaction.

Based on its analysis, the underwriting plugin assigns **underwriting flags** to the transaction.

What is an underwriting plugin? [#what-is-an-underwriting-plugin]

An **underwriting plugin** is a module that contains custom logic (written in Java) to perform underwriting checks.

The underwriting transaction is capable of adding and clearing (removing) underwriting flags.

The plugin determines if the transaction passes underwriting. If so, the flow continues. If not, the transaction diverts to a blocked state.

What is an underwriting flag? [#what-is-an-underwriting-flag]

An **underwriting flag** is a marker that can be added to a transaction. Underwriting flags are either:

* Added manually (via the API or web app)
* Added programmatically (via an underwriting plugin)

There are five types of underwriting flags:

* `approve`
* `block`
* `decline`
* `info`
* `reject`

Once underwriting flags have been applied to a transaction, the system performs an **evaluation** process to analyze whether the transaction should proceed.

Post-underwriting Evaluation [#post-underwriting-evaluation]

After a transaction goes through pricing, the typical next step is for it to go through an underwriting plugin. The underwriting plugin adds or clears any flags on the transaction.

The next step is **evaluation**, where an algorithm determines the appropriate course of action for a transaction given its assigned flags. Then, the transaction is assigned an **underwriting status**.

Evaluation algorithm [#evaluation-algorithm]

The **evaluation algorithm** examines the remaining uncleared flags on a quote. The system makes the following checks in order:

1. If there are any `approve` flags assigned to the quote, underwriting *passes*. The transaction will transition to the desired state.
2. If there are any `reject` flags assigned to the quote, underwriting *fails*. The quote state will be set to `rejected`.
3. If there are any `decline` flags assigned to the quote, underwriting *fails*. The quote state will be set to `declined`.
4. If there are any `block` flags assigned to the quote, underwriting *fails*. The quote state will be set to `underwritingBlocked`.
5. Otherwise, underwriting passes.

Tips [#tips]

Based on the algorithm described above, we suggest the following tips:

* **If you never want to block underwriting**, avoid adding any flags (or only add `approve` or `info` flags).
* If your **decision making logic is in a system external to Socotra**, fetch that system's result in the underwriting plugin. Based on result, add an `approve`, `reject`, or `decline` flag. Evaluation will proceed as described above.
* If you **have a system where you also need to accomplish certain checks** (e.g. property inspection or manual review), you can add (and subsequently clear) `block` flags for each task.

Underwriting status [#underwriting-status]

Every quote has an `underwritingStatus` property that indicates the underwriting decision applied to the quote.

* `approved`
* `blocked`
* `declined`
* `none`
* `rejected`

<Callout type="warn">
  The `rejected` underwriting status is terminal. You cannot reset a transaction of its underwriting status when it is rejected. If this is not acceptable, we recommend using the `decline` or `block` flags as alternatives.
</Callout>

Example Underwriting Scenario [#example-underwriting-scenario]

A commercial auto quote advances to underwriting, and the [Underwriting Plugin](/configuration/plugins/underwriting) adds a `block` flag to the vehicle schedule element, resulting in the following <ApiLink name="QuoteUnderwritingResponse" />:

```javascript
{
    "quoteLocator": "01JHN92K8KJTRV8ZBHKN9QAF41",
    "accountLocator": "01JHG7ZM32ET1R1JFRRB80BXSS",
    "quoteState": "underwrittenBlocked",
    "productName": "CommercialAuto",
    // ...,
    "underwritingStatus": "blocked",
    "underwritingFlags": [
        {
            "locator": "01JHN9AQD6JS0Q67MNGCQSZ2Z5",
            "level": "block",
            "referenceType": "quote",
            "referenceLocator": "01JHN92K8KJTRV8ZBHKN9QAF41",
            "note": "Vehicle schedules with TIV over $100K must be reviewed by an underwriter",
            "tag": "uw_rule_01",
            "elementLocator": "01JHN92K8KZCSHX4QEJMBRTKAS",
            "createdTime": "2025-01-15T15:29:21.318840Z"
        }
    ]
}
```

The quote is currently `blocked`.

Later, an underwriter decides that this quote looks acceptable and should be advanced to `underwritten`. She decides to clear the flag while also adding an additional informational flag to the vehicle schedule element. Here's the body of the corresponding <ApiLink name="updateUnderwritingFlagsForQuote" />, exemplifying underwriting via the API:

```javascript
{
    "addFlags": [
        {
            "level": "approve",
            "elementLocator": "01JHN92K8KZCSHX4QEJMBRTKAS",
            "note": "Acceptable risk"
        }
    ],
    "clearFlags": [
        "01JHN9AQD6JS0Q67MNGCQSZ2Z5"
    ]
}
```

The manual underwriting update results in the following <ApiLink name="QuoteUnderwritingFlagsResponse" />:

```javascript
{
    {
        "quoteLocator": "01JHN92K8KJTRV8ZBHKN9QAF41",
        "flags": [
            {
                "locator": "01JHN9R36S986XH99HDVABM5EW",
                "level": "approve",
                "referenceType": "quote",
                "referenceLocator": "01JHN92K8KJTRV8ZBHKN9QAF41",
                "note": "Acceptable risk",
                "elementLocator": "01JHN92K8KZCSHX4QEJMBRTKAS",
                "createdBy": "dc68c494-6918-487a-bf08-58c2983175dc",
                "createdTime": "2025-01-15T15:36:39.385573Z"
            }
        ],
        "clearedFlags": [
            {
                "locator": "01JHN9AQD6JS0Q67MNGCQSZ2Z5",
                "level": "block",
                "referenceType": "quote",
                "referenceLocator": "01JHN92K8KJTRV8ZBHKN9QAF41",
                "note": "Vehicle schedules with TIV over $100K must be reviewed by an underwriter",
                "tag": "uw_rule_01",
                "elementLocator": "01JHN92K8KZCSHX4QEJMBRTKAS",
                "createdTime": "2025-01-15T15:29:21.318840Z",
                "clearedBy": "dc68c494-6918-487a-bf08-58c2983175dc",
                "clearedTime": "2025-01-15T15:36:39.385009Z"
            }
        ]
    }
}
```

Since the `block` flag has been cleared, and there are no other uncleared blocking flags, the quote can proceed to `underwritten` when the underwriter attempts to underwrite the quote again.

See also [#see-also]

* [Policy Transaction Underwriting API](/api/policy-management/policy-transactions#policyTransactionUnderwritingApi)
* [Quote Underwriting API](/api/quotes/quotes#quoteUnderwritingApi)


# Create a tenant configuration file



import Image from 'next/image';

This article explains how to **create a tenant configuration file** in the Socotra Insurance Suite.

Overview [#overview]

What will I learn? [#what-will-i-learn]

By the end of this tutorial, you will know:

* What a tenant configuration file is.
* What a tenant is.
* How to create a tenant configuration file from a template.
* How to navigate the Socotra web app to view and configure a tenant.
* How to add, modify, and remove data on the tenant configuration file.

What will I need? [#what-will-i-need]

You’ll need a set of credentials to log into your business account. To learn more about logging into your business account, see: [Log into Socotra](/getting-started/log-into-socotra)

Note about JSON [#note-about-json]

This article should give you a basic understanding of the data model of a tenant configuration file. There are two ways to create a tenant configuration file:

* Through the Socotra web app.
* Manually by writing JSON code.

This tutorial mostly focuses on how to use the Socotra web app, but manually writing JSON code is also a common method. We’ll show some examples of how the configuration is set up in JSON below.

**Don’t worry if you’re not comfortable with JSON just yet**. We’re going to focus on learning how to manipulate this data in the Socotra web app, but it’s useful to have a general idea of how things work behind the scenes for when you learn how to use the Socotra API.

**Tip**: When directly editing JSON code to make a tenant configuration in Socotra, remember this basic principle: There are several directories where you can define policy, billing, and other administrative settings, and it’s possible to link these settings together to make a valid tenant configuration and insurance product(s).

Also keep in mind that the example’s we’re going to cover aren’t the only way to set up a product in Socotra. Socotra is a highly configurable, flexible platform. These examples just show you the basics.

Now, let’s cover the basics of the Socotra data model by exploring what a tenant configuration file is.

Key concepts [#key-concepts]

What is a tenant configuration file? [#what-is-a-tenant-configuration-file]

In Socotra, a **tenant configuration file** defines one or more insurance products.

The tenant configuration file describes all aspects of the product, including exposures and coverages. It’s also where you define billing and administrative settings.

Once created and validated, tenant configuration files are deployed to *tenants*.

What is a tenant? [#what-is-a-tenant]

In Socotra, a **tenant** is a dedicated instance of the Socotra insurance policy administration system. Tenants allow you to isolate data related to insurance products in a highly customizable container. A business account can contain one or more tenants.

We’ll cover tenants in further detail later on in this learning path. For now, it’s enough that you’re familiar with the term.

Next, we'll cover how a tenant configuration file is generally structured.

How is a tenant configuration file structured? [#how-is-a-tenant-configuration-file-structured]

A tenant configuration file contains the settings for the administration of an insurance policy. The settings can be thought of as being subdivided into four categories:

* Global
* Policy
* Billing
* Resources

For right now, we'll start by focusing on the **Policy** category, which defines the structure of an *insurance product*.

What is an insurance product? [#what-is-an-insurance-product]

An **insurance product** is a data model composed of various elements that, when linked together, represent a product that can be used to create quotes and policies for *account holders*.

What is an account holder? [#what-is-an-account-holder]

An **account holder** is a third-party entity (a person or a business) who is capable of being quoted for and being issued a policy for an insurance product.

What is an element? [#what-is-an-element]

An **element** is a building block of an insurance product. Elements are data objects, and they have two required properties:

* category
* type

The **category** defines the kind of element. There are five valid categories:

* product
* policyLine
* exposureGroup
* exposure
* coverage

The **type** is a name that provides a human-readable description of the element.

**Note**: The type must start with a letter or underscore. It also cannot have the same name as a [reserved word/boolean value in the Java programming language](https://en.wikipedia.org/wiki/List_of_Java_keywords). See the [Configuration Deployment](/configuration/general-topics/deployment#configuration_element_name_length_limits) guide for more information on naming restrictions.

Visualizing an insurance product configuration [#visualizing-an-insurance-product-configuration]

The graphic below represents one possible configuration of an insurance product, using the **product**, **exposure**, and **coverage** elements.

<Image src="/images/create-a-tenant-configuration-file/gr-insurance-product-breakdown.png" alt="Infographic depicting the organization of a simplified insurance product." width={1728} height={1248} unoptimized />

In the graphic above:

* Each rectangle represents an **element**.

* Each element has two required properties:
  * **category** (the kind of element)
  * **type** (a name/description of the element)

* A **product** element is composed of (*contains*) one or more exposure elements.

* An **exposure** element contains one or more coverage elements.
  * **Note**: An exposure represents the level of risk or vulnerability held by an individual or business. This is usually what is being insured.

How does this look represented in the JSON code? The annotated screenshots below show a configuration in Visual Studio Code, though you can use any text editor to read and edit JSON.

<Image src="/images/create-a-tenant-configuration-file/gr-annotated-configuration-breakdown-1.png" alt="Screenshot of a product element in a tenant configuration in a code editor." width={1999} height={1260} unoptimized />

1. The **product** element “ho3” is located in the products directory.
   1. The **category** of the product element is inferred by its placement in the *products* directory name.
   2. The **type** of the product element is in the sub-directory name (*products > ho3*)

2. The `contents` array in config.json points to `dwelling`. This is the name of an exposure, as we’ll see in the screenshot below.

<Image src="/images/create-a-tenant-configuration-file/gr-annotated-configuration-breakdown-2.png" alt="Screenshot of an exposure in a tenant configuration in a code editor." width={1999} height={1260} unoptimized />

1. The exposures element “dwelling” is located in the exposures directory.
   1. The category of the exposures element is inferred by its placement in the exposures directory.
   2. The type of the exposures element is defined in the subdirectory (*exposures > dwelling*)
      1. You could just as easily rename “dwelling” to “home”, and it would have the same functionality; the exposure type would now be “home”.
      2. Be aware – when renaming in JSON, you must make sure to update all references to the old name as well.

2. The contents array in config.json likewise points to four coverages that we’ll see in the screenshot below.

<Image src="/images/create-a-tenant-configuration-file/gr-annotated-configuration-breakdown-3.png" alt="Screenshot of various coverages in a tenant configuration in a code editor." width={1999} height={1260} unoptimized />

1. The four **coverages** elements “coverage\_a”, “coverage\_b”, “personal\_property”, and “water\_backup” can be found in the coverages directory.

Ready to begin? [#ready-to-begin]

Continue onto the next section to learn how to create a tenant configuration file for an insurance product in Socotra.

Part 1 - Creating a configuration file [#part-1---creating-a-configuration-file]

First, you need to **create a configuration file**. There are broadly two ways to create a configuration file:

* Through the Socotra web app
* Manually by writing JSON code

We’re going to focus on creating the configuration through the Socotra web app, but we’ll cover how to directly edit the code later on in this learning path.

Socotra provides a template configuration file of a few mock insurance products. During this tutorial, you’ll use the template to learn more about navigating and modifying a configuration file.

Follow the steps below to create a configuration file from a template in Socotra.

1. Log into the Socotra web app.
   1. For more information, see: [Log in to Socotra](/getting-started/log-into-socotra).

2. Click **Configurations** (either in the top-left corner of the screen or in the center of the page).

<Image src="/images/create-a-tenant-configuration-file/sc-navigate-to-configurations.png" alt="Screenshot of the &#x22;Configurations&#x22; buttons on the Socotra landing page." width={3248} height={2046} unoptimized />

3. On the Config Files page, click **Add New**.

4. The **Add New** window will appear. This is where we can create a new configuration file. There are three options you an choose from:
   1. Start from Template (an example insurance configuration with some data pre-populated).
   2. Start from Blank (a bare-bones insurance product with very little configuration).
   3. Upload (allows you to upload an insurance product file you’ve pre-configured).

5. For the purpose of this tutorial, **make sure to select Start From Template**.

<Image src="/images/create-a-tenant-configuration-file/sc-start-from-template-and-name.png" alt="Screenshot of the &#x22;Start From Template&#x22; option when creating a new configuration." width={3248} height={2046} unoptimized />

6. Provide a name for your configuration.
   1. We recommend naming your configuration something easily identifiable and associated with the type of insurance product it represents.
   2. For this tutorial, we’ll simply call it `my_example_config`.

7. When you're satisfied with your configuration name, click **Confirm**.

8. If successful, a message will appear saying the configuration was successfully added.

Congratulations! You’ve successfully created your first tenant configuration file in Socotra.

Continue onto the next part to learn the basics of configuring it.

Part 2 - Basic editing of the tenant configuration file [#part-2---basic-editing-of-the-tenant-configuration-file]

In Part 1, you learned how to create a configuration file from a template.

In Part 2, you’ll learn how to make basic edits to the tenant configuration file.

View the configuration file [#view-the-configuration-file]

1. In the Config Files list, locate the configuration file you created in Part 1.
2. Click **Edit**.

<Image src="/images/create-a-tenant-configuration-file/sc-click-edit.png" alt="Screenshot of the &#x22;Edit&#x22; button you can click to edit/view a configuration." width={3248} height={2046} unoptimized />

Once you click **Edit**, you’ll be taken to the config mapping page. This is where you can edit your tenant configuration.

Concept - Attributes [#concept---attributes]

Remember that the configuration file is the definition of one or more insurance product(s).

On the left and center of the screen, you should see four categories. These are called **attribute categories**.

<Image src="/images/create-a-tenant-configuration-file/sc-attribute-categories.png" alt="Screenshot of the attribute categories of a configuration." width={3248} height={2046} unoptimized />

An **attribute category** is a logical grouping of attributes of your tenant configuration.

An **attribute** is a piece of data used to configure your insurance product. Attributes allow you to customize the specifics of a product, including the policy and billing.

There are dozens of nested attributes that make up an tenant configuration, but they broadly fall into four categories:

* Global
* Policy
* Billing
* Resources

We’ll briefly cover each of these categories in the table below. We’ll go further in depth on the data model of Socotra in later tutorials.

| Category  | Description                                                                                         | Sub-items                                                                                               |
| --------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Global    | Global attributes apply to the entirety of the tenant configuration.                                | Custom Data Types, Accounts, Defaults, Global Plugins, Aux Data, Custom Events                          |
| Policy    | Policy attributes are configurations for the issuance and administration of any insurance policies. | Products, Attributes, Coverage Terms, Charges, Transaction Types, Auto-Renewal Plans                    |
| Billing   | Billing attributes are configurations for the collection and disbursement of funds.                 | Billing Plans, Installment Plans, Delinquency Plans, Payments, Disbursements, Shortfall Tolerance Plans |
| Resources | Resources contain data and document generation tools.                                               | Constraint Tables, Tables, Documents                                                                    |

For right now, we’re going to focus on **Defaults** (under Global). Continue reading the section below to learn about default attributes.

Concept - Default attributes [#concept---default-attributes]

In the context of your tenant configuration, a **default attribute** is an attribute in the “Global” category that sets the standard behavior of your products. Default attributes can be overwritten by more specific attribute settings.

For example, even though default attributes might set a default currency, if you want a specific insurance product to have a different currency, you can configure that product in particular to have a different currency from the default.

Default attributes make it easy to have consistent behaviors across all products, while giving you the flexibility to make changes to specific products.

See the table below for a quick reference of each of the default attributes.

| Default attribute        | Description                                                                                                                                                                                                                                                                                                                              |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Time zone                | Defines the default time zone of the tenant                                                                                                                                                                                                                                                                                              |
| Currency                 | A three-letter currency code that represents the currency used when creating a quote.                                                                                                                                                                                                                                                    |
| Installment plan         | Points to an installment plan configuration. An installment plan informs the billing system on how to divide the charges for a transaction into installments, which are then used to construct invoices.                                                                                                                                 |
| Term duration            | Defines a numerical value to represent a length of time. This attribute is used alongside the Duration basis attribute. This value must be a positive integer greater than or equal to 1. For example, if you want a term to be six months, set *Term duration* to **6** and *Duration basis* to **Months**.                             |
| Duration basis           | Defines a unit of time for measuring the length of a term. Options include: `Hours`, `Days`, `Whole Days`, `None`, `Weeks`, `Months`, `MonthE360` (months based on a 360-day calendar), `Years`. For example, if you want a term to be six months, set *Term duration* to **6** and *Duration basis* to **Months**.                      |
| Shortfall tolerance plan | Points to a shortfall tolerance plan configuration. A shortfall tolerance plan determines the threshold allowed for payment deficits without penalties or disruptions. A default shortfall tolerance plan can be configured for your tenant as well as for each product. Any plan can additionally be assigned to a quote upon creation. |
| Auto renewal plan        | Points to an auto renewal plan configuration. Auto-renewal plans inform the system on how policies should be managed as they approach expiration. A default auto-renewal plan can be configured for your tenant as well as for each product. Any plan can additionally be assigned to a quote upon creation.                             |
| Billing plan             | Points to a billing plan configuration. A billing plan instructs the system on how to generate invoices. In particular, it defines at what state (acceptance or issuance) that an invoice would be generated for a policy.                                                                                                               |
| Delinquency plan         | Points to a delinquency plan configuration. A delinquency plan instructs the system on how to handle invoices that go unpaid post their due date.                                                                                                                                                                                        |
| Aux Data Settings        | The Aux Data setting determines the default length of time until an aux data entry will expire. A different setting/expiration can be used when creating a new aux data entry, however if no setting/expiration is included when creating a new aux data entry, it will use the default setting.                                         |

Edit the default attributes [#edit-the-default-attributes]

In this subsection, you’ll learn how to edit default attributes for your tenant configuration.

Let’s try changing the duration of any policy created using this config. Remember that changing policy duration requires changing two settings:

* Term duration (the amount of time)
* Term basis (the unit of time)

So, let’s suppose we want a policy to last **6 months**.

1. In the **Term Duration** field, type **6**.
2. In the **Duration Basis** dropdown, select **Months**.

You may have noticed that, after editing these fields, a **required** message appears under the Shortfall tolerance plan field. Continue onto the next subsection to learn more.

Concept - Attribute types [#concept---attribute-types]

The Shortfall Tolerance Plan field might be showing as required when you try to alter some of the other settings in Defaults, preventing you from saving any changes.

<Image src="/images/create-a-tenant-configuration-file/sc-shortfall-tolerance-plan-required.png" alt="Screenshot of an error saying that the Shortfall Tolerance Plan is required." width={3248} height={2046} unoptimized />

The reason why this is occurring is because **every default attribute field needs to have a value**.

There are essentially two types of attributes:

* Simple attributes
* Complex attributes

A **simple attribute** is an attribute that only consists of one setting. Examples of simple attributes include currency, term duration, and duration basis. These all have predefined values you can select from, or are otherwise simple enough that they only accept an integer value.

A **complex attribute** is a more advanced configuration. Remember that the default attributes set default settings for your insurance product. So, some of the default attributes point to configurations about a certain aspect of an insurance product.

To select a value for this field, first add at least one shortfall tolerance plan to the **Shortfall Tolerance Plans** section under the **Billing** dropdown on the left side of the screen. Then navigate to the **Defaults** section under the **Global** dropdown on the left side of the screen, click the **Shortfall tolerance plan** dropdown, and select a value.

<Image src="/images/create-a-tenant-configuration-file/sc-shortfall-tolerance-plan-option-select.png" alt="Screenshot of options for the Shortfall Tolerance Plan field." width={3248} height={2046} unoptimized />

When you make any change to the default values, a dialog box will appear at the top of the screen to indicate that your changes have been automatically saved.

We’ve learned about the basics of configuration files, including their attributes and how to make basic changes. In the next section, we’ll cover how to make more advanced changes to a configuration file.

Part 3 - Advanced editing of the tenant configuration file [#part-3---advanced-editing-of-the-tenant-configuration-file]

In Part 2, you learned about attributes in the configuration file, including how to set default attributes and create new attributes.

In Part 3, you’ll learn how to make more substantive changes to an insurance product.

View the Products menu [#view-the-products-menu]

Start by viewing the Product menu. This is where individual insurance products are defined.

<Image src="/images/create-a-tenant-configuration-file/sc-navigate-to-product-ho3.png" alt="Screenshot showing navigation to the Product menu." width={3248} height={2046} unoptimized />

1. In the left sidebar, navigate to **Policy > Products > Ho3**.
2. You should now be viewing the Ho3 (homeowner) product.

<Image src="/images/create-a-tenant-configuration-file/sc-product-tabs.png" alt="Screenshot of the tabs on the tenant configuration menu of a particular insurance product." width={3248} height={2048} unoptimized />

| Tab                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Eligible Account Types | Where you choose which account types are eligible for the quotes and policies that will be created based on this product. Account types are created in *Global > Accounts*.                                                                                                                                                                                                                                                                                                       |
| Contents               | Where you create hierarchical associations between elements. An element can refer to a policy line, exposure group, exposure, or coverage. These elements can have hierarchical relationships with each other. For example, an exposure contains one or more coverages. While you define all of the attributes in the Attributes menu (*Policy > Elements*), the relationship between the elements is defined in the Contents tab. (*Products > \[Selected Product] > Contents*). |
| Charges                | Where you choose which charges are associated with the product. Charges are defined in the Charges menu (*Policy > Charges*).                                                                                                                                                                                                                                                                                                                                                     |
| Coverage Terms         | Where you configure coverage terms. Coverage terms handle configurations related to: deductibles, limits (split limits, aggregate limits, lifetime limits, etc.), benefits ((like benefits for term life payouts), and riders ((like optional inclusion of additional coverage that doesn’t need a full Coverage attribute).                                                                                                                                                      |
| Data                   | Where you can create any custom data you want associated with the insurance product. If a data value isn’t captured in one of the default menus, you can create a custom value in the Data tab. This is also where you can see all of the fields that are inherited from other entities.                                                                                                                                                                                          |
| Static Data            | Where you can create custom data that you don’t want to be governed by the data revision rules of policy transactions. You can add or update data here even after a quote has become finalized and immutable. A maximum of 10 static data fields can be added per product.                                                                                                                                                                                                        |
| Plugins                | Where you manage product-specific plugins. These will overwrite any matching instances within Global Plugins for this product.                                                                                                                                                                                                                                                                                                                                                    |
| Documents              | Where you manage documents that are generated for this insurance product. Documents are declared and stored on the Documents page (*Resources > Documents*).                                                                                                                                                                                                                                                                                                                      |
| Settings               | Where you can overwrite any default attributes.                                                                                                                                                                                                                                                                                                                                                                                                                                   |

Making changes to the product [#making-changes-to-the-product]

In this section, we’ll cover how to add a new data field to a product.

For the purposes of this tutorial, you’re going to add a field that records the number of prior fraud convictions held by the customer.

1. While viewing your tenant configuration, navigate to **Policy > Products > Personal Auto**. Then, click the **Data** tab.
2. Click **Add New**.

<Image src="/images/create-a-tenant-configuration-file/sc-navigate-to-add-new-data-field.png" alt="Screenshot showing the &#x22;Add New&#x22; button to add a new data field to a product." width={3248} height={2048} unoptimized />

After you click **Add New**, a flyout window will appear.

3. Fill out the **Name** field.
   1. This should typically:
      1. Be description of the information the field is capturing.
      2. Be in `camelCase` or `PascalCase`.

   2. For this tutorial, we recommend providing the value `priorFraudConvictions` as the name.

4. Fill out the **Display Name** field.
   1. This should typically be based on the **Name** field.
   2. For this tutorial, we recommend providing the value `Prior Fraud Convictions` as the display name.

5. Select a value for the **Type** field.
   1. The type is the kind of data captured by the field.
   2. Examples include string (text), int (integer), etc.
   3. For this tutorial, we recommend selecting **string**.

6. Select a value for the **Quantifier** field.
   1. This sets whether the field must be provided when making a quote with this insurance product.
   2. For this tutorial, we recommend selecting **Optional (?)**.

7. Select a value for the **Scope** field.
   1. This sets whether this data is used for generating quick quotes, quotes, or both policies and quotes.
   2. For this tutorial, we recommend selecting **Policy + Quote**.

8. For the purposes of this tutorial, we can ignore the **Tags**, **Default value**, **Min length**, **Max length**, and **Regex** fields. We’ll cover these in future learning resources.

9. For the **Options** field, click **Add**.
   1. This is where you can add selectable options to represent how many fraud convictions the customer has.
   2. Enter “0” for the first value. Then, click **Add** again.
   3. Repeat this process to add options 0, 1, 2, and 3+.

10. Review the screenshots below and compare it to what you have configured. If something doesn’t match up, review these steps.

<Image src="/images/create-a-tenant-configuration-file/sc-add-new-data-field-flyout-menu-1.png" alt="Part 1 of 2, screenshot showing the flyout menu for adding a new data field to a product." width={3248} height={2048} unoptimized />

The Add new field flyout window (part 1)

<Image src="/images/create-a-tenant-configuration-file/sc-add-new-data-field-flyout-menu-2.png" alt="Part 2 of 2, screenshot showing the flyout menu for adding a new data field to a product." width={3248} height={2048} unoptimized />

The Add new field flyout window (part 2)

11. Click **Create**.

After clicking Create, the new data field should appear in the list of fields.

<Image src="/images/create-a-tenant-configuration-file/sc-new-data-field.png" alt="Screenshot of the data field appearing after clicking &#x22;Create&#x22;." width={3248} height={2048} unoptimized />

Recap [#recap]

In this tutorial, we covered:

* How to create a configuration file from a template.
* How to view and edit the basic settings of a configuration file.
* How to navigate the Products menu.
* How to add new data to configure the product.

Now that we have a configuration representing insurance products, how do we put it into action? The next step is to deploy the configuration file to a tenant. But what is a tenant?

Ready for the next module? [#ready-for-the-next-module]

See [Overview - Tenants](/getting-started/overview-tenants) to continue this learning path.


# Create a tenant



import Image from 'next/image';

This article explains how to **create a tenant** in the Socotra Insurance Suite.

Steps [#steps]

1. Log into your Socotra business account. For more information, see: [Log into Socotra](/getting-started/log-into-socotra).
2. Navigate to **System Manager > Tenants**.
3. Click **Create tenant**

<Image src="/images/create-a-tenant/sc-click-create-tenant.png" alt="Screenshot of the &#x22;Create tenant&#x22; button." width={3248} height={2048} unoptimized />

1. Provide the following information:
   1. **Name**: Provide a name for the tenant.
      1. This can be any value, but we recommend naming it something related to the kind of activity the tenant will host.
      2. For the purpose of this tutorial, we'll call it Example Tenant.

   2. **Description**: Provide a description of the tenant (optional)
      1. Though this is optional, it's best practice to provide a description of the kind of activity the tenant hosts.

   3. **From ECS**: Select "From ECS" from the dropdown to select a configuration. For more information, see: [Create a tenant configuration file](/getting-started/create-a-tenant-configuration-file)

2. See the screenshot below for an example of how your form should look.

<Image src="/images/create-a-tenant/sc-create-tenant.png" alt="Screenshot of the create tenant window." width={3248} height={2048} unoptimized />

3. Click **Create**.

<Callout>
  Note that, during tenant creation, validation is performed on the configuration. This process can take up to 60 seconds.
</Callout>

4. You should receive a message saying tenant creation was successful.

Ready for the next module? [#ready-for-the-next-module]

See [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api) to continue this learning path.


# Create a user



import Image from 'next/image';

This article explains how to **create a user** in the Socotra Insurance Suite.

Key concepts [#key-concepts]

Users [#users]

In Socotra, **users** are created at the business account level and assigned a tenant scope which designates which tenants a user has access to. They're also assigned a set of roles which determine what actions the user can execute on those tenants.

Admins [#admins]

In Socotra, the **admin** special system-defined that grants the assigned user(s) all permissions to all tenants. While such access is helpful in a learning setting to explore the full extent of system capability, it should be allocated with significant caution in production settings.

Ready to begin? [#ready-to-begin]

Continue onto the next section to learn how to create a user and grant them the admin role.

1. Log into your Socotra business account. For more information, see: [Log into Socotra](/getting-started/log-into-socotra).
2. Once logged in, click **Administration**. Then, click **Users**.

<Image src="/images/create-a-user/sc-users.png" alt="Screenshot showing navigation to the Users page." width={3248} height={2048} unoptimized />

1. Click the **Add user** button.

<Image src="/images/create-a-user/sc-add-user.png" alt="Screenshot calling out the Add user button." width={3248} height={2048} unoptimized />

1. Enter the user's details, including: username, password, first name, and last name.
2. Select the tenants the user will have access to.
3. **Optional**: Click into the **Add roles** field and select **Admin**.

<Image src="/images/create-a-user/sc-add-user-window.png" alt="Screenshot showing the user creation window." width={3248} height={2048} unoptimized />

4. Click **Create** to create the user.

<Image src="/images/create-a-user/sc-click-create.png" alt="Screenshot calling out the Create button to create a user." width={3248} height={2048} unoptimized />


# Create an account



import Image from 'next/image';

This article explains how to **create an account** in the Socotra Insurance Suite.

Key concepts [#key-concepts]

What is an account? [#what-is-an-account]

In Socotra, an **account** is a data object that represents a third-party entity (a person or a business) that is capable of being quoted for and being issued a policy for an insurance product.

Accounts associate individuals or businesses with the insurance products they’re covered by.

What is the process for creating an account? [#what-is-the-process-for-creating-an-account]

There are broadly three steps for creating an account:

| Step | Name     | Description                                                                                                                                                                                                                                                                                                                                                                                                                |
| ---- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1    | Create   | Once created, an account exists in a draft state. Accounts in a draft state aren’t finalized and can be updated without any restrictions.                                                                                                                                                                                                                                                                                  |
| 2    | Modify   | In a draft state, it’s possible to modify an account. You may want to do this if you want to change any information associated with the account or fix any errors (misspelled names, values that don’t meet field requirements, etc.).                                                                                                                                                                                     |
| 3    | Validate | The final stage of account creation is validation. Once validated, an account can be issued insurance policies. Accounts in a validated state cannot be updated as freely as those in a draft state. Any data provided must adhere to the account configuration, as well as any custom validation provided as part of the validation plugin. Also note that, once validated, an account can never return to a draft state. |

<Callout>
  You only need to validate an account when using the Socotra API. The web app validates the account automatically and raises any issues if validation fails.
</Callout>

API steps [#api-steps]

This section explains how to create an account using the Socotra API.

What will I need? [#what-will-i-need]

You will need the following:

* A Postman account
* [A copy of the Socotra Sample Collection and Environment](/getting-started/socotra-sample-postman-collection-and-environment)
* A workspace configured to use the Socotra API.

For more information about using Postman, see: [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api).

<span id="create-an-account-1" />

Create an account [#create-an-account]

1. Log into your Postman account and navigate to your Socotra Sample Collection.
2. While viewing the Socotra Sample Collection, navigate to **Policy > Account > Create Account**.

<Image src="/images/create-an-account/sc-postman-create-account.png" alt="Screenshot showing the Create Account endpoint in Postman." width={1999} height={1254} unoptimized />

3. Click the **Body** tab.

<Image src="/images/create-an-account/sc-postman-body-tab.png" alt="Screenshot calling out the Body tab of the Create Account endpoint in Postman." width={1999} height={1254} unoptimized />

4. You should see a text editing field with some pre-populated JSON.

<Image src="/images/create-an-account/sc-postman-prepopulated-json.png" alt="Screenshot showing pre-populated text in the body of the endpoint." width={1999} height={1254} unoptimized />

In the request body, we specify the following:

* A `type` of `consumerAccount`
* A `data` object to contain the field information we want to provide, containing the following:
  * A `firstName` field to record the account holder’s first name.
  * A `lastName` field to record the account holder’s last name.
  * A `crmKey` field to record an API key for a CRM associated with the account holder. This field is optional, as defined in the data schema we saw in Socotra.

5. Provide the relevant data for the account holder. Or, if you just want to see how the request works, provide the default values to see the results.
6. Click **Send**.

If successful, the response message will look something like the screenshot below:

<Image src="/images/create-an-account/sc-postman-create-account-success.png" alt="Screenshot showing a successful response to the endpoint." width={1999} height={1254} unoptimized />

Let’s breakdown the response:

* `locator`: This contains the unique identifier of the account.
* `type`: This contains the type of the account, in this case consumerAccount.
* `state`: This contains the account state. We can see that it’s a draft and has not yet been validated.
* `data`: This contains the data provided in the request body.
* `billingLevel`: This contains the billing level, which determines how the account is billed for its products.

Continue on to Part 2 to learn how to make modifications to the account.

Update an account [#update-an-account]

Once created, an account exists in a draft state. Before we validate the draft, let’s cover how to make changes to it.

If you look in the Postman collection under **Policy > Account**, you’ll see two endpoints labeled as **Update Account**.

<Image src="/images/create-an-account/sc-postman-update-account.png" alt="Screenshot showing the Update Account endpoints in Postman." width={1999} height={1254} unoptimized />

* Update Account (add), with method PATCH
* Update Account (replace), with method PUT

These endpoints achieve similar goals, but the difference is that the PATCH Update Account (add) endpoint adds data to an existing record, while the PUT Update Account (replace) endpoint replaces all of the data of an existing record with what’s provided in the request body.

For this tutorial, we’ll focus on using PATCH Update Account (add) to make partial changes to the account.

**Note**: Remember to update the accountLocator environment variable with the locator of the account you want to modify.

This endpoint modifies an account record by adding data to the existing record. Use this when you want to make a partial change to an account.

Let’s breakdown the request body of this endpoint:

<Image src="/images/create-an-account/sc-postman-update-account-breakdown.png" alt="Screenshot of the request body of the endpoint." width={1999} height={1254} unoptimized />

* The body contains an object called `setData`. This will contain the new data that we want the endpoint to use when updating the account.
  * `firstName`: This contains the new value for the firstName field.
  * `crmKey`: This contains the new value for the crmKey field.

After clicking **Send** to send the request, it should return the following response message upon success:

<Image src="/images/create-an-account/sc-postman-update-account-response.png" alt="Screenshot of the response body of the endpoint." width={1999} height={1254} unoptimized />

Note the updated values in the `firstName` and `crmKey` fields.

Validate an account [#validate-an-account]

Now that you’ve created an account and successfully updated it, the next step is to validate it.

1. While viewing the Socotra Sample Collection, navigate to **Policy > Account > Validate Account**.
2. Make sure that the locator for the account is either input in the accountLocator environment variable.
3. Click **Send**.
4. The response body should show that the request was successful.

<Image src="/images/create-an-account/sc-postman-validate-account.png" alt="Screenshot of account validation in Postman." width={1999} height={1254} unoptimized />

Web app steps [#web-app-steps]

This section explains how to create an account using the Socotra web app.

1. Log into the Socotra web app. For more information, see: [Log into Socotra](/getting-started/log-into-socotra).
2. Click **Operations**.

<Image src="/images/create-an-account/sc-web-operations.png" alt="Screenshot of the Operations button." width={3248} height={2048} unoptimized />

3. Select the tenant you'd like to add an account to.

<Image src="/images/create-an-account/sc-web-example-tenant.png" alt="Screenshot of the tenant selection page." width={3248} height={2048} unoptimized />

4. Click **Accounts**.

<Image src="/images/create-an-account/sc-web-accounts.png" alt="Screenshot of the tenant page." width={3248} height={2048} unoptimized />

5. Click **Add New Account**. You can choose what kind of account to make. This depends on what accounts are configured in your tenant configuration. In this example, there are two options: Commercial Account and Consumer Account.

<Image src="/images/create-an-account/sc-web-add-new-account.png" alt="Screenshot of the Add New Account button." width={3248} height={2048} unoptimized />

6. Fill out the account details.

<Image src="/images/create-an-account/sc-web-new-account-details.png" alt="Screenshot of the Account Details page." width={3248} height={2048} unoptimized />

7. Click **Create**.

Recap [#recap]

In this tutorial, we covered:

* How to create an account using the Socotra API.
* How to update an account using the Socotra API.
* How to validate an account using the Socotra API.
* How to create an account using the Socotra web app.

Now that we have an who can be issued a quote, the next question is: How does Socotra issue quotes? Continue on to the next learning module to learn more.

Ready for the next module? [#ready-for-the-next-module]

See [Execute a quote to bind](/getting-started/execute-a-quote-to-bind) to continue this learning path.


# Execute a quote to bind



import Image from 'next/image';

This article explains how to **execute a quote to bind** in the Socotra Insurance Suite.

Overview [#overview]

What will I learn? [#what-will-i-learn]

By the end of this tutorial, you will know how to basically take a quote through each stage of its life cycle via the Socotra API, including:

* Create a quote
* Validate a quote
* Price a quote
* Underwrite a quote
* Accept a quote
* Issue a quote

What will I need? [#what-will-i-need]

You will need the following:

* A Postman account
* [A copy of the Socotra Sample Collection and Environment](/getting-started/socotra-sample-postman-collection-and-environment)
* A workspace configured to use the Socotra API.

For more information about using Postman, see: [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api).

Key concepts [#key-concepts]

What is a quote? [#what-is-a-quote]

A **quote** is a price estimate for an insurance policy. A quote goes through six steps from creation to issuance:

1. Creation (as a draft quote)
2. Validation
3. Pricing
4. Underwriting checks
5. Acceptance
6. Issuance

Upon issuance of a quote, a *policy* is created.

What is a policy? [#what-is-a-policy]

A *policy* is the actual insurance product contract provided to the applicant.

Life cycle of a quote [#life-cycle-of-a-quote]

This section lists each chronological stage of a quote from creation to issuance.

<Image src="/images/execute-a-quote-to-bind/image2.png" alt="alt text" width={1738} height={376} unoptimized />

1. Draft (creation):
   * When a quote is created, it’s in a draft state. While in a draft state, the quote’s data, coverage terms, and attributes (like startTime and endTime) can be freely modified.
   * This is the only state in which this information can be changed. Once validated, the quote cannot be modified any further.

2. Validated: When a quote goes through validation, it’s checked against the product configuration and any other custom validation. Upon successful validation, the quote’s attributes can no longer be changed.

3. Priced: The quote has pricing generated.

4. Underwritten: The quote passes underwriting checks.

5. Accepted: The quote has been accepted, but not yet issued. This state requires successfully passing underwriting checks.

6. Issued: The quote has been issued, creating a resulting policy.

Resetting a quote [#resetting-a-quote]

Though a quote’s attributes can’t be modified after validation, it is possible to reset a quote. Doing so clears any of the data added to the quote by the pricing and underwriting process.

To reset a quote, use the Reset Quote route in the Socotra Sample Collection (*Policy > Quotes > Reset Quote*), making sure to use the locator for the quote you’d like to reset in the `quoteLocator` path variable.

Atypical quote states [#atypical-quote-states]

In addition to the typical lifecycle states of a quote, a quote can also exist in the following states when there are issues.

* **UnderwritingBlocked**: The quote cannot proceed due to underwriting flags but is not in a denied state of declined or rejected.
* **Declined**: The quote did not pass underwriting, but it can be re-underwritten or reset to draft.
* **Rejected**: The quote did not pass underwriting and cannot be re-underwritten or reset, but it can be discarded.
* **Refused**: Indicates that the customer has decided not to accept coverage. These quotes can be discarded or reset to draft.
* **Discarded**: The quote has been disposed of, so it cannot be processed further. It will not appear in any response, unless directly fetched by locator.

Ready to begin? [#ready-to-begin]

Continue onto the next section to learn how to execute a quote to bind using the Socotra API.

Steps [#steps]

Part 1 - Create a quote [#part-1---create-a-quote]

The first step is to **create a quote**. Upon creation, the quote will exist as a draft quote that can be modified up until validation.

To create a quote, follow these steps:

1. Log into your Postman account and navigate to the Socotra Sample Collection.
2. While viewing the Socotra Sample Collection, navigate to **Policy > Quotes > Create Quote**.
3. Click the **Body** tab.

<Image src="/images/execute-a-quote-to-bind/image7.png" alt="image1" width={1999} height={1261} unoptimized />

4. Once you’re viewing the Body tab of the Create Quote (HO3) request, you should see the following request information in JSON format (depicted in the screenshot below):

<Image src="/images/execute-a-quote-to-bind/image10.png" alt="image2" width={1999} height={1261} unoptimized />

5. This data is set up for you to make a draft quote immediately.
   * For a description of how this is set up, see the subsection below: Request body breakdown.
   * To create the quote, click **Send**.

6. After clicking **Send**, you should receive a response message indicating success like the one below:

<Image src="/images/execute-a-quote-to-bind/image6.png" alt="image3" width={1999} height={1261} unoptimized />

Once you’ve successfully created a quote in a draft state, the next step is validation.

Continue onto Part 2: Validate the quote to learn how to validate the quote.

We also recommend that you read the Request body breakdown section below to learn more about the request to make a draft quote.

Request body breakdown [#request-body-breakdown]

<Image src="/images/execute-a-quote-to-bind/image4.png" alt="image4" width={1999} height={1405} unoptimized />

Screenshot of the request body in Postman.

In this section, we’ll break down each of the top-level attributes of the request body.

* [productName`: This is the name of the product the quote is created for. This corresponds to an existing product on the tenant configuration (as established in `Create a tenant configuration file](/getting-started/create-a-tenant-configuration-file)).
* `accountLocator`: This is the unique identifier of the policyholder account the quote is being created for.
  * The text in curly braces, `accountLocator`, is referring to an environment variable in the Socotra Sample Environment in Postman.
  * Double-check this value is populated by navigating to **Environments > Socotra Sample Environment** in Postman and checking to make sure the `accountLocator` field is populated.

<Image src="/images/execute-a-quote-to-bind/image9.png" alt="image5" width={1999} height={1261} unoptimized />

The location of the accountLocator environment variable in the Socotra Sample Environment in Postman

* `startTime`: This is the datetime value of when the policy would go into effect.
  * In this example, the startTime is `yesterday`, a built-in Postman variable that automatically generates the datetime value for the day prior to the day the request runs.

* `elements`: The top-level elements field is an array of elements that form part of the insurance product.
  * Remember from [Create a tenant configuration file](/getting-started/create-a-tenant-configuration-file) that an element is any policyLine, exposureGroup, exposure, or coverage.

  * Elements define what the product offers and how it's administered.

  * In this sample, the product’s **exposure** is the object with the type `dwelling`.
    * The exposure has sub-nested elements. In this case, they are **coverages**.

  * The exposure also has its own `data` object that contains information about the exposure, including `windHailExclusion`, `distanceToCoast`, and `yearBuilt`.

  * The screenshot below shows a visual breakdown of the product, exposures, and coverages.

<Image src="/images/execute-a-quote-to-bind/image5.png" alt="image6" width={1999} height={1261} unoptimized />

A visual breakdown of the Product, Exposure, and Coverage in the JSON request body.

* `data`: The top-level data object contains information about the quote, including:
  * `applicantFirstName`: The first name of the person applying for insurance.
  * `applicantLastName`: The last name of the person applying for insurance.
  * `applicantDob`: The date of birth of the person applying for insurance.
  * `applicantInsuranceScore`: The insurance score of the person applying for insurance.
  * `noPriorInsurance`: Whether or not the applicant has never had insurance before.

* `billingTrigger`: Sets when the applicant is billed for the insurance. In this example, it’s upon `issue`, meaning that they will be billed when the quote is issued.

* `preferences`: Sets various preferences related to the quote. In this example, it’s setting the billing installment plan preference to `monthly10`.

* `delinquencyPlanName`: Sets the default delinquency plan, which sets the behavior if payment is not received. In this example, it’s setting the delinquency plan to `defaultDelinquencyPlan`.

Part 2 - Validate the quote [#part-2---validate-the-quote]

The next step in the quote lifecycle is validation. When a quote goes through validation, it’s checked against the product configuration and any other custom validation.

Once validated, the quote’s attributes cannot be changed any further.

Follow the steps below to validate the quote.

1. While viewing the Socotra Sample Collection, navigate to **Policy > Quotes > Validate Quote**.
2. Make sure your `quoteLocator` is set as an environment variable.
3. Click **Send**.
4. Upon successful validation, the response body should show that the quote state has changed to validated.

<Image src="/images/execute-a-quote-to-bind/image13.png" alt="image7" width={1999} height={1261} unoptimized />

Continue on to Part 3 to learn how to price the quote.

Part 3 - Price the quote [#part-3---price-the-quote]

Follow the steps below to validate the quote.

1. While viewing the Socotra Sample Collection, navigate to **Policy > Quotes > Price Quote**.
2. Make sure your `quoteLocator` is set as an environment variable.
3. Click **Send**.
4. Upon successful validation, the response body should show that the quote state has changed to priced.

<Image src="/images/execute-a-quote-to-bind/image1.png" alt="image8" width={1999} height={1261} unoptimized />

Continue on to Part 4 to learn how to underwrite the quote.

Part 4 - Underwrite the quote [#part-4---underwrite-the-quote]

1. While viewing the Socotra Sample Collection, navigate to **Policy > Quotes > Underwrite Quote**.
2. Make sure your `quoteLocator` is set as an environment variable.
3. Click **Send**.
4. Upon successful validation, the response body should show that the quote state has changed to underwritten.

<Image src="/images/execute-a-quote-to-bind/image8.png" alt="image9" width={1999} height={1261} unoptimized />

Continue on to Part 5 to learn how to accept the quote.

Part 5 - Accept the quote [#part-5---accept-the-quote]

1. While viewing the Socotra Sample Collection, navigate to **Policy > Quotes > Accept Quote**.
2. Make sure your `quoteLocator` is set as an environment variable.
3. Click **Send**.
4. Upon successful validation, the response body should show that the quote state has changed to accepted.

<Image src="/images/execute-a-quote-to-bind/image12.png" alt="image10" width={1999} height={1261} unoptimized />

Continue on to Part 6 to learn how to issue the quote.

Part 6 - Issue the quote [#part-6---issue-the-quote]

1. While viewing the Socotra Sample Collection, navigate to **Policy > Quotes > Issue Quote**.
2. Make sure your `quoteLocator` is set as an environment variable.
3. Click **Send**.
4. Upon successful validation, the response body should show that the quote state has changed to issued.

Recap [#recap]

In this tutorial, we covered:

* The basics of quotes and policies.
* How to create, validate, price, underwrite, accept, and issue a quote via the API.

In the next resource, we’ll cover what to do and how to make and execute changes on policies.

Ready for the next module? [#ready-for-the-next-module]

See [Execute policy transactions](/getting-started/execute-policy-transactions) to continue this learning path.


# Execute policy transactions



import Image from 'next/image';

This article explains how to **execute policy transactions** in the Socotra Insurance Suite.

Overview [#overview]

What will I learn in this tutorial? [#what-will-i-learn-in-this-tutorial]

By the end of this tutorial, you will have an understanding of:

* Policies in Socotra, including their terms and segments.
* How to describe, change, renew, cancel, or reinstate a policy using the Socotra API.

What will I need? [#what-will-i-need]

You will need the following:

* A Postman account
* [A copy of the Socotra Sample Collection and Environment](/getting-started/socotra-sample-postman-collection-and-environment)
* A workspace configured to use the Socotra API

For more information about using Postman, see: [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api)

Key concepts [#key-concepts]

What is a policy? [#what-is-a-policy]

In Socotra, a **policy** is a transaction between the **insurer** (an insurance company) and the **insured** (a customer). Policies outline products provided to the insured by the insurer.

For example, a home owner’s insurance policy typically contains information related to:

* The exposure (the home being insured)
* The coverages (definitions of how much the home is insured for)
* The general administration of the policy

Policies are subdivided into **terms** and **segments**.

What are terms and segments? [#what-are-terms-and-segments]

Terms [#terms]

In an insurance policy, a **term** is the period of time between the policy's start and end.

A term spans from the initial effective date to the expiration date of the policy.

When a policy is renewed, a new term is created and the expiration date is pushed further into the future, typically by the same length of time as the original term.

For example, the terms of a homeowners policy that’s been renewed twice would look something like sample below:

* Term 0: January 2024 - January 2025 (initial policy creation)
* Term 1: January 2025 - January 2026 (first renewal)
* Term 2: January 2026 - January 2027 (second renewal)

Segments [#segments]

In an insurance policy, a segment is a subdivision of a term. A segment contains all of the elements of a policy, meaning any of the following:

* Products
* Policy Lines
* Exposure Groups
* Exposures
* Coverages

When a policy is first created, it has a single default term and a single default segment. The graphic below shows an example of a basic policy.

<Image src="/images/execute-policy-transactions/image9.png" alt="alt text" width={1999} height={1082} unoptimized />

Graphical representation of a basic policy, term, segment, and elements. It begins on the Effective Date (Eff Date) and ends on the Expiration Date (Exp Date).

<span id="policyTransaction" />

What is a policy transaction? [#what-is-a-policy-transaction]

A **policy transaction** is a change made to a policy. There are four basic types of policy transactions that can be made to an existing policy:

* Change
* Renew
* Cancel
* Reinstate

<Callout>
  In addition to the above, an **issuance policy transaction** is automatically created and issued by the system when a quote moves to the `issued` state, and the resulting policy is created, while a **reversal policy transaction** may be issued to reverse a previously issued transaction. See the [Policy Transactions](/features/policy-management/policy-transactions) feature guide for more information.
</Callout>

It takes two steps to make a policy transaction:

* Creation (define instructions for what to do to the policy)
* Issuance (execute the instructions)

In the section below, we're going to cover some examples of each of these types of policy transactions.

Example scenarios [#example-scenarios]

Example 1 - Changing a policy [#example-1---changing-a-policy]

<Image src="/images/execute-policy-transactions/image14.png" alt="image1" width={1999} height={1135} unoptimized />

In this example, we see a policy with a single term and two segments. This means that the policy was modified sometime during the first term.

In Segment A, they have two coverages:

* **Coverage A**: $550,000 limit
* **Coverage B**: 10% limit

Mid-way through the customer’s first term, they request that their limit for Coverage A be increased from $550,000 to $600,000. This would be accomplished by creating and issuing a change transaction.

Upon issuance of the change transaction, a new segment is created in the term with two coverages:

* **Coverage A**: $600,000 limit (increased from $550,000)
* **Coverage B**: 10% (stays the same)

Example 2 - Renewing a policy [#example-2---renewing-a-policy]

<Image src="/images/execute-policy-transactions/image5.png" alt="image2" width={1999} height={624} unoptimized />

In this example, we see a continuation from Example 1. The customer wants to renew their coverage, but they also want to add an additional Personal Property coverage. This would be accomplished by creating and issuing a renewal transaction containing data for the new coverage.

Upon issuance of the renewal transaction, the system would:

* Create a new term
* Create a new segment in the term
* Add all requested coverages to the new segment

Example 3 - Canceling a policy [#example-3---canceling-a-policy]

<Image src="/images/execute-policy-transactions/image13.png" alt="image3" width={1999} height={624} unoptimized />

Continuing the scenario in examples 1 and 2, the customer has decided they would like to cancel their policy, which has four months remaining until the end of its second term.

Upon creating and issuing the cancellation transaction, the system would make a “gap” segment to represent the remaining period where no coverage was provided to the customer.

Tutorials [#tutorials]

Scenario - Homeowner seeking to modify home insurance coverage [#scenario---homeowner-seeking-to-modify-home-insurance-coverage]

For these tutorials, let’s use the example of a homeowner called Homer Sample.

* Homer Sample owns a home with a roof that is 15 years old.
* He has an existing policy from Example Insurance with an effective date of January 1, 2024.
* The policy has two coverages:
  * Coverage A, with a limit of $550,000
  * Coverage B, with a limit of 10%

For these tutorials, we’ll use Postman to simulate policy transactions Socotra can make based on Homer Sample’s requested changes.

Tutorial 1 - Making a change to a policy [#tutorial-1---making-a-change-to-a-policy]

Homer Sample reaches out to Example Insurance Company with a request:

* Homer Sample wants to increase the coverage on his dwelling from **:math:`550,000** to **`\ 600,000**.
* He wants this to take effect on **June 1, 2024**.

We can easily accomplish this with the Socotra API.

However, before we can make any policy changes, first we need to locate his customer account number.

<span id="11---locating-customers-account-number-in-postman" />

1.1 - Locating customer's account number in Postman [#11---locating-customers-account-number-in-postman]

To locate a customer’s account number using the Socotra API in Postman, follow these steps:

1. In the Socotra Sample Collection, navigate to **Policy > Accounts > List Accounts**.
2. Click **Send** to run the request.
3. The response body will include a list of all the accounts on the current tenant.
4. Locate the account you want to use. For this tutorial, we’ll use Homer Sample’s account.

<Image src="/images/execute-policy-transactions/image3.png" alt="image4" width={1999} height={1223} unoptimized />

5. Copy the account’s `locator` value (the unique identifier of the account) and paste it into the `accountLocator` environment variable in the Socotra Sample Environment.

**Tip**: Keep the Socotra Sample Environment open as a tab in Postman so you can easily switch back and forth between it and the requests.

<span id="12---locating-customers-policy-in-postman" />

1.2 - Locating customer's policy in Postman [#12---locating-customers-policy-in-postman]

The next step is to locate Homer Sample’s policy.

When a quote is issued in Socotra, the system automatically generates a corresponding policy. To find the policy, we’ll first search for the issued quote that created it.

To locate a customer’s policy using the Socotra API in Postman, follow these steps:

1. In the Socotra Sample Collection, navigate to **Policy > Quotes > List Account’s Quotes**.
2. Run the request.
3. Locate the quote in the response body. The relevant quote should have a `quoteStatus` of `issued`.

<Image src="/images/execute-policy-transactions/image8.png" alt="image5" width={1999} height={1223} unoptimized />

4. Once you’ve identified the issued quote, scroll down until you find the quote’s `policyLocator`.

<Image src="/images/execute-policy-transactions/image6.png" alt="image6" width={1999} height={1223} unoptimized />

5. Copy the policy locator and paste it into the `policyLocator` environment variable in the Socotra Sample Environment.

<span id="13---retrieving-customers-policy-details" />

1.3 - Retrieving customer's policy details [#13---retrieving-customers-policy-details]

Now that we have Homer Sample’s policy number, we can retrieve details about the elements of his policy.

In particular, we’re interested in finding the policy’s:

* Exposures (i.e. the dwelling)
* The exposure’s coverages

To retrieve a customer’s policy details, we can use the Describe Policy Snapshot endpoint of the Socotra API, which retrieves information about a policy as it exists at a current date and time.

To locate a customer’s policy details, follow these steps:

1. In the Socotra Sample Collection, navigate to **Policy > Policies > Describe Policy Snapshot**.

2. In the date query parameter, enter the following: 2024-06-01T00:00:00Z.
   1. This is a timestamp that tells the endpoint to retrieve the policy as it existed on the specified date.
   2. In this scenario, Homer Sample wants the insurance coverage to change on this date, so we’ll retrieve the policy information at this point to ensure we have the most up-to-date information.

3. Run the request.

The response body will look similar to the JSON contained in the code block below:

```json
{
	"locator": "01J5E660YXGBBNT26TQESCZHQF",
	"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
	"productName": "Ho3",
	"timezone": "America/New_York",
	"currency": "USD",
	"transaction": {
		"locator": "01J5E660YXGBBNT26TQESCZHQF",
		"transactionCategory": "issuance",
		"transactionType": "issuance",
		"effectiveTime": "2024-01-01T00:00:00Z",
		"issuedTime": "2024-08-16T18:11:45.647779Z",
		"preferences": {
			"installmentPreferences": {
				"installmentPlanName": "monthly10"
			}
		},
		"segment": {
			"locator": "01J5E66VBHEQWA7Z8Y3XDVFAXV",
			"segmentType": "coverage",
			"startTime": "2024-01-01T00:00:00Z",
			"endTime": "2025-01-01T00:00:00Z",
			"element": {
				"type": "Ho3Segment",
				"locator": "01J5E66VBHEQWA7Z8Y3XDVFAXV",
				"parentLocator": "01J5E66VBHEQWA7Z8Y3XDVFAXV",
				"elements": [
					{
						"type": "DwellingPolicy",
						"locator": "01J5E66VBJYBESTDJFYAZBPAXX",
						"parentLocator": "01J5E66VBHEQWA7Z8Y3XDVFAXV",
						"elements": [
							{
								"type": "Coverage_bPolicy",
								"locator": "01J5E66VBMACX1D1K00K0YYZNE",
								"parentLocator": "01J5E66VBJYBESTDJFYAZBPAXX",
								"coverageTerms": {
									"Coverage_b_limit": "CB20"
								},
								"staticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
								"originalEffectiveTime": "2024-01-01T00:00:00Z"
							},
							{
								"type": "Coverage_aPolicy",
								"locator": "01J5E66VBKYGJZT44JYPCNA3T6",
								"parentLocator": "01J5E66VBJYBESTDJFYAZBPAXX",
								"coverageTerms": {
									"Coverage_a_limit": "CA550000"
								},
								"staticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
								"originalEffectiveTime": "2024-01-01T00:00:00Z"
							}
						],
						"data": {
							"windHailExclusion": "No",
							"yearBuilt": 2013,
							"distanceToCoast": 3000,
							"occupancy": "Primary"
						},
						"staticLocator": "01J5E660YX1PHQNZ1F0404830V",
						"originalEffectiveTime": "2024-01-01T00:00:00Z"
					}
				],
				"data": {
					"applicantInsuranceScore": "800",
					"applicantDob": "1980-01-01",
					"applicantFirstName": "Homer",
					"applicantLastName": "Sample",
					"noPriorInsurance": "No"
				},
				"staticLocator": "01J5E660YXGBBNT26TQESCZHQF",
				"originalEffectiveTime": "2024-01-01T00:00:00Z"
			},
			"duration": 12
		}
	},
	"delinquencyPlanName": "defaultDelinquencyPlan"
}
```

The **`transaction`** object is the most relevant portion of the response body for the purposes of this tutorial. It contains all of the information about the segment, exposure, and coverages.

Navigating down the JSON tree, the transaction object contains:

* `transaction`
  * `segment` (a default period of 12 months from startTime to endTime)
    * `element` (the exposure group)
      * `elements` (the exposures, i.e. the dwelling)
        * `elements` (the coverages, i.e. Coverage\_aPolicy and Coverage\_bPolicy)

For the purposes of this tutorial, Homer Sample wants to change the `coverage_a_limit` from $550,000 to $600,000.

<span id="14---creating-a-change-transaction" />

1.4 - Creating a change transaction [#14---creating-a-change-transaction]

Now that we’ve located Homer Sample’s policy, we’re ready to create a change transaction to modify it.

There are essentially two steps to making any transaction, including change transactions:

* Creating the transaction
* Issuing the transaction

In this section, we’ll cover creating the transaction. In the next section, we’ll cover issuing the transaction.

We’re going to change the coverage from $550,000 (`CA550000`) to $600,000 (`CA600000`).

The code sample below shows the `Coverage_aPolicy` (extracted from the full code block above).

```json
{
	"type": "Coverage_aPolicy",
	"locator": "01J5E66VBKYGJZT44JYPCNA3T6",
	"parentLocator": "01J5E66VBJYBESTDJFYAZBPAXX",
	"coverageTerms": {
		"Coverage_a_limit": "CA550000"
	},
	"staticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
	"originalEffectiveTime": "2024-01-01T00:00:00Z"
}
```

The `staticLocator` is the unique identifier we'll use to target the coverage for modification.

To create a change transaction to a policy, follow these steps:

1. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Change > Create Change Transaction**.
2. Click the **Body** tab.
3. Paste the `staticLocator` value of the `Coverage_aPolicy` object into the request body.

<Image src="/images/execute-policy-transactions/image4.png" alt="image7" width={1999} height={1223} unoptimized />

4. Set the `effectiveTime` field to June 1, 2024 (`2024-06-01T00:00:00Z`).

<Image src="/images/execute-policy-transactions/image11.png" alt="image8" width={1999} height={1201} unoptimized />

5. Click **Send**.
6. You should receive a response message containing a `locator` value.

<Image src="/images/execute-policy-transactions/image1.png" alt="image9" width={1999} height={1223} unoptimized />

When you create a transaction, it’s assigned a unique identifier stored in the locator field. Note that the transaction is in a draft state, meaning it won’t go into effect until it’s issued.

1. Copy and paste the locator value into the transactionLocator environment variable in the Socotra Sample Environment.

<span id="15---issuing-a-change-transaction" />

1.5 - Issuing a change transaction [#15---issuing-a-change-transaction]

Now that we’ve created a change transaction for Homer Sample’s policy, we’re finally ready to issue the transaction.

To issue a change transaction, follow these steps:

1. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Change > Issue Change Transaction**.
2. Click **Send**.
3. You should receive a response indicating success.

<Image src="/images/execute-policy-transactions/image10.png" alt="image10" width={1999} height={1223} unoptimized />

<span id="16---viewing-the-changed-policy" />

1.6 - Viewing the changed policy [#16---viewing-the-changed-policy]

Now that the change transaction has been issued, we can check the policy to see the reflected changes to Homer Sample’s policy.

To do that, we’ll use the **Describe Policy Term** endpoint (**Policy > Policies > Describe Policy Term**). Running this endpoint for this policy reveals that there are now two subsegments:

* The original segment (the policy before the change)
* The new segment (the policy after the change)

The JSON in the code block below should look similar to your response body. Note the two objects in the *subsegments* array.

```json
{
	"policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
	"locator": "01J5E660YXGBBNT26TQESCZHQF",
	"staticLocator": "01J5E660YXGBBNT26TQESCZHQF",
	"termNumber": 0,
	"startTime": "2024-01-01T00:00:00Z",
	"endTime": "2025-01-01T00:00:00Z",
	"duration": 12,
	"durationBasis": "months",
	"subsegments": [
		{
			"locator": "01J5E66VBHEQWA7Z8Y3XDVFAXV",
			"type": "coverage",
			"startTime": "2024-01-01T00:00:00Z",
			"endTime": "2024-06-01T00:00:00Z",
			"duration": 5.001344086021505,
			"elements": [
				{
					"locator": "01J5E66VBKYGJZT44JYPCNA3T6",
					"staticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
					"type": "Coverage_aPolicy",
					"chargeSummaries": {
						"coverage_a_premium": 343.84
					}
				},
				{
					"locator": "01J5E66VBMACX1D1K00K0YYZNE",
					"staticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
					"type": "Coverage_bPolicy",
					"chargeSummaries": {
						"coverage_b_premium": 68.77
					}
				},
				{
					"locator": "01J5E66VBHEQWA7Z8Y3XDVFAXV",
					"staticLocator": "01J5E660YXGBBNT26TQESCZHQF",
					"type": "Ho3Segment",
					"data": {
						"noPriorInsurance": "No",
						"applicantInsuranceScore": "800",
						"applicantDob": "1980-01-01",
						"applicantFirstName": "Homer",
						"applicantLastName": "Sample"
					}
				},
				{
					"locator": "01J5E66VBJYBESTDJFYAZBPAXX",
					"staticLocator": "01J5E660YX1PHQNZ1F0404830V",
					"type": "DwellingPolicy",
					"data": {
						"occupancy": "Primary",
						"windHailExclusion": "No",
						"yearBuilt": 2013,
						"distanceToCoast": 3000
					}
				}
			]
		},
		{
			"locator": "01J5E7AV7P2CEWGEX4K034V1XE",
			"type": "coverage",
			"startTime": "2024-06-01T00:00:00Z",
			"endTime": "2025-01-01T00:00:00Z",
			"duration": 6.998655913978495,
			"elements": [
				{
					"locator": "01J5E7AV7QBNBRHTTGQHPXHKDW",
					"staticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
					"type": "Coverage_aPolicy",
					"chargeSummaries": {
						"coverage_a_premium": 481.16
					}
				},
				{
					"locator": "01J5E7AV7RE6HPEDDFE2RSTR57",
					"staticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
					"type": "Coverage_bPolicy",
					"chargeSummaries": {
						"coverage_b_premium": 96.23
					}
				},
				{
					"locator": "01J5E7AV7P2CEWGEX4K034V1XE",
					"staticLocator": "01J5E660YXGBBNT26TQESCZHQF",
					"type": "Ho3Segment",
					"data": {
						"applicantInsuranceScore": "800",
						"applicantDob": "1980-01-01",
						"applicantFirstName": "Homer",
						"applicantLastName": "Sample",
						"noPriorInsurance": "No"
					}
				},
				{
					"locator": "01J5E7AV7PP2XY7593HGP537HY",
					"staticLocator": "01J5E660YX1PHQNZ1F0404830V",
					"type": "DwellingPolicy",
					"data": {
						"windHailExclusion": "No",
						"yearBuilt": 2013,
						"distanceToCoast": 3000,
						"occupancy": "Primary"
					}
				}
			]
		}
	]
}
```

Tutorial 2 - Renewing a policy [#tutorial-2---renewing-a-policy]

Now that we’ve practiced making and executing a change to a policy, let’s try renewing a policy. Homer Sample has decided that he want to renew his coverage:

* His original term was from January 2024 to January 2025.
* He wants to renew coverage through January 2026.
* He also wants to add a personal property coverage to his dwelling.

With the Socotra API, we can easily renew the policy while also adding a new coverage.

**Note**: For a refresher on how to locate a customer’s account number or policy number, refer back to sections 1.1 and 1.2.

To create a renewal transaction for a policy, follow these steps:

1. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Renewal > Create Renewal Transaction**.
2. Click the **Body** tab. You should see something similar to the JSON in the code block below:

```json
[
	{
		"action": "params",
		"effectiveTime": "<insert_time_stamp_here>"
	},
	{
		"action": "add",
		"elements": [
			{
				"parentLocator": "<insert_dwelling_locator_here>",
				"type": "Personal_Property"
			}
		]
	}
]
```

The code block above contains the data required to add a coverage to a policy during the renewal process. There are two placeholders:

* “effectiveTime”: “`<insert_time_stamp_here>`”
* “parentLocator”: “`<insert_dwelling_locator_here>`”

For the `<insert_time_stamp_here>` placeholder, you should provide a time stamp that’s on the same day as the end date of the previous segment.

The excerpt below shows you where to find the segment’s `startTime` and `endTime` (near the bottom).

```json
{
    "locator": "01J5E660YXGBBNT26TQESCZHQF",
    "accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
    "productName": "Ho3",
    "timezone": "America/New_York",
    "currency": "USD",
    "transaction": {
        "locator": "01J5E7848G8Y1Q9TAYMFFCMH0S",
        "transactionCategory": "change",
        "transactionType": "change",
        "effectiveTime": "2024-06-01T00:00:00Z",
        "issuedTime": "2024-08-16T18:31:25.332935Z",
        "preferences": {
            "installmentPreferences": {
                "installmentPlanName": "monthly10"
            }
        },
        "segment": {
            "locator": "01J5E7AV7P2CEWGEX4K034V1XE",
            "segmentType": "coverage",
            "startTime": "2024-06-01T00:00:00Z",
            "endTime": "2025-01-01T00:00:00Z",
            "element": {
        // ... <SHORTENED FOR BREVITY> ...
```

To find the effective time, look for the `endDate` of the previous term.

For example, if the `endDate` of the previous term is `2025-01-01T00:00:00Z`, the time stamp used for renewal should be the same value. This shows that the policy renews on the same day that the old policy ended so that coverage does not lapse.

To find the unique identifier of the dwelling, we can look at the response body of Describe Policy Snapshot. You can find the dwelling locator at `transaction.segment.element.elements.[0].locator` (under the `type` value `DwellingPolicy`).

```json
{
	"locator": "01J5E660YXGBBNT26TQESCZHQF",
	"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
	"productName": "Ho3",
	"timezone": "America/New_York",
	"currency": "USD",
	"transaction": {
		"locator": "01J5E7848G8Y1Q9TAYMFFCMH0S",
		"transactionCategory": "change",
		"transactionType": "change",
		"effectiveTime": "2024-06-01T00:00:00Z",
		"issuedTime": "2024-08-16T18:31:25.332935Z",
		"preferences": {
			"installmentPreferences": {
				"installmentPlanName": "monthly10"
			}
		},
		"segment": {
			"locator": "01J5E7AV7P2CEWGEX4K034V1XE",
			"segmentType": "coverage",
			"startTime": "2024-06-01T00:00:00Z",
			"endTime": "2025-01-01T00:00:00Z",
			"element": {
				"type": "Ho3Segment",
				"locator": "01J5E7AV7P2CEWGEX4K034V1XE",
				"parentLocator": "01J5E7AV7P2CEWGEX4K034V1XE",
				"elements": [
					{
						"type": "DwellingPolicy",
						"locator": "01J5E7AV7PP2XY7593HGP537HY",
						"parentLocator": "01J5E7AV7P2CEWGEX4K034V1XE",
						"elements": [
							{
								"type": "Coverage_bPolicy",
								"locator": "01J5E7AV7RE6HPEDDFE2RSTR57",
								"parentLocator": "01J5E7AV7PP2XY7593HGP537HY",
								"coverageTerms": {
									"Coverage_b_limit": "CB20"
								},
								"staticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
								"originalEffectiveTime": "2024-01-01T00:00:00Z"
							},
							{
								"type": "Coverage_aPolicy",
								"locator": "01J5E7AV7QBNBRHTTGQHPXHKDW",
								"parentLocator": "01J5E7AV7PP2XY7593HGP537HY",
								"coverageTerms": {
									"Coverage_a_limit": "CA600000"
								},
								"staticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
								"originalEffectiveTime": "2024-01-01T00:00:00Z"
							}
						],
						"data": {
							"windHailExclusion": "No",
							"yearBuilt": 2013,
							"distanceToCoast": 3000,
							"occupancy": "Primary"
						},
						"staticLocator": "01J5E660YX1PHQNZ1F0404830V",
						"originalEffectiveTime": "2024-01-01T00:00:00Z"
					}
				],
				"data": {
					"applicantInsuranceScore": "800",
					"applicantDob": "1980-01-01",
					"applicantFirstName": "Homer",
					"applicantLastName": "Sample",
					"noPriorInsurance": "No"
				},
				"staticLocator": "01J5E660YXGBBNT26TQESCZHQF",
				"originalEffectiveTime": "2024-01-01T00:00:00Z"
			},
			"duration": 6.998655913978495,
			"basedOn": "01J5E66VBHEQWA7Z8Y3XDVFAXV"
		}
	},
	"delinquencyPlanName": "defaultDelinquencyPlan"
}
```

The value we want to copy and paste into the renewal request body is the `staticLocator` of the dwelling.

So, for a policy that renews on January 1 2025, we’d use a request body something like the one below:

```json
[
	{
		"action": "params",
		"effectiveTime": "2025-01-01T00:00:00Z"
	},
	{
		"action": "add",
		"elements": [
			{
				"parentLocator": "01J5E7AV7PP2XY7593HGP537HY",
				"type": "Personal_Property"
			}
		]
	}
]
```

3. Click **Send** to execute the request.
4. You should see a response body like the one in the screenshot below.

<Image src="/images/execute-policy-transactions/image7.png" alt="image11" width={1999} height={1223} unoptimized />

5. Copy and paste the `locator` into the `renewalTrxLocator` environment variable in the Socotra Sample Environment.
6. Navigate to the Issue Renewal Transaction endpoint.
7. Click **Send** to execute it.

You should receive a response like the one below, indicating that the policy has been renewed.

<Image src="/images/execute-policy-transactions/image2.png" alt="image12" width={1999} height={1223} unoptimized />

Tutorial 3 - Canceling a policy [#tutorial-3---canceling-a-policy]

Now that we’ve renewed the policy, let’s learn how to cancel a policy. Homer Sample has decided that he want to cancel his coverage:

* His original term was from **January 2024** to **January 2025**
* He renewed for a new term from **January 2025** to **January 2026**
* In **March 2025**, he decided he wanted to cancel his policy.

With the Socotra API, we can easily cancel the policy. This is considerably more straightforward than changing or renewing a policy because there’s no request body to build. We simply need to create a cancellation transaction and then issue it.

1. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Cancellation > Create Cancellation Transaction**.

2. Click the **Body** tab.
   1. Set the timestamp to the requested cancellation date.
   2. In this case, March 1 2025 is the requested end date

3. For a time stamp, this is: `2025-03-01T00:00:00Z`.

4. Click **Send**.

5. You should receive a response message similar to the one in the screenshot below:

6. Copy the `locator` field in the response body.
   1. This is the unique identifier for the transaction.
   2. We’ll use this value to issue the transaction.

7. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Cancellation > Issue Cancellation Transaction**.

8. Paste the `locator` value you copied in step 6 into the `transactionLocator` field.

9. Click **Send**.

10. You should receive a response indicating success.

Tutorial 4 - Reinstating a policy [#tutorial-4---reinstating-a-policy]

Finally, let’s practice reinstating a policy. Homer Sample has changed his mind. After canceling his policy in March of 2025, he decided in July of 2025 to reinstate the policy.

Reinstating the policy is a virtually identical process to canceling it, except we’ll be using the Reinstatement endpoints instead of the cancellation endpoints.

1. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Reinstatement > Create Reinstatement Transaction**.

2. Click the **Body** tab.

3. Set the timestamp to July 2025 (e.g. *2025-07-01T00:00:00Z*).

4. Click **Send**.

5. You should receive a response message similar to the one in the screenshot below:

6. Copy the `locator` field in the response body.
   1. This is the unique identifier for the transaction.
   2. We’ll use this value to issue the transaction.

7. While viewing the Socotra Sample Collection, navigate to **Policy > Policies > Post-issuance Flows > Policy Reinstatement > Issue Reinstatement Transaction**.

8. Paste the `locator` value you copied in step 6 into the `transactionLocator` field.

9. Click **Send**.

10. You should receive a response indicating success.

Ready for the next module? [#ready-for-the-next-module]

See [Trigger billing, pay, and invoices](/getting-started/trigger-billing-pay-and-invoices) to continue this learning path.


# Introduction to Socotra



This article provides an **introduction to the Socotra Insurance Suite**.

Overview [#overview]

What is Socotra? [#what-is-socotra]

Socotra is the most powerful policy and billing technology in the insurance industry. Over 40 insurers worldwide trust Socotra to deliver the fastest product launches and updates, unrivaled data access and control, and the best support for insurance at massive scale–all for the lowest total cost of ownership. With true cloud and open APIs, Socotra is the most mature insurance core platform on the market. Learn more at [https://socotra.com](https://socotra.com) .

What is Socotra Insurance Suite? [#what-is-socotra-insurance-suite]

Socotra Insurance Suite is a policy administration and billing service for the insurance industry. It offers API and UI tools to help you build a modern, flexible, and uniquely scalable platform alongside your existing proprietary or legacy insurance systems.

What is the Getting Started with Socotra learning path? [#what-is-the-getting-started-with-socotra-learning-path]

The Getting Started with Socotra learning path is a set of tutorials, guides, and other documentation that will guide you through using Socotra for the first time.

This is the first article in this learning path.

Overall, this learning path will prepare you to:

* Log into Socotra
* Learn about the key concepts behind the Socotra data model
* Set up an insurance product
* Work with quotes

Have questions? [#have-questions]

If you have any questions or need assistance at any stage of this learning process, feel free to reach out to [support@socotra.com](mailto:support@socotra.com) for assistance.

Ready for the next module? [#ready-for-the-next-module]

See [Log into Socotra](/getting-started/log-into-socotra) to continue this learning path.


# Log into Socotra



import Image from 'next/image';

This article explains how to **log into the Socotra Insurance Suite** through the web app.

Overview [#overview]

What will I learn? [#what-will-i-learn]

By the end of this guide, you will know how to log into the Socotra web app.

What will I need? [#what-will-i-need]

You'll need a **set of credentials to log into your business account**.

To gain access to a Socotra business account with user credentials, navigate to [https://www.socotra.com/contact-us/](https://www.socotra.com/contact-us/) and fill out the form to speak to a Sales representative and book a demo.

Or, you can reach out by sending an email to [sales@socotra.com](mailto:sales@socotra.com).

If you have issues with your credentials, reach out to your Socotra representative for assistance.

Key concepts [#key-concepts]

What is a business account? [#what-is-a-business-account]

In Socotra, a **business account** is a representation of your organization. It provides a logical grouping of tenants and users in a Socotra environment.

In other words, a business account is your *unique instance of Socotra*, where you can configure and customize to the needs of your business.

Socotra can create one or more business accounts for your organization depending on your unique needs. You’ll receive login credentials to access your business account through secure channels to contacts you authorize.

Your Socotra representative will guide you through the process of making a business account and receiving credentials.

Ready to begin? [#ready-to-begin]

Continue onto the next section to learn how to log into Socotra.

Steps [#steps]

1. Navigate to the [Socotra web app](https://ui-ec-sandbox.socotra.com/en/login) login page.
2. At the login screen, enter the name of your business account.
3. Click **Proceed to Login**.

<Image src="/images/log-into-socotra/business-account-input-page.png" alt="The Socotra business account input page." width={7032} height={4456} unoptimized />

4. You should be redirected to the sign in page for your account.

<Image src="/images/log-into-socotra/business-account-login-page.png" alt="The Socotra business account login page." width={7032} height={4456} unoptimized />

5. Enter your username and password in the appropriate fields.
6. Click **Sign In** to sign into your Socotra business account.

Recap [#recap]

Once you click **Sign in**, you should successfully log into your business account. If you experience any issues, we recommend taking the following steps:

1. Make sure that you’re trying to log into your business account.
2. Double-check that you’re inputting your login information correctly.

If after performing these steps you still can’t log in, reach out to [support@socotra.com](mailto:support@socotra.com).

Ready for the next module? [#ready-for-the-next-module]

See [Create a tenant configuration file](/getting-started/create-a-tenant-configuration-file) to continue this learning path.


# Overview - Tenants



import Image from 'next/image';

This article provides an **overview of tenants** in the Socotra Insurance Suite.

What is a tenant? [#what-is-a-tenant]

A **tenant** is a dedicated instance of the Socotra insurance policy management system. Tenants allow you to isolate data related to insurance products in a highly customizable container.

A business account can contain one or more tenants. Business accounts usually have more than one tenant to keep data separate.

For example, it’s common to have a tenant for prototyping configurations and another for live business. Some organizations will have several tenants used exclusively for prototyping configurations, some for testing, and one for live business.

Tenants page [#tenants-page]

The **Tenants** page is where you can view a list of the tenants on your business account.

<Image src="/images/overview-tenants/sc-tenant-page.png" alt="Screenshot of the Tenants page" width={1999} height={1232} unoptimized />

We’ll break down each of the major features of this page.

* **Search bar**: In the search bar, you can enter a full or partial tenant name to filter the results that appear in the table.

* **Type filter**: In the type filter (next to the search bar), you can filter by what type of tenant you want to see in the results. There are three types of tenants:
  * **Production**: A tenant in a live environment that handles actual insurance business.
  * **Test**: A tenant used for prototyping configurations and doing any other testing.
  * **Retired**: A tenant that has been deactivated. Retired tenants are retained for record keeping purposes.

* **Created on**: A date stamp of when the tenant was created.

* **Locator**: Click the Locator icon to copy the unique identifier of the tenant.

* **Create Tenant**: Click the Create Tenant button to create a new tenant.

Tenant configuration page [#tenant-configuration-page]

Clicking on any non-retired tenant will bring you to the **tenant configuration page**.

<Image src="/images/overview-tenants/sc-tenant-page.png" alt="Screenshot of the Tenants page" width={1999} height={1232} unoptimized />

The tenant configuration workspace lets you modify details related to the tenant, including the name and the description.

The tenant configuration workspace is also where you can:

* Redeploy a product configuration file
* Download a product configuration file
* Promote a tenant
* Retire a tenant

There are two major sub-menus of the tenant configuration workspace: **Users** and **Resources**.

Users [#users]

The **Users** page (*Tenants > \[Selected Tenant] > Users*) is where you select which users configured on your business account have access to the tenant.

Resources [#resources]

The **Resources** page (*Tenants > \[Selected Tenant] > Resources*) is where you can upload documents, tables, and template resources to be used in the tenant.

<Image src="/images/overview-tenants/sc-tenant-resources-page.png" alt="Screenshot of a tenant's resources page." width={1999} height={1232} unoptimized />

This page contains tabs for two sub-concepts of resources: **Instances** and **Groups**.

Resource instances [#resource-instances]

A **resource instance** is an individual occurrence of a resource. In Socotra, the structure and name of a resource are defined separately from the data contained within the resource.

For example, it’s possible to define the blueprint of a table, including its static name and structure, and then create multiple instances of the resource that contain the actual data.

So, a blueprint called ExampleTable could have instances called ExampleTable2024, ExampleTable2025, and so on, that contain the actual data.

Resource groups [#resource-groups]

A **resource group** is a set of resource instances that become available based on the data parameters within the group, allowing for the selection of resources at specific times.

Ready for the next module? [#ready-for-the-next-module]

See [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api) to continue this learning path.


# Set up Postman to use the Socotra API



import Image from 'next/image';

This article explains how to **set up Postman to use the Socotra API**.

Overview [#overview]

The **Socotra API** provides a programmatic approach to exercising and building on top of the Socotra platform. All Socotra operations are available via a series of HTTP endpoints.

Postman is an API testing tool that makes it easy and accessible to test and familiarize yourself with how the Socotra API works.

What will I learn? [#what-will-i-learn]

By the end of this guide, you will know how to:

* Import a sample Socotra Postman collection and Socotra Postman environment.
* Edit your environment variables to authenticate against the Socotra API.
* Authenticate against the Socotra API.

What will I need? [#what-will-i-need]

You will need the following:

* [A copy of the Socotra Sample Collection and Environment](/getting-started/socotra-sample-postman-collection-and-environment)
* Credentials for logging into Socotra

To authenticate with the Socotra API, you’ll need a set of credentials for logging into your business account.

To gain access to a Socotra Insurance Suite business account with user credentials, navigate to [https://www.socotra.com/contact-us/](https://www.socotra.com/contact-us/) and fill out the form to speak to a Sales representative and book a demo.

Alternatively, you can reach out by sending an email to [sales@socotra.com](mailto:sales@socotra.com).

Issues with your credentials? [#issues-with-your-credentials]

If you’ve already reached out to Socotra, received credentials, but can no longer find them, or you’re having issues using the credentials, reach out to your Socotra representative for assistance.

Ready to begin? [#ready-to-begin]

Continue onto the next section to learn how to set up Postman to use the Socotra API.

Steps [#steps]

Part 1 - Set up your collection and environment [#part-1---set-up-your-collection-and-environment]

To get started making requests against the Socotra API, you’ll first need to import the Socotra Postman collection. The collection contains preformed requests that make it easier for you to test the API.

You’ll also need to import an environment, which is where you’ll input your credentials for authenticating against the API.

1. Navigate to [https://postman.com](https://postman.com).

2. Log into your Postman account.
   1. If you don’t have a Postman account, register for one and log in.

3. Once you’ve logged into Postman, you should see a screen similar to the one depicted in the screenshot below.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-postman-landing-page.png" alt="Screenshot of Postman once logged in." width={1999} height={1231} unoptimized />

4. In the left sidebar, click **Import**.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-import-button-callout.png" alt="Screenshot of clicking the import button in the left sidebar of Postman." width={1999} height={1231} unoptimized />

5. Upload the Socotra Postman collection you downloaded in the *What will I need* section above?

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-import-window.png" alt="Screenshot of the collection upload window in Postman." width={1999} height={1232} unoptimized />

6. After importing the collection, it should appear in the left sidebar.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-collection-in-sidebar.png" alt="Screenshot of a collection appearing in the left sidebar of Postman." width={1999} height={1232} unoptimized />

7. After importing the Postman collection, the next step is to import the Postman environment.
8. In the left sidebar, click **Environments**. Then, click **Import**.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-click-environment-then-import.png" alt="Screenshot of navigating to Environments, then Import, in Postman." width={1999} height={1231} unoptimized />

9. Upload the Socotra Postman environment you downloaded in the *What will I need?* section above.
10. After importing the environment, it should appear in the left sidebar.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-environment-in-sidebar.png" alt="Screenshot of an environment appearing in the left sidebar of Postman." width={1999} height={1232} unoptimized />

Part 2 - Set up your environment [#part-2---set-up-your-environment]

With the Socotra Postman collection and environment imported to your workspace, the next step is to update the environment with your authentication credentials.

The Postman environment is a convenient way of storing all of the data necessary for connecting with the Socotra API. In this part, we’ll walk through how to set up authentication so you can use the Socotra API.

1. In the left sidebar, click Environments.
2. Open the Socotra Sample Environment environment.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-open-environment.png" alt="Screenshot of navigating to an environment in Postman." width={1999} height={1232} unoptimized />

3. You should see a screen similar to the one depicted in the screenshot below.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-environment-variable-list.png" alt="Screenshot of Postman environment variables." width={1999} height={1232} unoptimized />

The variables defined in the Socotra Sample Environment are used throughout the Socotra Sample Collection. Some of the variables are used for authentication so that you can use the API. Other variables are used for storing data so that you can conveniently reference it when making API requests.

For right now, the three most important variables to cover are:

* `business_account_name`
* `business_account_username`
* `business_account_password`

As a reminder, this information is the same used when logging into the Socotra web app (for a refresher, see [Log in to Socotra](/getting-started/log-into-socotra).

4. Type your credentials in the `business_account_name`, `business_account_username`, and `business_account_password` fields.
   1. Make sure to type the information in both the **Initial value** and **Current value** columns
   2. See the screenshot below for an example of how this might look.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-credential-variable-callout.png" alt="Screenshot of the variables used to get authorization from the Socotra API in Postman." width={1999} height={1232} unoptimized />

5. Make sure that you save your changes. You can save in Postman by doing CTRL+S (Windows / Linux), CMD+S (Mac), or by pressing the Save button in the top-right corner of the screen.

With your three business environment variables inputted and saved, the next step is to get authentication from Socotra.

Part 3 - Authenticate with Socotra [#part-3---authenticate-with-socotra]

With your environment variables updated, the final step is to authenticate against the Socotra API.

1. In the left sidebar, click Collections.
2. Click the Socotra Sample Collection collection.
3. Click the Authorization tab.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-collection-authorization-tab.png" alt="Screenshot of navigating to the Authorization tab of a Postman collection." width={1999} height={1232} unoptimized />

4. Scroll down the page. You may notice some fields that have values in curly braces that are red. **Do not edit these values**.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-red-curly-brace-callout.png" alt="Screenshot calling out variables in red curly braces in Postman." width={1999} height={1232} unoptimized />

5. These values are referencing the variables established in the environment file. There is no environment selected, however.
6. In the top-right corner of the screen, click the **No environment** dropdown and select the environment called **Socotra Sample Environment**.
   1. This will tell Postman to use the variables declared in that environment.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-select-environment-dropdown.png" alt="Screenshot showing the environment selection dropdown menu in Postman." width={1999} height={1232} unoptimized />

7. Scroll down to the bottom of the page.
   1. Also, notice that the environment values are no longer red. This means that Postman is pointing to the environment file and populating the variables with the environment’s values.

8. Click **Get New Access Token**.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-click-get-new-access-token.png" alt="Screenshot calling out the Get New Access Token button in Postman." width={1999} height={1232} unoptimized />

9. After clicking **Get New Access Token**, a dialog box should appear alerting you that your authentication was successful. Click **Proceed** or wait for the window to automatically redirect you.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-click-proceed.png" alt="Screenshot of a window in Postman indicating authentication was successful." width={1999} height={1232} unoptimized />

10. A window will appear showing you an access token. Click **Use Token**.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-click-use-token.png" alt="Screenshot of the Use Token button in Postman." width={1999} height={1232} unoptimized />

11. Note that the access token expires five minutes after generation. Upon expiration, you’ll have to re-authenticate by refreshing the token.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-click-refresh-token.png" alt="Screenshot of the refresh token button in Postman." width={1999} height={1232} unoptimized />

Make a request to test your authentication [#make-a-request-to-test-your-authentication]

To make sure authentication was successful, you can run a simple endpoint of the Socotra API.

1. In the Socotra Sample Collection, navigate to **Socotra Sample Collection > Auth > Users > Describe Current User (Who am I?)**
   1. This is a very simple endpoint that returns basic information about the user making the API request, making it perfect for testing authentication.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-whoami-callout.png" alt="Screenshot of navigating to the Who Am I endpoint of the Socotra API." width={1999} height={1232} unoptimized />

2. Click **Send**.
3. If successful, you should receive a 200 OK code and a response body that looks something like the screenshot below:

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-whoami-response.png" alt="Screenshot of the response to running the Who Am I endpoint of the Socotra API." width={1999} height={1232} unoptimized />

4. If you receive 200 OK and a response body, congratulations! You’re ready to start using the Socotra API in Postman.
5. If you experience any issues, re-read this guide and check out the Troubleshooting section below.

Troubleshooting [#troubleshooting]

If you’re receiving an “Authentication failed - Couldn’t complete authentication. Check the Postman Console for more details” message like the one depicted in the screenshot above, follow this checklist:

1. Make sure you’ve selected the correct environment. For this tutorial, you should have **“Socotra Sample Environment”** selected in the dropdown in the top-right corner of the screen.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-select-environment-dropdown.png" alt="Screenshot showing the environment selection dropdown menu in Postman." width={1999} height={1232} unoptimized />

2. Make sure that your `business_account_name`, `business_account_username`, and `business_account_password` environment fields contain your login credentials. Review Part 2: Set up your environment to review the steps to do this. Your configuration should look something like the screenshot below.

<Image src="/images/set-up-postman-to-use-the-socotra-api/sc-credential-variable-callout.png" alt="Screenshot of the variables used to get authorization from the Socotra API in Postman." width={1999} height={1232} unoptimized />

Recap [#recap]

In this guide, we covered:

* How to import a sample Socotra collection and environment in Postman
* Edit an environment in Postman
* Get an access token for making requests to the Socotra API

Now that we have Postman set up, the next step is to explore the functionality that Socotra provides through its API.

Ready for the next module? [#ready-for-the-next-module]

See [Create an account](/getting-started/create-an-account) to continue this learning path.


# Socotra sample Postman collection and environment



Socotra provides a **sample Postman collection and environment** for following the [Getting Started with Socotra](/getting-started/introduction-to-socotra) learning path.

<Cards className="mt-4">
  <Card href="/Socotra-Sample-Collection.postman_collection.json" title="Download Collection" description="Save as Socotra-Sample-Collection.postman_collection.json." />

  <Card href="/Socotra-Sample-Environment.postman_environment.json" title="Download Environment" description="Save as Socotra-Sample-Environment.postman_environment.json." />
</Cards>


# Trigger billing, pay, and invoices



This article explains how to **trigger billing, pay, and invoices** in the Socotra Insurance Suite.

Overview [#overview]

What will I learn? [#what-will-i-learn]

By the end of this walkthrough, you will have an understanding of:

* When billing is triggered.
* The basics of installment lattices, installments, invoices, and payments.
* How to create a quote for a new business, bill it, and pay a generated invoice.

What will I need? [#what-will-i-need]

You will need the following:

* A Postman account
* [A copy of the Socotra Sample Collection and Environment](/getting-started/socotra-sample-postman-collection-and-environment)
* A workspace configured to use the Socotra API.

For more information about using Postman, see: [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api)

What is the billing life cycle? [#what-is-the-billing-life-cycle]

In Socotra, the **billing life cycle** is a set of processes that handles calculating charges and building invoices for insurance policies.

The billing life cycle also handles receiving and distributing payments towards invoices.

Walkthrough the billing life cycle [#walkthrough-the-billing-life-cycle]

The billing life cycle has six sequential stages:

1. Quote is issued (via API)
2. System generates an installment lattice
3. System generates installments
4. System generates invoice(s)
5. Payment is created (via API)
6. Payment is posted to invoice(s) (via API)

We'll cover each step in the subsections below.

Stage 1: Quote is issued (via API) [#stage-1-quote-is-issued-via-api]

The first stage of the billing life cycle occurs when a quote is issued.

Note: For more information on how to issue a quote, see: [Execute a quote to bind](/getting-started/execute-a-quote-to-bind)

Before a quote is issued, all of the requested insurance coverages are priced. That means that all of the charges related to the insurance coverage are calculated. Several types of charges can apply to insurance coverage, including:

* premiums
* taxes
* fees
* credits
* ceded premiums
* non-financial charges
* surcharges

When the quote is issued, all of the pricing information is sent to the Socotra billing service.

At this point, the billing service's main priority is to create one or more invoices for the insurance policy term. To accomplish that, it uses a data structure called an *installment lattice*.

Stage 2: System generates an installment lattice [#stage-2-system-generates-an-installment-lattice]

After receiving all of the pricing information from the quote, the next stage of the billing life cycle is for the system to generate an *installment lattice*.

* An **installment lattice** is a data structure that divides an insurance policy term into one or more frames.
* A **frame** is a data object that represents a single subdivision of an insurance policy term.

The number of frames an installment lattice contains depends on the installment plan used in the quote/policy.

Let's consider the following example: A person buys a homeowner's insurance policy, and the term's expected duration is 12 months. When the billing life cycle creates an installment lattice for the term, the number of frames it contains depends on the installment plan.

| Installment plan | # of months in term | # of frames |
| ---------------- | ------------------- | ----------- |
| Quarterly        | 12                  | 4           |
| Monthly          | 12                  | 12          |
| Monthly 10       | 12                  | 10          |

The code block below shows an installment lattice for an insurance policy term that lasts 12 months and has a "Monthly 10" installment plan.

```json
{
	"locator": "01J5E66WEQV8GGKSH5RTQAYCTB",
	"settingsLocator": "01J5E66WEK8SNY0QWJPSBKAVWG",
	"createdAt": "2024-08-16T18:11:46.092575Z",
	"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
	"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
	"termStartTime": "2024-01-01T00:00:00Z",
	"termEndTime": "2025-01-01T00:00:00Z",
	"termLocator": "01J5E660YXGBBNT26TQESCZHQF",
	"quoteLocator": "01J5E660YXGBBNT26TQESCZHQF",
	"policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
	"currency": "USD",
	"timezone": "America/New_York",
	"effectiveTime": "2024-01-01T00:00:00Z",
	"frames": [
		{
			"installmentStartTime": "2024-01-01T00:00:00Z",
			"installmentEndTime": "2024-01-31T05:00:00Z",
			"coverageStartTime": "2024-01-01T00:00:00Z",
			"coverageEndTime": "2024-03-06T06:32:44Z",
			"normalizedWeight": 0.181818181818,
			"coverageDuration": 2.170088112306,
			"generateTime": "2023-12-17T05:00:00Z",
			"dueTime": "2024-01-01T04:59:59.999Z",
			"installmentDuration": 0.974462365591
		},
		{
			"installmentStartTime": "2024-01-31T05:00:00Z",
			"installmentEndTime": "2024-02-29T05:00:00Z",
			"coverageStartTime": "2024-03-06T06:32:44Z",
			"coverageEndTime": "2024-04-09T03:21:49Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.102639125348,
			"generateTime": "2024-01-17T05:00:00Z",
			"dueTime": "2024-02-01T04:59:59.999Z",
			"installmentDuration": 0.998238783834
		},
		{
			"installmentStartTime": "2024-02-29T05:00:00Z",
			"installmentEndTime": "2024-03-31T04:00:00Z",
			"coverageStartTime": "2024-04-09T03:21:49Z",
			"coverageEndTime": "2024-05-11T20:49:05Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.079178750996,
			"generateTime": "2024-02-15T05:00:00Z",
			"dueTime": "2024-03-01T04:59:59.999Z",
			"installmentDuration": 1.001761216166
		},
		{
			"installmentStartTime": "2024-03-31T04:00:00Z",
			"installmentEndTime": "2024-04-30T04:00:00Z",
			"coverageStartTime": "2024-05-11T20:49:05Z",
			"coverageEndTime": "2024-06-14T14:16:22Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.102639536041,
			"generateTime": "2024-03-17T04:00:00Z",
			"dueTime": "2024-04-01T03:59:59.999Z",
			"installmentDuration": 0.99914874552
		},
		{
			"installmentStartTime": "2024-04-30T04:00:00Z",
			"installmentEndTime": "2024-05-31T04:00:00Z",
			"coverageStartTime": "2024-06-14T14:16:22Z",
			"coverageEndTime": "2024-07-17T07:43:38Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.073313644962,
			"generateTime": "2024-04-16T04:00:00Z",
			"dueTime": "2024-05-01T03:59:59.999Z",
			"installmentDuration": 1.00085125448
		},
		{
			"installmentStartTime": "2024-05-31T04:00:00Z",
			"installmentEndTime": "2024-06-30T04:00:00Z",
			"coverageStartTime": "2024-07-17T07:43:38Z",
			"coverageEndTime": "2024-08-20T16:27:16Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.108504330944,
			"generateTime": "2024-05-17T04:00:00Z",
			"dueTime": "2024-06-01T03:59:59.999Z",
			"installmentDuration": 0.99914874552
		},
		{
			"installmentStartTime": "2024-06-30T04:00:00Z",
			"installmentEndTime": "2024-07-31T04:00:00Z",
			"coverageStartTime": "2024-08-20T16:27:16Z",
			"coverageEndTime": "2024-09-22T18:38:11Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.090909261748,
			"generateTime": "2024-06-16T04:00:00Z",
			"dueTime": "2024-07-01T03:59:59.999Z",
			"installmentDuration": 1.00085125448
		},
		{
			"installmentStartTime": "2024-07-31T04:00:00Z",
			"installmentEndTime": "2024-08-31T04:00:00Z",
			"coverageStartTime": "2024-09-22T18:38:11Z",
			"coverageEndTime": "2024-10-25T12:05:27Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.064515992135,
			"generateTime": "2024-07-17T04:00:00Z",
			"dueTime": "2024-08-01T03:59:59.999Z",
			"installmentDuration": 1.0
		},
		{
			"installmentStartTime": "2024-08-31T04:00:00Z",
			"installmentEndTime": "2024-09-30T04:00:00Z",
			"coverageStartTime": "2024-10-25T12:05:27Z",
			"coverageEndTime": "2024-11-28T06:32:44Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.117302294902,
			"generateTime": "2024-08-17T04:00:00Z",
			"dueTime": "2024-09-01T03:59:59.999Z",
			"installmentDuration": 0.99914874552
		},
		{
			"installmentStartTime": "2024-09-30T04:00:00Z",
			"installmentEndTime": "2025-01-01T00:00:00Z",
			"coverageStartTime": "2024-11-28T06:32:44Z",
			"coverageEndTime": "2025-01-01T00:00:00Z",
			"normalizedWeight": 0.090909090909,
			"coverageDuration": 1.090908950617,
			"generateTime": "2024-09-16T04:00:00Z",
			"dueTime": "2024-10-01T03:59:59.999Z",
			"installmentDuration": 3.026388888889
		}
	],
	"reversalLattice": false
}
```

Pay close attention to the structure of each of the objects in the `frames` array. The code block below focuses on the first frame in the array.

```json
// The JSON has been annotated with comments
// for documentation purposes.

// If you intend to use this JSON for any reason,
// remove the comments.
"frames": [
    {
        // When the installment period begins.
        "installmentStartTime": "2024-01-01T00:00:00Z",

        // When the installment period ends.
        "installmentEndTime": "2024-01-31T05:00:00Z",

        // When the coverage period begins.
        "coverageStartTime": "2024-01-01T00:00:00Z",

        // When the coverage period ends.
        "coverageEndTime": "2024-03-06T06:32:44Z",

        // The weight of the frame in comparison to other frames.
        "normalizedWeight": 0.181818181818,

        // The duration of the coverage in the time unit used by the quote.
        // In this case, ~2.17 months
        "coverageDuration": 2.170088112306,

        // The date and time the billing system will generate an invoice.
        "generateTime": "2023-12-17T05:00:00Z",

        // What the due date of the invoice should be when generated.
        "dueTime": "2024-01-01T04:59:59.999Z",

        // The duration of the installment period.
        "installmentDuration": 0.974462365591
    },
```

Remember that a frame represents a subdivision of an insurance policy term. It contains two ways of describing the subdivision:

* The subdivision as an installment period
* The subdivision as a coverage period

The parameters prepended with *installment* determine the installment period. This is the period of time when the installment is issued to the customer. Additionally, the *generateTime* is when the invoice is generated, and the *dueTime* is when installment payment is due.

The parameters prepended with *coverage* determine the coverage period.

Notice in the code block above that the *installmentEndTime* and the *coverageEndTime* aren't the same. This is because this installment lattice was generated for a policy that's billed on a "monthly 10" installment schedule. That means the policy is billed in 10 installments for a 12-month period. This is where the concept of *normalizedWeight* comes into play.

Let's add the next frame from the lattice into our analysis:

```json
{
   // ...,
   "frames": [
       {
           "installmentStartTime": "2024-01-01T00:00:00Z",
           "installmentEndTime": "2024-01-31T05:00:00Z",
           "coverageStartTime": "2024-01-01T00:00:00Z",
           "coverageEndTime": "2024-03-06T06:32:44Z",
           "normalizedWeight": 0.181818181818,
           "coverageDuration": 2.170088112306,
           "generateTime": "2023-12-17T05:00:00Z",
           "dueTime": "2024-01-01T04:59:59.999Z",
           "installmentDuration": 0.974462365591
       },
       {
           "installmentStartTime": "2024-01-31T05:00:00Z",
           "installmentEndTime": "2024-02-29T05:00:00Z",
           "coverageStartTime": "2024-03-06T06:32:44Z",
           "coverageEndTime": "2024-04-09T03:21:49Z",
           "normalizedWeight": 0.090909090909,
           "coverageDuration": 1.102639125348,
           "generateTime": "2024-01-17T05:00:00Z",
           "dueTime": "2024-02-01T04:59:59.999Z",
           "installmentDuration": 0.998238783834
       },
       // ...
```

In the code block above, the first frame...

* Has an `installmentDuration` lasting approximately one month.
* Has a `coverageDuration` lasting approximately two months
* Has a `normalizedWeight` of .18 – approximately twice the other frames

Meanwhile, the second frame...

* Has an *installmentDuration* lasting approximately one month
* Has a *coverageDuration* lasting approximately one month
* Has a *normalizedWeight* of .09 – approximately half the first frame.

With an installment lattice created and populated with frames, the system then generates the installments that will be used for building invoices.

Stage 3: System generates installments [#stage-3-system-generates-installments]

Once the installment lattice has been created, the system automatically generates a set of installments based on the frames in the lattice.

The code block below shows examples of two installments generated from the example frames above:

```json
[
	{
		"locator": "01J5E66WFYVZ8X9Q98W7MRDMJ2",
		"installmentLatticeLocator": "01J5E66WEQV8GGKSH5RTQAYCTB",
		"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
		"currency": "USD",
		"timezone": "America/New_York",
		"installmentFrameIndex": 0,
		"quoteLocator": "01J5E660YXGBBNT26TQESCZHQF",
		"policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
		"transactionLocator": "01J5E660YXGBBNT26TQESCZHQF",
		"installmentStartTime": "2024-01-01T00:00:00Z",
		"installmentEndTime": "2024-01-31T05:00:00Z",
		"coverageStartTime": "2024-01-01T00:00:00Z",
		"coverageEndTime": "2024-03-06T06:32:44Z",
		"installmentDuration": 0.974462365591,
		"coverageDuration": 2.170088112306,
		"generateTime": "2023-12-17T05:00:00Z",
		"dueTime": "2024-01-01T04:59:59.999Z",
		"invoiceLocator": "01J5E66WTJCBYJ9P3KNPYA1KF6",
		"createdAt": "2024-08-16T18:11:46.092575Z",
		"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
		"updatedAt": "2024-08-16T18:11:46.092575Z",
		"updatedBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
		"installmentItems": [
			{
				"locator": "01J5E66WFY059MB4B5EXWT884Z",
				"installmentLocator": "01J5E66WFYVZ8X9Q98W7MRDMJ2",
				"chargeLocator": "01J5E66VBVQHEDJQSTNGSY77KS",
				"elementLocator": "01J5E66VBMACX1D1K00K0YYZNE",
				"elementStaticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
				"chargeType": "coverage_b_premium",
				"chargeCategory": "premium",
				"amount": 29.84,
				"invoiceItemLocator": "01J5E66WTJP601E481JJ6TJAHG",
				"createdAt": "2024-08-16T18:11:46.092575Z",
				"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
			},
			{
				"locator": "01J5E66WFYK2Q5PGGZC3FS5FRQ",
				"installmentLocator": "01J5E66WFYVZ8X9Q98W7MRDMJ2",
				"chargeLocator": "01J5E66VBVSW4RT1YEVGA9R8QC",
				"elementLocator": "01J5E66VBKYGJZT44JYPCNA3T6",
				"elementStaticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
				"chargeType": "coverage_a_premium",
				"chargeCategory": "premium",
				"amount": 149.19,
				"invoiceItemLocator": "01J5E66WTJ0XD6B9NVY2S8C9PG",
				"createdAt": "2024-08-16T18:11:46.092575Z",
				"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
			}
		]
	},
	{
		"locator": "01J5E66WFY09W2W2T74DZEFG8Q",
		"installmentLatticeLocator": "01J5E66WEQV8GGKSH5RTQAYCTB",
		"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
		"currency": "USD",
		"timezone": "America/New_York",
		"installmentFrameIndex": 1,
		"quoteLocator": "01J5E660YXGBBNT26TQESCZHQF",
		"policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
		"transactionLocator": "01J5E660YXGBBNT26TQESCZHQF",
		"installmentStartTime": "2024-01-31T05:00:00Z",
		"installmentEndTime": "2024-02-29T05:00:00Z",
		"coverageStartTime": "2024-03-06T06:32:44Z",
		"coverageEndTime": "2024-04-09T03:21:49Z",
		"installmentDuration": 0.998238783834,
		"coverageDuration": 1.102639125348,
		"generateTime": "2024-01-17T05:00:00Z",
		"dueTime": "2024-02-01T04:59:59.999Z",
		"invoiceLocator": "01J5E66X9B6YSHRQ9KMKG98ATB",
		"createdAt": "2024-08-16T18:11:46.092575Z",
		"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
		"updatedAt": "2024-08-16T18:11:46.092575Z",
		"updatedBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
		"installmentItems": [
			{
				"locator": "01J5E66WFYBB62CTHZBAKTS39H",
				"installmentLocator": "01J5E66WFY09W2W2T74DZEFG8Q",
				"chargeLocator": "01J5E66VBVSW4RT1YEVGA9R8QC",
				"elementLocator": "01J5E66VBKYGJZT44JYPCNA3T6",
				"elementStaticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
				"chargeType": "coverage_a_premium",
				"chargeCategory": "premium",
				"amount": 75.81,
				"invoiceItemLocator": "01J5E66X9B9YDCF6TGJ99S9854",
				"createdAt": "2024-08-16T18:11:46.092575Z",
				"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
			},
			{
				"locator": "01J5E66WFYJG0JW53ZDKGDTJW8",
				"installmentLocator": "01J5E66WFY09W2W2T74DZEFG8Q",
				"chargeLocator": "01J5E66VBVQHEDJQSTNGSY77KS",
				"elementLocator": "01J5E66VBMACX1D1K00K0YYZNE",
				"elementStaticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
				"chargeType": "coverage_b_premium",
				"chargeCategory": "premium",
				"amount": 15.16,
				"invoiceItemLocator": "01J5E66X9BRMH53HB5YDC09Z3N",
				"createdAt": "2024-08-16T18:11:46.092575Z",
				"createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
			}
		]
	}
	// ...,
]
```

The installments contain the charges for insurance coverage provided during the `coverageDuration` (the span of time between the `coverageStartTime` and the `coverageEndTime`).

After the system has generated the installments, the next step is to generate *invoices*.

Stage 4: System generates invoice(s) [#stage-4-system-generates-invoices]

The next stage of the billing life cycle is for the system to generate one or more invoices.

The billing system generates invoices on the `generateTime` (found on either the `frame` or the `installment`). The number of invoices created upon issuance of a quote depends on whether there is any retroactive coverage.

For example, if someone buys a policy for homeowner's insurance on March 1, and coverage also begins on March 1, then the system generates just one invoice. However, if the policy provides retroactive coverage to January 1, then the system generates the initial invoice, as well as invoices for previous frames.

The code block below shows an example of an invoice.

```json
[
	{
		"locator": "01J604B4VBYAFQ1NF04PRF50YD",
		"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
		"state": "open",
		"invoiceItems": [
			{
				"locator": "01J604B4VBFF29WKEFHFXP21BV",
				"chargeType": "coverage_a_premium",
				"chargeCategory": "premium",
				"amount": 150.0,
				"remainingAmount": 150.0,
				"invoiceLocator": "01J604B4VBYAFQ1NF04PRF50YD",
				"installmentItemLocators": ["01J604B421BYA71V49AK4AB713"],
				"timezone": "America/New_York",
				"quoteLocator": "01J6049YN0YK3EY28J090NEW5Y",
				"policyLocator": "01J6049YN0YK3EY28J090NEW5Y",
				"transactionLocator": "01J6049YN0YK3EY28J090NEW5Y",
				"elementStaticLocator": "01J6049Z4415XFRVGA4EJ72ZMM"
			},
			{
				"locator": "01J604B4VBRFX5W0VWJWY7TYVF",
				"chargeType": "coverage_b_premium",
				"chargeCategory": "premium",
				"amount": 30.0,
				"remainingAmount": 30.0,
				"invoiceLocator": "01J604B4VBYAFQ1NF04PRF50YD",
				"installmentItemLocators": ["01J604B421S190JDXJ0EK9GWAM"],
				"timezone": "America/New_York",
				"quoteLocator": "01J6049YN0YK3EY28J090NEW5Y",
				"policyLocator": "01J6049YN0YK3EY28J090NEW5Y",
				"transactionLocator": "01J6049YN0YK3EY28J090NEW5Y",
				"elementStaticLocator": "01J6049Z44CH4TFBBQPN22DHG8"
			}
		],
		"generatedTime": "2024-08-23T17:25:28.541Z",
		"dueTime": "2024-09-07T03:59:59.999Z",
		"currency": "USD",
		"startTime": "2024-08-23T00:00:00Z",
		"endTime": "2024-09-22T04:00:00Z",
		"timezone": "America/New_York",
		"totalAmount": 180.0,
		"totalRemainingAmount": 180.0
	}
]
```

Stage 5: Payment is created (via API) [#stage-5-payment-is-created-via-api]

When a customer sends a payment to their insurer, the next stage of the billing life cycle is to create a record of the payment.

To do that, we'll use the Create Payment endpoint (*/billing/:tenantLocator/payments*). The *targets* array in the request body contains the invoices to apply payment to, with the *containerLocator* being the unique identifier of the invoice.

```json
{
	"accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
	"amount": 180.0,
	"data": {
		"payerFirstName": "Example",
		"payerLastName": "User",
		"note": "payment"
	},
	"targets": [
		{
			"containerLocator": "01J604B4VBYAFQ1NF04PRF50YD",
			"containerType": "invoice"
		}
	],
	"useDefaultFinancialInstrument": true,
	"transactionNumber": "abc123",
	"type": "StandardPayment"
}
```

Note that creating the payment does not apply it to the invoice. To apply the payment, you must post the payment.

Stage 6: Payment is posted to invoice (via API) [#stage-6-payment-is-posted-to-invoice-via-api]

The final stage is to post the payment. Posting a payment applies it to an invoice.

Every invoice has two parameters tracking the amount on the invoice:

* *totalAmount* - The original amount of the invoice
* *totalRemainingAmount* - The amount left to pay on the invoice

To post a payment, we'll use the Post Payment endpoint (*/billing/:tenantLocator/payments/:paymentLocator/post*). This applies the payment to the *totalRemainingAmount* of the invoice.

When the *totalRemainingAmount* reaches 0, the invoice is marked as "settled".


# Set up and use the Config SDK for tenant configuration



import Image from 'next/image';

This article explains how to **set up and use the Config SDK to configure tenants** for the Socotra Insurance Suite.

Overview [#overview]

**Note**: The Config SDK is intended for a technical audience comfortable with programming.

For users who aren't comfortable with programming, we recommend using the Socotra web interface to make configuration changes. For more information, see: [Create a tenant configuration file](/getting-started/create-a-tenant-configuration-file).

What is the Config SDK? [#what-is-the-config-sdk]

The **Config SDK** is a set of tools that are developed and maintained by Socotra for its developer community.

The Config SDK accelerates tenant configuration development for Socotra Insurance Suite by allowing you to develop from a usable base configuration. It also gives you the opportunity to integrate with third-party tools.

The Config SDK includes industry-standard development tools that assist you in product creation, maintenance, and troubleshooting.

The Config SDK has two primary components:

* A template to organize your configuration's source code
* A collection of Gradle tasks (packaged as a Gradle plugin)

Advantages to using the Config SDK [#advantages-to-using-the-config-sdk]

There are several advantages to using the Config SDK and a compatible IDE, including:

* IDE-assisted code generation
* Inspection
* Proactive plugin and configuration validity checks

Using the Config SDK lets you interact more easily with the Socotra data model and static typing.

Advantage example: Streamlining data typing [#advantage-example-streamlining-data-typing]

Suppose you've defined a new insurance product with some underlying elements and data extensions in your JSON config. Now, you want to write a validation plugin.

The Java code for your plugin must refer to the types you've defined in your config, in addition to the core Socotra data types.

While it's possible to write all of that code *without* typing assistance, it's far easier to have an IDE that's able to reference compiled classes for all of your defined data types and the core Socotra data types.

Advantage example: Generating Java classes [#advantage-example-generating-java-classes]

You can also use the Config SDK, along with Socotra API developer endpoints, to expedite the configuration process. With Socotra's developer API endpoints, you can send a config to a tenant and receive compiled JAva classes corresponding to the types therein.

The SDK's Gradle plugin task set streamlines this activity, placing compiled classes from the target tenant or your in-progress config into a directory that your IDE can treat as a library.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image1.png" alt="Graphic representing the relationship between IDE and Tenant. The IDE sends definitions to the tenant, and the tenant returns a validated model." width={660} height={596} unoptimized />

Once you’ve set up the Config SDK, you can write tenant config JSON and plugin code in your IDE, run Config SDK tasks to validate your data model, leverage the IDE’s code completion and generation features, and deploy the config to the tenant.

What will I learn? [#what-will-i-learn]

By the end of this tutorial, you will know how to:

* Set up the Config SDK for rapid configuration development
* Use key Config SDK features to more easily create and maintain plugin code / tests.

What will I need? [#what-will-i-need]

You'll need the following to follow this tutorial:

* A set of credentials to log into your business account.
  * To learn more, see: [Log into Socotra](/getting-started/log-into-socotra).

* An Integrated Development Environment (IDE) (e.g. IntelliJ, Visual Studio Code, etc.)
  * You can use any IDE, but we recommend using [IntelliJ](https://www.jetbrains.com/idea/) (either Ultimate or the free Community Edition).

* JDK 17 (or higher)
  * Java 17 is the production execution environment for Socotra.
  * Plugin code should be written against the Java 17 standard.

* A tenant created in your business account.
  * The tenant allows the Config SDK ot use the tenant's development API endpoints for critical tasks. It also serves as the target for configuration deployment from the SDK.
  * For more information, see: [Create a tenant in Socotra](/getting-started/create-a-tenant)

Steps [#steps]

<span id="part-1---create-a-personal-access-token-" />

Part 1 - Create a Personal Access Token [#part-1---create-a-personal-access-token]

The first step is to **create a Personal Access Token** in Socotra. The Personal Access Token allows the Config SDK to use your business account's access to Socotra API endpoints.

1. Log into your Socotra business account. For more information, see: [Log into Socotra](/getting-started/log-into-socotra).
   1. For more information, see: [Log into Socotra](/getting-started/log-into-socotra).

2. Click the **profile icon** in the top-right corner of the screen.

3. Click **Personal Access Tokens**.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image2.png" alt="Screenshot of the Personal Access Token menu bar in Socotra" width={573} height={500} unoptimized />

4. On the Personal Access Tokens page, click **Create token**.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image3.png" alt="Screenshot of the Create token button in Socotra" width={1999} height={756} unoptimized />

5. In the **Create token** window, enter a token name of your choice.
   1. For the purposes of this guide, a token with “Full Access” permissions and tenant scope will suffice.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image4.png" alt="Screenshot of the Create token window in Socotra" width={1172} height={1018} unoptimized />

**Note**: If you've created a tenant but don't see any options under "Add tenants", navigate to the **Tenants** tab in your User Profile. Then, confirm that there is at least one tenant scope entry for your user. If the table is empty, create a "Full Access" entry.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image5.png" alt="Screenshot of a tenant in Socotra" width={1999} height={759} unoptimized />

Part 2 - Download and configure the Config SDK [#part-2---download-and-configure-the-config-sdk]

Once you've created a Personal Access Token, the next step is to:

* Download the Config SDK
* Open it
* Link it to a tenant

We'll cover how to do that in this section. Before we begin, however, let's review the components of the Config SDK:

* A template (to serve as the canonical repository for your tenant code)
* A Gradle plugin (to run critical tasks and minimize the number of steps required to get started)

Now that we've reviewed that information, let's continue to learn how to download and configure the Config SDK.

1. Download the latest Config SDK template from Socotra's GitHub repository: [https://github.com/socotra/config-sdk-template](https://github.com/socotra/config-sdk-template)
2. Unzip the Config SDK archive.
3. Open the Config SDK directory in your IDE.
4. You should see the following directory structure (which also reflects a typical Gradle project):

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image6.png" alt="Screenshot of the Config SDK directory structure" width={682} height={808} unoptimized />

The Config SDK plugin will be fetched from the repository’s Maven package index using your GitHub username and a GitHub personal access token (PAT) with the `read:packages` scope.

**Note**: If you encounter an error fetching the plugin, check to ensure that Gradle is using appropriate credentials when attempting to fetch the plugin package.

1. Open `build.gradle.kts` and inspect the `socotra-developer` section. To set up the Config SDK, you’ll need the following information:
   * The base Socotra API URL corresponding to your target tenant (e.g. for sandbox `https://api-ec-sandbox.socotra.com`)
   * The target tenant locator
   * Your personal access token string

**We recommend using environment variables to store these values**, especially for any source-controlled development. The example below depicts retrieving environment variables and falling back to hard-coded values.

```kotlin
`socotra-developer` {
    apiUrl.set(System.getenv("SOCOTRA_KERNEL_API_URL") ?: "http://hardcoded-fallback-tenant-url")
    tenantLocator.set(System.getenv("SOCOTRA_KERNEL_TENANT_LOCATOR") ?: "hardcoded-fallback-tenant-locator")
    personalAccessToken.set(System.getenv("SOCOTRA_KERNEL_ACCESS_TOKEN") ?: "hardcoded-fallback-access-token")
}
```

Alternatively, it's also possible (though *not advised*) to simply hard-code the values:

```kotlin
`socotra-developer` {
   apiUrl.set("https://api.socotra.com")
   tenantLocator.set("11d4ae42-971f-45cc-a287-40decd85eaa4")
   personalAccessToken.set("SOCP_01J2VBZSEAN80DEHSFPAF5Y1NY")
}
```

Part 3 - Fetch your tenant's config [#part-3---fetch-your-tenants-config]

After setting credentials in the `socotra-developer` section of `build.gradle.kts`, you’re ready to execute the Config SDK’s Gradle plugin tasks.

1. Open the Gradle toolbar to reveal the task set under `kernel-developer`.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image7.png" alt="Screenshot of tasks under kernel-developer in the Config SDK" width={718} height={802} unoptimized />

* `cleanupSocotraFolders`: Deletes temporary artifacts produced by the other Gradle plugin tasks.
* `deployConfigToTenant`: Deploys config in your socotra-config directory to the tenant.
* `downloadConfigAndPlugins`: Downloads the tenant’s config, along with plugin code and compiled class files for reference by plugins.
* `downloadReferenceDataModel`: Downloads compiled class files for reference by plugins.
* `refreshReferenceDataModel`: Places compiled classes corresponding to your local socotra-config definition for reference by plugin code.
* `validateConfig`: Validates the config in socotra-config.

1. Double-click `downloadConfigAndPlugins` (or run `./gradlew downloadConfigAndPlugins`) in your IDE's terminal.
   1. You should see a new `socotra-config` directory in your file tree.
   2. \`socotra-config contains a local copy of your tenant's configuration.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image8.png" alt="Screenshot of the socotra-config folder in the Config SDK" width={834} height={1314} unoptimized />

Part 4 - Update and validate the configuration [#part-4---update-and-validate-the-configuration]

1. Open `socotra-config/accounts/ConsumerAccount/config.json`.
2. Add an optional “Notes” field with an invalid type, such as “binary”, and save it:

```json
"data": {
    // ...,
    "Notes": {
        "displayName": "Notes",
        "type": "binary?"
    }
}
```

3. Run the `validateConfig` task. You should see an error like the following:

::

"Error in config bundle: accounts\[ConsumerAccount].data\[Notes]: type \[Binary] is not defined"

4. Since `validateConfig` has brought an error to our attention, let’s fix it by changing it to a valid type:

```json
"data": {
    // ...,
    "Notes": {
        "displayName": "Notes",
        "type": "string?"
    }
}
```

5. After saving, run `validateConfig` again.
   1. You should see the task complete successfully, indicating that the config is once again in a deployable state.

6. Deploy your updated config to the tenant by running `deployConfigToTenant`. You’ll need to confirm deployment by typing “DEPLOY” in the terminal prompt:

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image9.png" alt="Screenshot of tenant deployment prompt in terminal" width={962} height={386} unoptimized />

7. Then, ensure that your local Java classes are aligned with the latest state by running `downloadReferenceDatamodel`.

Part 5 - Write a plugin [#part-5---write-a-plugin]

Plugin development is where the Config SDK really shines since it allows you to write code with all the productivity-enhancing IDE facilities you would usually expect for Java projects.

In this step, we’ll write a simple validation plugin for the `ConsumerAccount`.

1. Click on the cycle icon in the Gradle sidebar (or run `./gradlew --refresh-dependencies`) to ensure that your IDE has the most recent references to Socotra data types and your own custom data types in your configuration.

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image10.png" alt="Screenshot of the refresh icon in an IDE" width={910} height={852} unoptimized />

2. Open `ValidationPluginImpl.java` in the `src/main/java/com/socotra/deployment/customer` directory to begin writing your plugin.
   1. All plugins must belong to the `com.socotra.deployment.customer` namespace.
   2. You’ll always work on plugin code in the `src/main directory`, moving code into the `socotra-config/plugins` directory when you are ready for deployment.

3. You will see a stub `validate` method entry for `ConsumerAccountRequest` in `ValidationPluginImpl`.

4. In the method, you can test out the auto-complete features by typing `consumerAccount.data().no` in a new line in the method, which will cause the IDE to suggest available data element – notice how the IDE suggest the new “Notes” field that we added:

<Image src="/images/use-the-config-sdk-for-tenant-configuration/image11.png" alt="Screenshot of an example of code completion in an IDE" width={1606} height={928} unoptimized />

5. After writing any additional logic for “Consumer Account” validation in this plugin, you can move the plugin code to `socotra-config/plugins` and deploy.
   1. Future releases of the Config SDK will streamline this process and able to be automated.

Part 6 - Write tests [#part-6---write-tests]

As is typical for Java projects, you can write tests in `src/test`, a parallel directory to `src/main`.

1. Make sure you have the following sample code deployed to your tenant:

```java
package com.socotra.deployment.customer;

import com.socotra.coremodel.ValidationItem;

public class ValidationPluginImpl implements ValidationPlugin {
 @Override
 public ValidationItem validate(ConsumerAccountRequest request) {
   ConsumerAccount consumerAccount = request.account();

   if (consumerAccount.data().lastName().equalsIgnoreCase("Batman")) {
     return ValidationItem.builder()
         .addError("A fictional person cannot be insured")
         .build();
   }

   return ValidationItem.builder().build();
 }
}
```

2. Create a new Java file `ValidationPluginTest` in `src/test/com/socotra/deployment/customer`.
3. Create a new method called `testConsumerValidationCatchesSpeciousClaimsToBeTheDarkKnight`. In this method, we’ll create a mock `ConsumerAccount` and run tests against it.

Since the Config SDK template is organized like a typical Gradle project and makes a distinction between the ready-for-deployment configuration and the namespaced Java code, you are free to introduce any other Java libraries you find useful in facilitating development.

For testing, we’ll introduce the Mockito framework, and build a test that uses it. Update your `build.gradle.kts` dependencies list to add `testImplementation("org.mockito:mockito-core:5.+")`, and then refresh your Gradle dependencies. Then copy the following code into the test file:

```java
package com.socotra.deployment.customer;

import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class ValidationPluginTest {
   @Test
   public void testConsumerValidationCatchesSpeciousClaimsToBeTheDarkKnight() {
       var consumerAccountRequest = mock(ValidationPlugin.ConsumerAccountRequest.class);
       var consumerAccount = mock(ConsumerAccount.class);
       var consumerAccountData = mock(ConsumerAccount.ConsumerAccountData.class);

       when(consumerAccountRequest.account()).thenReturn(consumerAccount);
       when(consumerAccount.data()).thenReturn(consumerAccountData);

       // Batman returns an error
       when(consumerAccountData.lastName()).thenReturn("Batman");
       var validationItem = (new ValidationPluginImpl().validate(consumerAccountRequest));
       assert(validationItem.errors().size() == 1);

       // Other names are acceptable
       when(consumerAccountData.lastName()).thenReturn("Smith");
       validationItem = (new ValidationPluginImpl().validate(consumerAccountRequest));
       assert(validationItem.errors().size() == 0);
   }
}
```

When you run unit tests from the Gradle sidebar or by executing `./gradlew test` in the terminal, you’ll see the tests pass. You can change the validation error sizes or the strings in the test to verify that the tests are actually running.

Once you’re satisfied with your plugin code, you can move it to `socotra-config` so that it can be deployed.


# Transactions and Billing



import Image from 'next/image';

import { visuals } from './transactions-and-billing.visuals';

In this tutorial, we will showcase key transactions and examine how they impact billing and accounting ledgers. We'll move from issuance, through a series of standard transactions, and conclude with an in-depth look at some out-of-sequence scenarios.

You can follow along by deploying the configuration and running the Postman collections in the [tutorial](https://github.com/socotra/ec-learning-paths/tree/main/transactions-and-billing) repo. The sample configuration is a simplified homeowner's product with just enough rating logic to illustrate the concepts.

Homeowner Product Structure [#homeowner-product-structure]

The diagram below shows an example product and a policy element tree: A product (HO3) with product-level tax and fee charges, with a single exposure (Dwelling) with two coverages. Each coverage has its own premium charge.

<ProductTree data={visuals.productStructure} />

Standard Transactions [#standard-transactions]

Issuance [#issuance]

First, let's have a look at issuance ("Issue" in the corresponding Postman collection). When the policy is issued, the rated charges are assigned to elements as follows:

<ProductTree data={visuals.issuanceCharges} />

These charges are sent to the billing system, which slices them across installments according to your billing settings. To keep things simple in this tutorial, we're reducing the number of installments and invoices by using these "up-front" <ApiLink name="InstallmentPlanRef" /> settings:

```json
{
	"displayName": "Upfront",
	"cadence": "fullPay",
	"anchorMode": "termStartDay",
	"generateLeadDays": 14,
	"dueLeadDays": 0,
	"maxInstallmentsPerTerm": 1000
}
```

The diagram below shows how charges flow into a billing stream installment and then to an account invoice. In this case, the issuance transaction results in a single installment, for which an invoice is generated. See the [Installment Lattices](/features/billing/installments-and-installment-lattices) and [Invoicing](/features/billing/invoicing) feature guides for more details on installment grouping and invoice generation.

<ChargesBillingAccount data={visuals.issuanceFlow} />

From transaction issuance to invoice generation, the following `faTransaction` ledger entries will be posted:

* Billing receipt of quote issuance (credit to policy ledger, debits to charge ledger)
* Created installments (credits to charge ledger, debits to installment item ledger)
* Generated invoice(s) (credits to installment item ledger, debits to invoice items)

<LedgerTAccounts data={visuals.issuanceLedger} />

In this guide, we're showing credits and debits rolled up to the ledger category level (policy, charge, etc.). Socotra's accounting is more granular than that, which you can see if you follow the sequence of ledger transactions in the "Issue" flow in the Transaction Lab.

1. The first transaction, "Get ledger account - policy" shows the credit to this particular policy's ledger (Click the image for full-size view):

   <Image src="/images/learning-paths/transactions-and-billing/transaction-issuance-1.png" alt="Transaction Lab — policy ledger after issue" width={1755} height={606} unoptimized />

2. When we get the financial transaction (A) that affected that ledger, we see not just one `charge` ledger but four: A `charge` ledger for each of the charges. In the Postman post-response script, we select one of those `charge` ledgers for the next ledger call.

   <Image src="/images/learning-paths/transactions-and-billing/transaction-issuance-2.png" alt="Transaction Lab — financial transaction A with four charge ledgers" width={1758} height={814} unoptimized />

3. "Get ledger account - charge" shows the debit from financial transaction A, along with a credit from another financial transaction (B), "Created installments".

   <Image src="/images/learning-paths/transactions-and-billing/transaction-issuance-3.png" alt="Transaction Lab — charge ledger with debit from A and credit from B" width={1754} height={783} unoptimized />

4. When fetching details for financial transaction B, we see its corresponding credits against four of the `charge` ledgers, and debits against four `installmentItem` ledgers.

   <Image src="/images/learning-paths/transactions-and-billing/transaction-issuance-4.png" alt="Transaction Lab — financial transaction B credits and installment item debits" width={1745} height={775} unoptimized />

5. Again, having chosen one ledger at random, this time for `installmentItem`, the "Get ledger account - installmentItem" shows (B) having debited and another financial transaction (C) "Generated invoice(s)", crediting the `installmentItem` ledger.

   <Image src="/images/learning-paths/transactions-and-billing/transaction-issuance-5.png" alt="Transaction Lab — installmentItem ledger with debit from B and credit from C" width={1771} height={774} unoptimized />

6. Fetching financial transaction (C) shows the credits against all the `installmentItem` ledgers and all of the relevant `invoiceItem` ledgers.

   <Image src="/images/learning-paths/transactions-and-billing/transaction-issuance-6.png" alt="Transaction Lab — financial transaction C credits to installment items and invoice items" width={1761} height={775} unoptimized />

This level of detail enables thorough credit tracking through the system, but for the purposes of this guide, we'll show simplified views in which T-accounts are consolidated by type.

Endorsement [#endorsement]

Now let's look at an endorsement transaction ("Issue and endorse" in the corresponding Postman collection).

In this series, we'll change the coverage limit for Coverage A from $350,000 to $550,000, effective a few months after policy start.

This time, when fetching the `policy` ledger, we'll see an additional financial transaction: "Billing Receipt of Transaction", including the transaction locator.

The charges assigned to elements on the endorsement segment will look like this:

<ProductTree data={visuals.endorsementCharges} />

Notice that coverage B has no assigned charges, since the rater returned no rate items for it.

The endorsement transaction will result in charges sent to the billing system:

<ChargesBillingAccount data={visuals.endorsementFlow} />

Since we're using up-front billing, the endorsement transaction will result in a single installment, for which an invoice is generated. The ledgers now look like this:

<LedgerTAccounts data={visuals.endorsementLedger} />

Cancellation [#cancellation]

Next, let's have a look at cancellations. Suppose that instead of having issued an endorsement, we had cancelled the policy. In a typical cancellation scenario, the flow of credit will be reversed, reflecting a return of the value that had been assigned to the period after the effective cancellation time.

For example, cancelling our sample policy about 1 month after the start date will result in an overall charge reduction of $452.36. Charges sent to the billing system will have negative values, and instead of a $452.36 credit to the policy ledger, we will see a $452.36 debit.

<LedgerTAccounts data={visuals.cancellationLedger} />

The Postman collection includes a "flat cancel" routine you can run to see similar results.

Renewal [#renewal]

In a renewal scenario ("Issue and renew" in the corresponding Postman collection), the flow of credit will be similar to that of an endorsement, but with the addition of a new term. Because of the invoicing settings in the sample configuration, we will not yet see a generated invoice for the transaction. Here's how the charges on the segment for the transaction will look:

<ProductTree data={visuals.renewalCharges} />

And the billing stream will look like this:

<ChargesBillingAccount data={visuals.renewalFlow} />

Notice that the invoice has **not** been generated yet, since the corresponding installment created by the transaction has a `generateTime` in the future, as a consequence of the billing settings that we highlighted earlier. In particular, setting the `anchorMode` to `termStartDay` and `generateLeadDays` to 14 means that the installment will have a `generateTime` set to 14 days before the renewal term. Accordingly, the ledgers after this sequence of issuance and renewal will not yet have a generated invoice transaction for the renewal:

<LedgerTAccounts data={visuals.renewalLedger} />

Reversals [#reversals]

Next, we'll take a look at reversals (Postman: "Issue, endorse, reverse"). Starting from the endorsement sequence we saw earlier, we'll reverse the endorsement transaction to see how the platform reacts.

Upon issuance of the reversal transaction, if you fetch the issued transactions for the policy ("Get issued transactions" list), you'll see just two transactions:

1. Issuance
2. Reversal

What happened to the endorsement transaction? You can still fetch information about it by using the <ApiLink name="fetchAffectedTransactions" /> API endpoint and supplying the reversal transaction locator. The issued transactions list is a streamlined view of the transactions that have directly brought the policy to its current state, including reversals.

If you fetch pricing for the reversal transaction, you won't see charges there: offset charges are created automatically by the billing service when it detects a transaction's transition from `issued` to `reversed`. As you might expect, the billing stream for the reversal transaction is the inverse of the endorsement:

<ChargesBillingAccount data={visuals.reversalFlow} />

In accounting, we'll have three financial transactions:

1. Billing Receipt of Quote Issuance
2. Billing Receipt of Transaction: \[locator: ..., category: change]
3. Created offset installments

With the resulting ledgers:

<LedgerTAccounts data={visuals.reversalLedger} />

Out-of-Sequence [#out-of-sequence]

We recommend taking a look at the [Out-of-Sequence Transactions](/features/policy-management/out-of-sequence-transactions) guide for some background before diving into the examples below. We'll illustrate the key points in that article and show how out-of-sequence transactions affect billing and accounting.

Case 1: Issue, Endorse, Cancel [#case-1-issue-endorse-cancel]

In the Postman collection "Issue, endorse, cancel", we will issue the same endorsement we saw in the earlier examples, and then issue a cancellation back to policy issuance ("Flat cancel"). This is out of sequence since the cancellation's effective time is earlier than the endorsement's.

You'll notice that when you create the cancellation transaction, the <ApiLink name="PolicyTransactionResponse" /> `transactionCategory` is `aggregate`, and that there are two transactions listed in the `aggregatedTransactions` array: The cancellation transaction and the reapplication of the original endorsement transaction. Notice that the `locator` of the endorsement transaction is now different from its original locator. The original locator remains constant as the `staticLocator` so that the same transaction is recognizable even if new instances of it are created for reapplication purposes like this.

After issuing the transaction and running "Get issued transactions list" for the policy, you'll see three transactions, ordered as though these transactions were issued in sequence:

1. Issuance
2. Cancellation
3. Endorsement

You can trace the order definitively by looking at the `baseTransactionLocator` for each transaction. The issuance has no `baseTransactionLocator` since it is the very first transaction. The cancellation's `baseTransactionLocator` points to issuance, while the endorsement points to the cancellation.

*Before issuing the cancellation transaction*

| Transaction       | Based on | Reapplication of | State  |
| ----------------- | -------- | ---------------- | ------ |
| Issuance (Tx1)    |          |                  | Issued |
| Endorsement (Tx2) | Tx1      |                  | Issued |

*After issuing the cancellation transaction*

| Transaction          | Based on | Reapplication of | State    |
| -------------------- | -------- | ---------------- | -------- |
| Issuance (Tx1)       |          |                  | Issued   |
| Endorsement (Tx2)    | Tx1      |                  | Reversed |
| Cancellation (Tx3.1) | Tx1      |                  | Issued   |
| Endorsement (Tx3.2)  | Tx3.1    | Tx2              | Issued   |

This pattern is what we mean when we say that out-of-sequence transactions will be handled as though all the transactions were issued in sequence, and that "all sequences of transactions through a given base transaction (which is called that transaction's [local stack)](/features/policy-management/out-of-sequence-transactions#high-level-approach) are in sequence". The issued transactions list tells this story, while also allowing you to reconstruct the complete history of the policy if needed. You can see that both the endorsement and cancellation transactions share the same `aggregateTransactionLocator` that you can use to view details about the aggregate, and that the endorsement has a `reapplicationOfLocator` pointing to its previous instance (in this case, the original version of the endorsement transaction).

Fetching the ledger for the policy, we'll have four financial transactions:

1. Billing Receipt of Quote Issuance
2. Billing Receipt of Transaction: \[locator: ..., category: change]
3. Created offset installments
4. Billing Receipt of Transaction: \[locator: ..., category: cancellation]

Since well-designed financial ledgers are fundamentally append-only, preserving a complete audit trail rather than rewriting history, the financial transactions follow our transaction issuance (not effective date) order:

1. Charges created by policy issuance
2. Charges created by the endorsement
3. Endorsement charges reversed due to the out-of-sequence cancellation
4. Inverse policy issuance charges created by the flat cancellation

The resulting ledgers look like this:

<LedgerTAccounts data={visuals.oosIssueEndorseCancelLedger} />

If you run "List invoices for policy", you'll see three invoices: One resulting from issuance, another for the endorsement, and a third for the endorsement reversal and cancellation. This is exactly what the ledger state reveals -- even though there were distinct "created installments" financial transactions for the endorsement reversal ("offset") and cancellation, both of those installments were grouped into a single invoice, for which there is one "generated invoices" financial transaction.

Case 2: Issue, Endorse, Endorse, Endorse [#case-2-issue-endorse-endorse-endorse]

As mentioned in the [Out-of-Sequence Transactions](/features/policy-management/out-of-sequence-transactions) guide, aggregate transactions do not nest. To illustrate handling for multiple out-of-sequence transactions, we'll issue a series of transactions out of order:

1. Issuance with coverage A limit of $350,000
2. Endorsement effective 3 months from policy start, changing the coverage A limit to $400,000
3. Endorsement effective 2 months from policy start, changing the coverage A limit to $450,000
4. Endorsement effective 1 month from policy start, changing the coverage A limit to $500,000

Recall that Socotra's default out-of-sequence functionality will display the resulting policy state as though the transactions had been issued in order of effective date. You can think of each transaction as retaining just the changes it had made relative to its original base transaction, so all endorsement 1 knows is "apply a change to set the coverage A limit to $400,000", all endorsement 2 knows is "apply a change to set the coverage A limit to $450,000", etc.

This is the resulting policy state after all these endorsements are issued:

1. Segment 1, policy start to month 1: Coverage A limit is $350,000 (policy issuance)
2. Segment 2, from month 1 to month 2: Coverage A limit is $500,000 (endorsement 3's change)
3. Segment 3, from month 2 to month 3: Coverage A limit is $450,000 (endorsement 2's change)
4. Segment 4, from month 3 onward: Coverage A limit is $400,000 (endorsement 1's change)

Navigation through the ledgers is left as an exercise for the reader.

In this guide, we have explored the interplay between fundamental transaction sequences and Socotra's billing system. While the product data model and invoicing configuration have been kept deliberately simple, these concepts apply uniformly across implementations, and we encourage you to use this sample as the basis for study and scenario analysis specific to your product.


# Deprecated API Items



{/* This file is auto-generated by scripts/generate-derived-docs.ts. Do not edit manually. */}

<Callout>
  The following entities, parameters, and properties have been marked as
  deprecated, which means you should avoid using them. They will be removed in
  future releases.
</Callout>

Endpoints [#endpoints]

POST /auth/identity [#post-authidentity]

* Endpoint: <ApiLink name="createIdentityProvider">POST /auth/identity</ApiLink>
* Status: deprecated

GET /auth/users/{locator}/accessmask [#get-authuserslocatoraccessmask]

* Endpoint: <ApiLink name="fetchUserMasks">GET /auth/users/\{locator}/accessmask</ApiLink>
* Status: deprecated

PATCH /auth/users/{locator}/accessmask [#patch-authuserslocatoraccessmask]

* Endpoint: <ApiLink name="addDataSecurityMask">PATCH /auth/users/\{locator}/accessmask</ApiLink>
* Status: deprecated

DELETE /auth/users/{locator}/accessmask/{tenantLocator} [#delete-authuserslocatoraccessmasktenantlocator]

* Endpoint: <ApiLink name="deleteUserMasks">DELETE /auth/users/\{locator}/accessmask/\{tenantLocator}</ApiLink>
* Status: deprecated

GET /auth/users/{locator}/accessmask/{tenantLocator} [#get-authuserslocatoraccessmasktenantlocator]

* Endpoint: <ApiLink name="fetchUserMasksForTenant">GET /auth/users/\{locator}/accessmask/\{tenantLocator}</ApiLink>
* Status: deprecated

GET /auth/users/{locator}/accessmask/{tenantLocator}/{type} [#get-authuserslocatoraccessmasktenantlocatortype]

* Endpoint: <ApiLink name="fetchUserMask">GET /auth/users/\{locator}/accessmask/\{tenantLocator}/\{type}</ApiLink>
* Status: deprecated

GET /billing/{tenantLocator}/jobs/installments/quotes/{locator}/list [#get-billingtenantlocatorjobsinstallmentsquoteslocatorlist]

* Endpoint: <ApiLink name="fetchInstallmentsJobDataForQuotes">GET /billing/\{tenantLocator}/jobs/installments/quotes/\{locator}/list</ApiLink>
* Status: deprecated

PATCH /payment-execution/{tenantLocator}/paymentProviders/{locator}/inactivate [#patch-payment-executiontenantlocatorpaymentproviderslocatorinactivate]

* Endpoint: <ApiLink name="inactivatePaymentProviderConfiguration">PATCH /payment-execution/\{tenantLocator}/paymentProviders/\{locator}/inactivate</ApiLink>
* Status: deprecated

GET /policy/{tenantLocator}/policies/snapshot/list [#get-policytenantlocatorpoliciessnapshotlist]

* Endpoint: <ApiLink name="fetchMultipleSnapshots">GET /policy/\{tenantLocator}/policies/snapshot/list</ApiLink>
* Status: deprecated

GET /policy/{tenantLocator}/transactions/{locator}/affectedTransactions/list [#get-policytenantlocatortransactionslocatoraffectedtransactionslist]

* Endpoint: <ApiLink name="fetchAffectedTransactionsForListEndpoint">GET /policy/\{tenantLocator}/transactions/\{locator}/affectedTransactions/list</ApiLink>
* Status: deprecated

GET /policy/{tenantLocator}/transactions/{locator}/segments/{segmentLocator} [#get-policytenantlocatortransactionslocatorsegmentssegmentlocator]

* Endpoint: <ApiLink name="fetchPolicySegmentEx">GET /policy/\{tenantLocator}/transactions/\{locator}/segments/\{segmentLocator}</ApiLink>
* Status: deprecated

GET /policy/{tenantLocator}/transactions/{locator}/segments/list [#get-policytenantlocatortransactionslocatorsegmentslist]

* Endpoint: <ApiLink name="fetchTransactionSegments">GET /policy/\{tenantLocator}/transactions/\{locator}/segments/list</ApiLink>
* Status: deprecated

Schemas [#schemas]

AccountResponse [#accountresponse]

* Schema: <ApiLink name="AccountResponse">AccountResponse</ApiLink>
* Deprecated properties: `state`

ChargeRef [#chargeref]

* Schema: <ApiLink name="ChargeRef">ChargeRef</ApiLink>
* Deprecated properties: `displayName`

ClaimsManagementRef [#claimsmanagementref]

* Schema: <ApiLink name="ClaimsManagementRef">ClaimsManagementRef</ApiLink>
* Deprecated properties: `claims`

ConfigurationRef [#configurationref]

* Schema: <ApiLink name="ConfigurationRef">ConfigurationRef</ApiLink>
* Deprecated properties: `billingPlans`, `claims`, `defaultAnchorMode`, `defaultBillingLevel`, `defaultBillingPlan`, `defaultDueLeadDays`, `defaultGenerateLeadDays`, `defaultLapseType`, `defaultRegion`

DeployedConfigMetadata [#deployedconfigmetadata]

* Schema: <ApiLink name="DeployedConfigMetadata">DeployedConfigMetadata</ApiLink>
* Deprecated properties: `pluginVersionStatus`

DeploymentMetadata [#deploymentmetadata]

* Schema: <ApiLink name="DeploymentMetadata">DeploymentMetadata</ApiLink>
* Deprecated properties: `version2`

DocumentJobInfo [#documentjobinfo]

* Schema: <ApiLink name="DocumentJobInfo">DocumentJobInfo</ApiLink>
* Deprecated properties: `state`

DocumentSummary [#documentsummary]

* Schema: <ApiLink name="DocumentSummary">DocumentSummary</ApiLink>
* Deprecated properties: `state`

ElementRef [#elementref]

* Schema: <ApiLink name="ElementRef">ElementRef</ApiLink>
* Deprecated properties: `pluralType`

ParamsChangeInstructionCreateRequest [#paramschangeinstructioncreaterequest]

* Schema: <ApiLink name="ParamsChangeInstructionCreateRequest">ParamsChangeInstructionCreateRequest</ApiLink>
* Deprecated properties: `billingModeChange`, `inheritSettings`

ParamsChangeInstructionResponse [#paramschangeinstructionresponse]

* Schema: <ApiLink name="ParamsChangeInstructionResponse">ParamsChangeInstructionResponse</ApiLink>
* Deprecated properties: `billingModeChange`, `inheritSettings`

PolicyMigrationRequest [#policymigrationrequest]

* Schema: <ApiLink name="PolicyMigrationRequest">PolicyMigrationRequest</ApiLink>
* Deprecated properties: `preferences`

ProductRef [#productref]

* Schema: <ApiLink name="ProductRef">ProductRef</ApiLink>
* Deprecated properties: `defaultBillingPlan`, `pluralType`

QuickQuotePriceResponse [#quickquotepriceresponse]

* Schema: <ApiLink name="QuickQuotePriceResponse">QuickQuotePriceResponse</ApiLink>
* Deprecated properties: `state`


# Open API Specification File



{/* Hand authored file */}

Open API is a specification that documents APIs like Socotra's in a machine-readable format. Use the schema file to import into your REST client or create integration code.

<Cards className="mt-4">
  <Card href="/openapi/socotra-openapi.json" target="_blank" rel="noopener noreferrer" title="View Raw File" description="Open the combined OpenAPI JSON in a new tab." />

  <Card href="/openapi/socotra-openapi.json" download="socotra-openapi.json" title="Download" description="Save as socotra-openapi.json." />
</Cards>


# Release Notes Archive



<Callout>
  This is a continuation of older release notes from the [main release notes page](/other-resources/release-notes).
</Callout>

September 11, 2024 [#september-11-2024]

* On <ApiLink name="PolicyTransactionResponse" />, the property `acceptedTime` has been added, the properties `aggregatedTransactions` and `changeInstructions` have now marked as optional.
* On <ApiLink name="QuoteResponse" />, the deprecated property `boundTime` has been removed in favor of the new property `acceptedTime`.
* On <ApiLink name="TransactionPriceResponse" />, the property `aggregatedTransactions` is now marked as optional.

September 4, 2024 [#september-4-2024]

Optional Properties [#optional-properties]

The following properties are now marked as optional:

* <ApiLink name="AccountResponse" />: `autoRenewalPlanName`,
  `delinquencyPlanName`, `excessCreditPlanName`, `shortfallTolerancePlanName`,
  `invoiceDocument`, `preferences`, `region`
* <ApiLink name="QuoteCreateRequest" />: `durationBasis`, `billingLevel`,
  `billingTrigger`, `region`
* <ApiLink name="ElementRef" />: `coverageTerms`, `data`
* <ApiLink name="ElementResponse" />: `coverageTerms`, `data`
* <ApiLink name="TenantResponse" />: `description`
* <ApiLink name="QuoteResponse" />: `static`
* <ApiLink name="AccountCreateRequest" />: `region`
* <ApiLink name="AccountUpdateReplaceDataRequest" />: `region`

Billing Triggers [#billing-triggers]

The "Billing Trigger" setting is being removed, and the following entities now have the property `billingTrigger` deprecated.

* <ApiLink name="PolicyResponse" />
* <ApiLink name="PolicyTransactionResponse" />
* <ApiLink name="QuoteCreateRequest" />
* <ApiLink name="QuoteUpdateRequest" />
* <ApiLink name="QuoteResponse" />
* <ApiLink name="BillingPlanRef" />

In addition:

* On <ApiLink name="ConfigurationRef" /> and <ApiLink name="ProductRef" />, `defaultBillingTrigger` is deprecated.
* The endpoint `updatePolicyBillingTrigger` is deprecated.
* The entity `BillingTriggerUpdateRequest` is deprecated.

Other Change [#other-change]

* On <ApiLink name="DocumentSummary" />, the property `documentInstanceState` has been added, and the equivalent property `state` has been deprecated.

August 28, 2024 [#august-28-2024]

* The following state properties have been changed, from `state`:
  * <ApiLink name="AccountResponse" />: `accountState`
  * <ApiLink name="QuickQuoteResponse" />: `quickQuoteState`
  * <ApiLink name="QuickQuotePriceResponse" />: `quickQuoteState`
  * <ApiLink name="InvoiceResponse" />: `invoiceState`
  * <ApiLink name="DocumentInstanceResponse" />: `documentInstanceState`

* The endpoints <ApiLink name="previewInvoicesForQuote" /> and <ApiLink name="previewInvoicesForTransaction" /> have had the property `includeZeroAmountInvoices` added, and `excludeOtherPolicies` has been removed.

* The endpoint <ApiLink name="fetchTransactionSegments" /> has been deprecated in favor of <ApiLink name="fetchTransactionSegment" /> because transactions can have a maximum of a single segment.

* The entity <ApiLink name="DocumentInstanceResponse" /> has new properties `category` and `external`.

August 21, 2024 [#august-21-2024]

Diaries [#diaries]

[Diaries](/api/aux-data/diary) are a new feature that enables a running narrative to be attached to individual entities. The following endpoints have been added:

* <ApiLink name="createDiary" />
* <ApiLink name="fetchLatestDiaryEntriesByReference" />
* <ApiLink name="fetchLatestDiaryEntryByLocator" />
* <ApiLink name="fetchAllDiaryEntriesByLocator" />
* <ApiLink name="updateDiary" />
* <ApiLink name="discardDiary" />

The following entities are used in the above endpoints:

* <ApiLink name="DiaryEntryCreateRequest" />
* <ApiLink name="DiaryEntryResponse" />
* <ApiLink name="DiaryEntryUpdateRequest" />

For now, diaries are enabled for quotes, policies, and policy transactions. Other entities will be enabled in the future.

See the [Diaries Feature Guide](/features/work-management/diaries) for more information.

Regions [#regions]

Regions are now supported. The new `region` property has been added to:

* <ApiLink name="AccountCreateRequest" />
* <ApiLink name="AccountResponse" />
* <ApiLink name="PolicyResponse" />
* <ApiLink name="PolicySnapshotResponse" />
* <ApiLink name="QuoteResponse" />
* <ApiLink name="AccountUpdateReplaceDataRequest" />

Also, `defaultRegion` has been added to <ApiLink name="ConfigurationRef" />.

Changes to Paged List Fetch Semantics [#changes-to-paged-list-fetch-semantics]

When fetching entities with any of the following endpoints, a new query parameter is available called `extended`. Setting `extended` to true means that the return object will not be a bare array of entities, but rather a List Contents object that includes an indicator that the list is complete. The following endpoints have been changed:

* <ApiLink name="fetchMultipleAccounts" /> returns
  <ApiLink name="AccountListResponse" />.
* <ApiLink name="fetchQuotesForAccount" />,
  <ApiLink name="fetchAllQuotesInGroup" />, and
  <ApiLink name="fetchQuotesInATenant" /> return
  <ApiLink name="QuoteListResponse" />.
* <ApiLink name="fetchMultipleQuickQuotes" /> and `fetchQuickQuotesForAGroup`
  return <ApiLink name="QuickQuoteListResponse" />.
* <ApiLink name="fetchPoliciesForAccount" /> returns
  <ApiLink name="PolicyListResponse" />.
* <ApiLink name="fetchPolicySnapshotsForAnAccount" /> returns
  <ApiLink name="PolicySnapshotListResponse" />.
* <ApiLink name="fetchIssuedTransactions" /> returns
  <ApiLink name="PolicyTransactionListResponse" />.
* <ApiLink name="fetchMultipleTerms" /> returns
  <ApiLink name="TermListResponse" />.

<Callout>
  Later, the `extended` property will be removed and the default behavior will be as if it were `true`.
</Callout>

Auto Transaction Rebasing [#auto-transaction-rebasing]

Before, transactions were always invalidated when a transaction on another branch became issued. Now, these transactions are automatically rebased on to the new, latest issued transaction. This behavior can be bypassed by setting the `autoRebase` query parameter to `false` when using the <ApiLink name="issueTransaction" /> endpoint.

Other Changes [#other-changes]

The following entity properties have been marked as optional:

* <ApiLink name="AuthTokenResponse" />: `permissions` and `tenants`
* <ApiLink name="ElementResponse" />: `coveragesTerms` and `elements`
* <ApiLink name="PolicyResponse" />: `branchHeadTransactionLocators`

July 31, 2024 [#july-31-2024]

Quick Quotes [#quick-quotes]

[Quick Quotes](/api/quick-quotes) are a lightweight mechanism for quotation without full underwriting support or document generation. Element extension data for quick quotes can be a subset of that used on a full quote.

The following endpoints have been added:

* <ApiLink name="fetchQuickQuote" />
* <ApiLink name="fetchMultipleQuickQuotes" />
* <ApiLink name="createQuickQuote" />
* <ApiLink name="validateQuickQuote" />
* <ApiLink name="updateQuickQuote" />
* <ApiLink name="createQuoteFromQuickQuote" />
* <ApiLink name="copyQuickQuote" />
* <ApiLink name="resetQuickQuote" />
* <ApiLink name="discardQuickQuote" />
* <ApiLink name="priceAQuickQuote" />
* <ApiLink name="fetchPricingForQuickQuote" />
* <ApiLink name="addElementsToQuickQuote" />
* <ApiLink name="deleteElementsFromQuickQuote" />
* <ApiLink name="fetchDependencyMapForQuickQuote" />
* <ApiLink name="evaluateConstraintsForQuickQuote" />
* `assignQuickQuoteToGroup`
* `fetchQuickQuotesForAGroup`

In support of the above endpoints, the following new entities are used:

* <ApiLink name="QuickQuoteResponse" />
* <ApiLink name="QuickQuotePriceResponse" />
* <ApiLink name="QuickQuoteCreateRequest" />
* <ApiLink name="QuickQuoteUpdateRequest" />

Account Level Billing [#account-level-billing]

Account level billing is activated by setting the `billingLevel` of the account, policy, or quote to `account`. If a policy or quote uses `inherit` for the `billingLevel`, it will defer to the account for the setting.

The following endpoints have been added to modify the billing level:

* <ApiLink name="updateBillingLevelForAnAccount" />
* <ApiLink name="updateBillingLevelForAPolicy" />
* <ApiLink name="updateBillingLevelForAQuote" />

Each of these endpoints takes a <ApiLink name="UpdateBillingLevelRequest" /> entity.

In addition, the following entities have added a `billingLevel` property:

* <ApiLink name="AccountResponse" />
* <ApiLink name="AccountCreateRequest" />
* <ApiLink name="AccountUpdateRequest" />
* <ApiLink name="AccountUpdateReplaceDataRequest" />
* <ApiLink name="PolicyResponse" />
* <ApiLink name="QuoteResponse" />
* <ApiLink name="QuoteCreateRequest" />
* <ApiLink name="QuoteUpdateRequest" />

Policy Transaction Branching [#policy-transaction-branching]

Policy transaction branching is done by setting the `baseLocator` of the transaction to a transaction other than the most recently created transaction. The following endpoints that create policy transactions now have a `baseLocator` parameter:

* <ApiLink name="createPolicyTransaction" />
* <ApiLink name="changePolicy" />
* <ApiLink name="renewPolicy" />
* <ApiLink name="reinstatePolicy" />
* <ApiLink name="cancelPolicy" />

And the following entity has a `baseLocator` property:

* <ApiLink name="PolicyTransactionReversalRequest" />

Configuration Changes [#configuration-changes]

* Added the property `delinquencyLevel`, and removed properties `baseLapseOn` and `lapseConflictHandling` from <ApiLink name="DelinquencyPlanRef" />
* Added the property `defaultBackdatedInstallmentsBilling` to <ApiLink name="ConfigurationRef" />.
* Deprecated the `billingPlans` and `defaultBillingPlan` properties on <ApiLink name="ConfigurationRef" />, and `defaultBillingPlan` on <ApiLink name="ProductRef" />. These will be removed in an upcoming release.

Other Changes [#other-changes-1]

* Endpoints which return a streaming response now show the type of object in the stream. So <ApiLink name="StreamingResponseBody" /> now is shown as `StreamingResponseBody<string>`, `StreamingResponseBody<ZipFile>`, etc.
* The <ApiLink name="InvoiceItemResponse" />'s `installmentItemsLocators` property has been renamed to `installmentItemLocators`, and has added properties `invoiceLocator` and `transactionLocator`. Also, the `reversalOfLocator` property has been removed.
* Added a `timezone` property to <ApiLink name="InvoiceResponse" />
* Added the `preemptingLapseTransactionLocator` property to <ApiLink name="DelinquencyReference" />.
* Added properties `realizedAt`, `reversalReason`, and `reversedAt` to <ApiLink name="CreditResponse" />.
* Added the boolean property `reversalLattice` to <ApiLink name="InstallmentLatticeResponse" />, and made the `settingsLocator` property optional.
* On <ApiLink name="QuoteResponse" /> and <ApiLink name="QuoteGroupAssignmentRequest" />, renamed the `quoteGroupLocator` property to `groupLocator`.
* On <ApiLink name="PolicyResponse" />, added the properties `latestTermLocator` and `billingLevel`.
* On <ApiLink name="AccountResponse" />, <ApiLink name="AccountCreateRequest" />, <ApiLink name="AccountUpdateRequest" />, and <ApiLink name="AccountUpdateReplaceDataRequest" />, added the properties `billingLevel` and `invoiceDocument`.
* Added the <ApiLink name="fetchInvoicesForAccount" /> endpoint.

July 24, 2024 [#july-24-2024]

*Internal changes only for this release.*

July 1, 2024 [#july-1-2024]

Stateless Operations [#stateless-operations]

Stateless operations are a way to determine the validatability, pricing, and underwriting for a quote or policy transaction without changing its state. The following endpoints now have a `stateless` parameter added to generate the results of the call without a state change:

* <ApiLink name="validateTransaction" />
* <ApiLink name="validateQuote" />

Other endpoints will also be updated with a `stateless` parameter in upcoming releases.

Invoices and Installments [#invoices-and-installments]

* On <ApiLink name="InvoiceItemResponse" />, added new properties `invoiceLocator` and `transactionLocator`, and changed the `installmentItemsLocators` property to be called `installmentItemLocators`, and made the `elementStaticLocator` property required.
* On <ApiLink name="InvoiceResponse" />, made the `startTime` and `endtime` properties required, and changed the type of the `currency` property to `string`.
* On <ApiLink name="InstallmentItem" />, removed the property `reversalOfLocator`.
* On <ApiLink name="InstallmentLatticeResponse" />, added the property `reversalLattice`, and made the `settingsLocator` property required.

Other Changes [#other-changes-2]

* Added a new <ApiLink name="fetchInvoiceDetails" /> endpoint for retrieving granular information about the contents of invoices. The response includes the new entities <ApiLink name="InvoiceDetailsResponse" />, `PolicyInvoiceSummary`, `InvoiceItemSummary`, and `InstallmentItemSummary`.
* Added the <ApiLink name="previewInvoicesForQuote" /> endpoint, with <ApiLink name="InvoicePreviewResponse" /> and <ApiLink name="InvoiceItemPreview" /> entities.
* Added the <ApiLink name="fetchPreferencesForATransaction" /> endpoint.
* Added the property `preemptingLapseTransactionLocator` to <ApiLink name="DelinquencyReference" />, which indicates that some other delinquency's lapse transaction has taken precedence over this delinquency's lapse transaction.
* Added the property `delinquencylevel` to <ApiLink name="DelinquencySettings" />
* On <ApiLink name="DelinquencyPlanRef" />, added the property `delinquencyLevel` and removed the properties `baseLapseOn` and `lapseConflictHandling`.
* On <ApiLink name="PolicyResponse" />, added the property `latestTermLocator` and made the `startTime` and `endTime` properties required.
* On <ApiLink name="QuoteGroupAssignmentRequest" />, changed the name of the `quoteGroupLocator` property to `groupLocator`.

June 10, 2024 [#june-10-2024]

Policies [#policies]

* Added the properties `startTime` and `endTime` to <ApiLink name="PolicyResponse" />. These indicate the start and end of the policy based on issued transactions only.

Invoices and Payments [#invoices-and-payments]

* Added endpoint <ApiLink name="fetchInvoicesTargetedByAPayment" />
* Added endpoint <ApiLink name="fetchInvoicesTargetedByACreditDistribution" />
* Added the property `unsettledTime` to <ApiLink name="InvoiceResponse" />, to indicate when a settled invoice became unsettled due to a payment reversal.
* The property `elementStaticLocator` has been added to the <ApiLink name="InvoiceItemResponse" /> entity.

Installments [#installments]

* The `reversalOfTransactionLocator`, `tenantLocator`, `invalidated`, `originationType`, and `refused` properties have been removed from <ApiLink name="Installment" />
* The `reversedByInstallmentItemLocator` and `tenantLocator` properties have been removed from <ApiLink name="InstallmentItem" />
* The `tenantLocator` property has been removed from <ApiLink name="InstallmentLatticeResponse" />

Stateless Operations [#stateless-operations-1]

These endpoints now have a boolean `stateless` property to allow calculation of pricing or underwriting data without changing the state of the associated quote or policy:

* <ApiLink name="priceQuote" />
* <ApiLink name="underwriteQuote" />
* <ApiLink name="priceTransaction" />
* <ApiLink name="underwriteTransaction" />

Underwriting [#underwriting]

The responses for quote and policy transaction underwriting have been changed:

* <ApiLink name="underwriteQuote" /> now returns a
  <ApiLink name="QuoteUnderwritingResponse" />
* <ApiLink name="underwriteTransaction" /> now returns a
  <ApiLink name="TransactionUnderwritingResponse" />

Accounting [#accounting]

* The "Cash" T-Accounts that represent cash inflows and outflows from the system are now managed at the customer account level.
* These are accessed through the new `fetchALedgerCashAccount` and <ApiLink name="fetchMultipleLedgerCashAccounts" /> endpoints.
* The tenant-wide cash account has been removed and so the `GET /billing/{tenantLocator}/accounting/ledgerAccounts/cash` endpoint has been removed as well.

Delinquency [#delinquency]

* The properties `graceEndAt` and `lapseTransactionEffectiveDate` properties have been added to <ApiLink name="DelinquencyResponse" />
* The `references` property is now optional on <ApiLink name="DelinquencyResponse" />
* On <ApiLink name="DelinquencyPlanRef" /> the properties `advanceLapseTo` and `lapseTransactionType` are now optional.
* The properties `executedAt` and `reversedAt` have been added to <ApiLink name="CreditDistributionResponse" /> and <ApiLink name="PaymentResponse" />

Aux Data [#aux-data]

* On <ApiLink name="AuxDataResponse" /> the property `auxDataSettingsName` is now optional.
* On <ApiLink name="AuxDataKey" /> the `auxDataSettingsName` property is now optional.

Data Extension Constraints [#data-extension-constraints]

These [Data Extension Constraints](/configuration/data-extensions/data-extension-constraints) endpoints are now accessed with POST API calls:

* <ApiLink name="evaluateConstraintsForQuote" />
* <ApiLink name="evaluateConstraintsForPolicyTransaction" />

Other Changes [#other-changes-3]

* Added the parameter `includeReversed` to the <ApiLink name="fetchPaymentsForAnInvoice" />, <ApiLink name="fetchCreditsForAnInvoice" />, and <ApiLink name="fetchCreditDistributionsForAnInvoice" /> endpoints to include those response items that have been previously reversed.
* Added the property `preferences` to <ApiLink name="TransactionSnapshotResponse" />.
* Added the property `searchSummary` to <ApiLink name="SearchResultResponse" />.
* Removed the property `transactionLocator` from <ApiLink name="SegmentResponse" />.
* Removed the properties `rootLocator` and `tenantLocator` from <ApiLink name="ElementResponse" />.
* Added the property `updatedAt` to <ApiLink name="TenantResponse" />.
* On <ApiLink name="ProductRef" /> the properties `defaultAutoRenewalPlan`, `defaultDelinquencyPlan`, and `defaultShortfallTolerancePlan` are now optional.

May 23, 2024 [#may-23-2024]

Users [#users]

* Added the <ApiLink name="fetchMultipleBasicUsers" /> endpoint to return streamlined user responses, which allows for a larger page size. This endpoint returns an array of <ApiLink name="BasicUserResponse" /> entities.

Excess Credits [#excess-credits]

The *Excess Credits* feature is forthcoming to handle excess customer credits held in a credit balance.

* Added the `excessCreditPlans` and `defaultExcessCreditPlan` properties to <ApiLink name="ConfigurationRef" />, and added with the <ApiLink name="ExcessCreditPlanRef" /> entity.
* Added the `excessCreditPlanName` property to <ApiLink name="AccountCreateRequest" />, <ApiLink name="AccountResponse" />, <ApiLink name="AccountUpdateRequest" />, and <ApiLink name="AccountUpdateReplaceDataRequest" />.

Open API Definitions [#open-api-definitions]

A top level property in the [Open API definition file](/openapi/socotra-openapi.json) was erroneously called `externalDocuments` rather than its proper name `externalDocs`. This has been corrected. (This property is not currently used as so contains an empty array.)

Other Changes [#other-changes-4]

* Clarified that the `references` property of <ApiLink name="DelinquencyResponse" /> will only be populated when fetching a single delinquency entity. Accordingly marked `references` as optional.
* Renamed the `listByTransactionLocator` endpoint to <ApiLink name="fetchInstallmentsForPolicyTransaction" />
* The <ApiLink name="DocumentInstanceResponse" /> entity has the following properties marked as optional: `policyLocator`, `referenceDocumentLocator`, `segmentLocator`, `termLocator`, `transactionLocator`, `name`, `staticName`, `documentFormat`, `processingErrors`, `readyAt`, and `createdBy`.

May 20, 2024 [#may-20-2024]

Event Stream Data Definition [#event-stream-data-definition]

* Information about the data contained within each payload is now on the [Event Definitions Page](/configuration/general-topics/event-definitions).

May 17, 2024 [#may-17-2024]

Deprecations [#deprecations]

The following entity properties are now `deprecated` and will be removed in a future release:

* <ApiLink name="ConfigurationRef" />: `defaultAnchorMode`,
  `defaultBillingLevel`, `defaultDueLeadDays`, `defaultLapseType`, `regions`
* <ApiLink name="ChargeRef" />: `displayName`
* <ApiLink name="ElementRef" />: `pluralType`
* <ApiLink name="ProductRef" />: `pluralType`
* <ApiLink name="ParamsChangeInstructionCreateRequest" />: `inheritSettings`,
  `billingModeChange`
* <ApiLink name="ParamsChangeInstructionResponse" />: `inheritSettings`,
  `billingModeChange`

Static Data [#static-data]

* Added the parameter `includeStaticData` to the <ApiLink name="fetchQuotesForAccount" /> and <ApiLink name="fetchPoliciesForAccount" /> endpoints.

Other Changes [#other-changes-5]

* On <ApiLink name="ParamsChangeInstructionCreateRequest" /> and <ApiLink name="ParamsChangeInstructionResponse" />:
  * The `triggerBillingChange` property has been added, to replace `billingModeChange`
  * The `preferences` and `newPolicyEndTime` properties are now optional.

May 15, 2024 [#may-15-2024]

Renewal Management and Auto-Renewal [#renewal-management-and-auto-renewal]

* There is a new [Renewal Management API](/api/policy-management/renewal-management) which supports the upcoming renewal management feature, including automatic renewal functionality.
* A feature guide for renewal management is forthcoming.

Resources [#resources]

* Added the `byStaticName` and `date` parameter to the <ApiLink name="fetchResource" /> and <ApiLink name="fetchSecret" /> endpoints for finer control of resource retrieval.
* The <ApiLink name="fetchDocumentTemplate" /> endpoint now returns a streaming response rather than a `string`.

Policy Snapshots [#policy-snapshots]

* Added the <ApiLink name="fetchPolicySnapshotsForAnAccount" /> endpoint.
* Added document information with the `documentSummary` property on <ApiLink name="SubsegmentSummary" />

Credits [#credits]

* Added the <ApiLink name="fetchCredits" /> endpoint to fetch credits across an entire tenant.

"List" Endpoints [#list-endpoints]

Changed the path to the following endpoints that return multiple endpoints for greater consistency:

* <ApiLink name="fetchPaymentsForAnInvoice" />: `/billing/{tenantLocator}
  /invoices/{locator}/payments/list`
* <ApiLink name="fetchCreditsForAnInvoice" />: `/billing/{tenantLocator}
  /invoices/{locator}/credits/list`
* <ApiLink name="fetchCreditDistributionsForAnInvoice" /> `/billing/ {tenantLocator}/invoices/{locator}/creditDistributions/list`

Other Changes [#other-changes-6]

* <ApiLink name="ElementResponse" /> now has an `originalEffectiveTime` property
  which shows when that element was first added to the policy.
* On the <ApiLink name="fetchTermSummaryByTermNumber" /> endpoint, changed the `number` parameter to `termNumber`.
* Added a `description` parameter to the <ApiLink name="createTenant" /> endpoint.
* On the <ApiLink name="fetchInvoicesForPolicy" /> and <ApiLink name="fetchInvoicesForQuote" /> endpoints, added the `includeZeroAmountInvoices` parameter for filtering. The default is `false`.
* On <ApiLink name="UnderwritingFlagResponse" />, removed properties `createdBy`, `createdTime`, `clearedBy` `clearedTime`.
* On <ApiLink name="TransactionPriceResponse" />, changed the `pricingItems` property to now be `charges`.
* On <ApiLink name="InstallmentSettings" />, the `maxInstallmentsPerTerm` property is now optional.

May 1, 2024 [#may-1-2024]

Charges [#charges]

On the week of May 6, 2024, there will be a change that requires configuration for which charges can be attached to elements. Each element definition must declare the charges that apply. <ApiLink name="ElementRef" /> and <ApiLink name="ProductRef" /> now have a `charges` property, which is an array of the charge types.

<Callout type="warn">
  All the applicable charges *must* be returned by the rating plugin, and *only* those charges can be applied; otherwise, the rating call will fail and the policy transaction or quote will fail to reach the `priced` state.
</Callout>

Documents [#documents]

* Documents may now be managed and retrieved by the entity they are attached to with these endpoints:
  * <ApiLink name="fetchDocumentsForSegment" />

  * <ApiLink name="fetchDocumentsForTransaction" />

  * <ApiLink name="fetchDocumentsForQuote" /> (previously named
    `fetchDocumentsByQuote`)

  * <ApiLink name="fetchDocumentsJobForSegment" />

  * <ApiLink name="fetchDocumentsJobForTransaction" />

  * <ApiLink name="fetchDocumentsJobForQuote" /> (previously named
    `fetchQuoteDocumentsJob`)

  * <ApiLink name="fetchMultipleDocumentsJobsForSegment" />

  * <ApiLink name="fetchMultipleDocumentsJobsForTransaction" />

  * <ApiLink name="fetchMultipleDocumentsJobsForQuote" /> (previously named
    `getQuoteDocumentsJobs`)

  * <ApiLink name="triggerTimedOutDocumentsJobForSegment" />

  * <ApiLink name="triggerTimedOutDocumentsJobForTransaction" />

  * <ApiLink name="triggerTimedOutDocumentsJobForQuote" /> (previously named
    `triggerTimedOutQuoteJob`)

* The <ApiLink name="DocumentInstanceResponse" /> property has a new `policyLocator` property.

* The `fetchSource` endpoint has been renamed to <ApiLink name="fetchSourceForDocument" />

<Callout>
  Policy documents are attatched to either policy segments or transactions, depending on [scope rules](/configuration/resources/documents#document_scope)
</Callout>

April 28, 2024 [#april-28-2024]

Feature Guides [#feature-guides]

New feature guides have been added for these topics:

* [InstallmentSettings](/features/billing/installment-settings)
* [Invoicing](/features/billing/invoicing)
* [Roles and Permissions](/features/security/roles-and-permissions)
* [Permissions List](/features/security/permissions-listing)

Along with these is an entirely set of configuration guides for plugins, including [rating](/configuration/plugins/rating), [validation](/configuration/plugins/validation), [underwriting](/configuration/plugins/underwriting), [precommit](/configuration/plugins/precommit), and [more](/configuration/plugins/overview).

Search [#search]

Search now has provisions for opting entity properties into or out of the search index:

* The property `defaultSearchable` has been added to <ApiLink name="ConfigurationRef" />, <ApiLink name="ProductRef" />, <ApiLink name="ElementRef" />, <ApiLink name="AccountRef" />, and <ApiLink name="DataTypeRef" />.
* The property `searchable` has been added to <ApiLink name="PropertyRef" />.

Password Policies [#password-policies]

Password policies now have editable settings:

* The <ApiLink name="fetchPasswordPolicy" /> endpoint can be used to find and update the individual settings. The payloads for these are <ApiLink name="PasswordPolicyResponse" /> and <ApiLink name="PasswordPolicyUpdateRequest" />, respectively.
* Settings include:
  * Minimum and maximum overall password length
  * The minimum number of uppercase letters, lowercase letters, numbers, and/or symbols
  * password expiration after a given number of days
  * Restrictions on reusing passwords before they are a certain number of days old

April 23, 2024 [#april-23-2024]

Payments [#payments]

* Added <ApiLink name="fetchPaymentsForAnInvoice" /> endpoint.

Write-Offs [#write-offs]

Added fetch endpoints:

* <ApiLink name="fetchWriteOff">
    Fetch a Write-Off
  </ApiLink>
* <ApiLink name="fetchMultipleWriteOffs">
    Fetch Multiple Write-Offs
  </ApiLink>

Other Changes [#other-changes-7]

* Added property `validationResult` to <ApiLink name="PolicyResponse" /> and <ApiLink name="AccountResponse" />
* Added configuration for `staticData` to <ApiLink name="ProductRef" />
* Deprecated endpoints <ApiLink name="fetchMultipleSnapshots" /> and <ApiLink name="fetchQuotesInATenant" />
* Added <ApiLink name="fetchPolicySegment" /> endpoint and deprecated <ApiLink name="fetchPolicySegmentEx" />

Feature Guides [#feature-guides-1]

Added new feature guides:

* [Accounting Example](/features/financials/accounting-example)
* [Accounting Primer](/features/financials/accounting-primer)
* [Credits From Policy Transactions](/features/billing/credits-from-policy-transactions)
* [Backloading Installments](/features/billing/backloading-installments)

April 17, 2024 [#april-17-2024]

Optional and Required Properties [#optional-and-required-properties]

The process for determining whether properties on entities were "required" (i.e. must be set on requests, or will always be set on responses) has moved from a manual to automated process. As a result of this some fields have changed from being indicated as required (with no suffix on their type name), or optional (with a `?` suffix on the type name.)

Write-Offs [#write-offs-1]

Added endpoints for write-off of invoices:

* <ApiLink name="writeOffInvoice" />
* <ApiLink name="reverseWriteOff" />

Term Summary [#term-summary]

Term Summaries are views of the term based on issued transactions, showing in-force coverage only. This essentially flattens the transactions that affect the term into a single series of segments, such that the segments cover the entire term without overlaps or time periods without segments. This is useful to understand the state of the term without constructing it from the transaction stack.

The <ApiLink name="fetchTermSummaryByTermLocator" /> and <ApiLink name="fetchTermSummaryByTermNumber" /> endpoints fetch the <ApiLink name="TermSummary">overall term summary</ApiLink>, and contains summary objects for <ApiLink name="SubsegmentSummary">segments</ApiLink> and <ApiLink name="ElementSummary">elements</ApiLink>. Extension data and charge information is included in the element summary.

Other Changes [#other-changes-8]

The `roundingMode` property on <ApiLink name="PropertyRef" /> has changed its enumeration values to use camel case: `ceiling`, `down`, `floor`, `halfDown`, `halfEven`, `halfUp-up`

April 12, 2024 [#april-12-2024]

Search [#search-1]

* Added the <ApiLink name="fetchAdditionalSearchResultsByToken" /> endpoint
* Added `offset` and `count` parameters to <ApiLink name="fetchSearchResults" /> endpoint
* Added properties `offset`, `count`, and `searchToken` to <ApiLink name="SearchServiceResponse" />, and removed `page`
* Renamed the `locator` property on <ApiLink name="SearchResultResponse" /> to `searchEntityLocator`

Invoicing [#invoicing]

* Added property `installmentsItemsLocator` to <ApiLink name="InvoiceResponse" />, and removed `invoiceLocator` and `installmentItems`
* Added properties `originationType`, and `refused`, and `invalidated` to <ApiLink name="Installment" />
* Added property `autoRenewalLocator` to <ApiLink name="TermResponse" />

Other Changes [#other-changes-9]

* Added a [Reinstatements Feature Guide](/features/policy-management/reinstatements)
* Added the <ApiLink name="fetchMultipleSnapshots" /> endpoint
* Renamed the `TransactionSnapshot` entity to <ApiLink name="TransactionSnapshotResponse" />
* Added parameter `accountLocator` to <ApiLink name="fetchMultiplePayments" />, <ApiLink name="fetchMultipleDisbursements" /> and <ApiLink name="fetchMultipleCreditDistributions" /> endpoints
* Added property `preferences` to <ApiLink name="AccountCreateRequest" />, <ApiLink name="AccountUpdateRequest" />, <ApiLink name="AccountUpdateReplaceDataRequest" />, and <ApiLink name="AccountResponse" />

April 8, 2024 [#april-8-2024]

Extension Data Constraints [#extension-data-constraints]

* Added a new [Extension Data Constraints Feature Guide](/configuration/data-extensions/data-extension-constraints) feature guide for understanding configuration and use of the constraints feature in building user interfaces.

Shortfall Management [#shortfall-management]

Added new endpoints supporting the ability to write-off shortfalls in payments below a configured threshold:

* <ApiLink name="fetchShortfallCredit" />
* <ApiLink name="fetchMultipleShortfallCredits" />

These endpoints return <ApiLink name="ShortfallCreditResponse" /> object(s).

Also, added the property `shortfallCreditLocators` to <ApiLink name="CreditDistributionResponse" />

Quote Groups [#quote-groups]

Added endpoints supporting Quote Groups:

* <ApiLink name="assignQuoteGroup" />
* <ApiLink name="fetchAllQuotesInGroup" />

Other changes:

* Added the ability to assign a quote to a different group when copying, using a <ApiLink name="QuoteGroupAssignmentRequest" />
* Added the property `quoteGroupLocator` to <ApiLink name="QuoteResponse" />

Term Fetch [#term-fetch]

Added an endpoint to fetch all terms in a policy:

* <ApiLink name="fetchMultipleTerms" />

Installments [#installments-1]

* Added the `basedOnLocator` and `effectiveTime` properties to <ApiLink name="InstallmentLatticeResponse" />
* Added the property `normalizedWeight` to <ApiLink name="InstallmentLatticeFrame" />

Policy Transaction Changes [#policy-transaction-changes]

Added an endpoint to update the change instructions for a policy transaction based on explicit updates to the new policy segment. This endpoint returns a standard <ApiLink name="PolicyTransactionResponse" /> with the `changeInstructions` property updated:

* <ApiLink name="fetchPolicyTransactionWithUpdatedChanges" />

Other Changes [#other-changes-10]

* Removed the property `transactionLocator` from <ApiLink name="EventResponse" />
* Changed the type of the `outcome` property of <ApiLink name="GraceJobData" /> from an enumeration to a string
* Added the properties `reversalReason` and `shortfallCreditLocators` to <ApiLink name="CreditDistributionResponse" />

April 1, 2024 [#april-1-2024]

Search [#search-2]

See the new [Search Feature Guide](/features/search) for details about Search including about how to use the [Search API](/api/search).

Events [#events]

* Added endpoints <ApiLink name="fetchEvent" /> and <ApiLink name="fetchEventsForARequest" />
* Renamed endpoint `listEvents` to <ApiLink name="fetchMultipleEvents" />
* Added the optional field `transactionLocator` to <ApiLink name="EventResponse" />

Elements [#elements]

On <ApiLink name="ElementCreateRequest" />:

* Removed the properties `locator`, `tenantLocator`, and `rootLocator`.
* Marked the properties `staticLocator` and `elements` as optional.

On <ApiLink name="ElementResponse" />:

* Marked the properties `staticLocator`, `rootLocator`, and `elements` as optional.

Payments, Credit Distributions, and Disbursements [#payments-credit-distributions-and-disbursements]

* Added the <ApiLink name="reversePayment" /> endpoint.
* Added the `reversalReason` and `shortfallCreditLocators` properties to <ApiLink name="PaymentResponse" />
* Added the property `useDefaultFinancialInstrument` to <ApiLink name="PaymentUpdateRequest" /> and <ApiLink name="DisbursementUpdateRequest" />
* Added a request body of <ApiLink name="CreditDistributionReverseRequest" /> to <ApiLink name="reverseCreditDistribution" />

Installments [#installments-2]

* Added properties `reversalOfInstallmentLocator` and `reversedByInstallmentLocator` to <ApiLink name="Installment" />
* Added properties `reversalOfInstallmentItemLocator` and `reversedByInstallmentItemLocator` to <ApiLink name="InstallmentItem" />

Plans and Prferences [#plans-and-prferences]

* Added the property `shortfallTolerancePlanName` to <ApiLink name="AccountCreateRequest" />, <ApiLink name="AccountUpdateRequest" />, <ApiLink name="AccountUpdateReplaceDataRequest" />, and <ApiLink name="AccountResponse" />

Constraints [#constraints]

* Changed the <ApiLink name="ConditionValue" /> entity to use `staticLocator` instead of `elementLocator` for referencing elements.

Resource Groups [#resource-groups]

* Marked the `selectionStartTime` property as `Required`.

Accounting [#accounting-1]

* On <ApiLink name="AccountLineItem" /> Changed the properties `refLocator`, `refType` and `type` to `referenceLocator`, `refType`, and `accountingType`, respectively.
* On <ApiLink name="AccountingTransactionResponse" />, changed the properties `transactionLocator`, `transactionNote`, and `transactionTime` to `faTransactionLocator`, `faTransactionNote`, and `faTransactionTime`, respectively.
* On <ApiLink name="LedgerAccountLineItem" />, changed the properties `txnLocator`, `txnNote`, `entryType`, and `txnTime` to `faTransactionLocator`, `faTransactionNote`, `accountingType`, and `faTransactionTime` respectively.

March 27, 2024 [#march-27-2024]

Policy Service [#policy-service]

* Updated the operation of policy transactions (policy change, renewal, etc.) to allow manipulation of the actual segment to be created in addition to operating only on the change instructions that describe how to do the transformation. This will better support our upcoming *Constraint Tables* feature, and will allow for more flexibility when working with transactions. Details on usage will follow.

* Added endpoints:
  * <ApiLink name="initializeTransaction" />
  * <ApiLink name="addElementsToPolicyWithTransaction" />
  * <ApiLink name="updateElementsInPolicyWithTransaction" />
  * <ApiLink name="removeElementsFromPolicyWithTransaction" />
  * <ApiLink name="evaluateConstraintsForPolicyTransaction" />
  * <ApiLink name="fetchDependencyMapForPolicyTransaction" />

* Removed `productName` from <ApiLink name="QuoteUpdateRequest" />

* Added `initialized` to the allowed values for the <ApiLink name="PolicyTransactionResponse" /> `state` property.

* On <ApiLink name="ElementResponse" />, marked `staticLocator` and `rootLocator` as optional.

Billing Service [#billing-service]

* Added endpoints:
  * <ApiLink name="fetchMultipleCreditDistributions" />
  * `fetchLedgerCashAccount`

* On <ApiLink name="InstallmentSettings" /> and <ApiLink name="InstallmentPreferences" />, changed the property `explicitAnchorDate` to `anchorTime`

* On <ApiLink name="InstallmentPreferences" />, added properties `anchorTime`, `dayOfWeek`, and `weekOfMonth`

* On <ApiLink name="AccountingTransactionResponse" />, changed the properties `transactionLocator`, `transactionNote`, and `transactionTime` to `faTransactionLocator`, `faTransactionNote`, and `faTransactionTime`, respectively.

* On <ApiLink name="Installment" />, added the properties `reversalOfInstallmentLocator` and `reversedByTransactionLocator`

Platform [#platform]

* Changed <ApiLink name="fetchSearchResults" /> to use method `POST` instead of `GET`
* On <ApiLink name="ResourceGroupCreateRequest" />, the `selectionStartTime` property is now properly marked as `required`
* On <ApiLink name="ProductRef" />, added the property `defaultShortfallTolerancePlan`
* Changed the name of the `ResourceGroup` entity to <ApiLink name="ResourceGroupResponse" />

Configuration [#configuration]

* Added the entities `1PropertyTypeInfo`, <ApiLink name="ReversalTypeRef" />, and <ApiLink name="ShortfallTolerancePlanRef" />
* On <ApiLink name="ConfigurationRef" />, added the properties `defaultShortfallTolerancePlan`, `shortfallTolerancePlans` and `reversalTypes`

<Callout>
  The <ApiLink name="fetchDependencyMapForPolicyTransaction" /> endpoint is part of *Constraint Tables*, an upcoming feature. Details will be provided within the next few days.
</Callout>

March 20, 2024 [#march-20-2024]

New Endpoints [#new-endpoints]

* <ApiLink name="fetchCreditDistribution" />

Path Change [#path-change]

The <ApiLink name="fetchAllHoldsForAnAccount" /> endpoint has changed its path:

*from* `/billing/{tenantLocator}/holds/{accountLocator}/list`

*to* `/billing/{tenantLocator}/holds/accounts/{accountLocator}/list`

Constraint Tables [#constraint-tables]

<Callout>
  *Constraint Tables* are part of an upcoming feature to facilitate UI development and validation. This feature is not yet ready for use.
</Callout>

These endpoints have been added:

* <ApiLink name="fetchDependencyMapForQuote" />
* <ApiLink name="fetchConstraints" /> with
  <ApiLink name="ConstraintDependency" /> response
* <ApiLink name="createConstraintTable" />
* <ApiLink name="replaceConstraintTable" />
* <ApiLink name="zipConstraintTable" />

Other Changes [#other-changes-11]

* Added the properties `dayOfWeek`, `explicitAnchorDate`, and `weekOfMonth` to <ApiLink name="InstallmentSettings" />
* Added the property `constraintTables` to <ApiLink name="ConfigurationRef" />
* Added the properties `constraint` and `propertyScopes` to <ApiLink name="PropertyRef" />
* Added the property `graceStartedAt` to <ApiLink name="DelinquencyResponse" />, and renamed `state` to `delinquencyState`
* Renamed the property `state` on <ApiLink name="DisbursementResponse" /> to `disbursementState`
* Renamed the property `state` on <ApiLink name="PaymentResponse" /> to `paymentState`
* Removed the `POST /billing/{tenantLocator}/invoices/{locator}/delinquencies` endpoint

March 13, 2024 [#march-13-2024]

Credit Distributions [#credit-distributions]

Added these endpoints:

* <ApiLink name="createCreditDistribution" />
* <ApiLink name="updateCreditDistribution" />
* <ApiLink name="createOrReplaceCreditDistribution" />
* <ApiLink name="validateCreditDistribution" />
* <ApiLink name="executeCreditDistribution" />
* <ApiLink name="reverseCreditDistribution" />
* <ApiLink name="resetCreditDistribution" />
* <ApiLink name="discardCreditDistribution" />

Added these entities:

* <ApiLink name="CreditDistributionResponse" />
* <ApiLink name="CreditDistributionCreateRequest" />
* <ApiLink name="CreditDistributionUpdateRequest" />
* <ApiLink name="CreditDistributionPutRequest" />
* <ApiLink name="CreditDistributionReverseRequest" />

Billing Holds [#billing-holds]

Added these endpoints:

* <ApiLink name="fetchHold" />
* <ApiLink name="updateHold" />
* <ApiLink name="validateHold" />
* <ApiLink name="releaseHold" />
* <ApiLink name="activateHold" />
* <ApiLink name="resetHold" />

Added these entities:

* <ApiLink name="HoldCreateRequest" />
* <ApiLink name="HoldResponse" />
* <ApiLink name="HoldUpdateRequest" />

Billing Triggers [#billing-triggers-1]

Billing triggers (either on `accepted` or on `issued`) are moving from billing plans to quotes and policies themselves.

* Added the `updatePolicyBillingTrigger` endpoint which uses a `BillingTriggerUpdateRequest`.
* Added the `billingTrigger` property to <ApiLink name="QuoteCreateRequest" />, <ApiLink name="QuoteUpdateRequest" />, <ApiLink name="QuoteResponse" />, <ApiLink name="PolicyResponse" />, and <ApiLink name="PolicyTransactionResponse" />.
* Removed `billingTrigger` from `BillingSettings` and `BillingPreferences`.

Search [#search-3]

* Changed the `searchType` on <ApiLink name="SearchRequest" /> to be called `searchEntityType`.
* Removed the `fetchSearchConfiguration` endpoint along with the `EntitySearchConfiguration`, `SearchConfiguration`, and `SearchSummaryResponse` endpoints.
* Removed the `searchSummary` response from <ApiLink name="SearchResultResponse" />

Other Changes [#other-changes-12]

* Changed the type of the `removeSources` and `removeTargets` properties of <ApiLink name="PaymentUpdateRequest" /> and <ApiLink name="DisbursementUpdateRequest" /> from locator\[] to <ApiLink name="CreditItem">CreditItem\[]</ApiLink>.
* Removed the properties `webhookLocator` and `tenantLocator` from <ApiLink name="DivertedEventResponse" />.

March 6, 2024 [#march-6-2024]

Static Data [#static-data-1]

Added a feature to associate "static" data with Quotes and Policies. This is data that lives outside the existing extension data for these entities, and is managed outside of policy transactions. It currently doesn't require configuration but is otherwise structured like normal extension data.

New endpoints:

* <ApiLink name="addStaticDataForQuote" />
* <ApiLink name="updateStaticDataForQuote" />
* <ApiLink name="replaceAllStaticDataForQuote" />
* <ApiLink name="addStaticDataForPolicy" />
* <ApiLink name="updateStaticDataForPolicy" />
* <ApiLink name="replaceAllStaticDataForPolicy" />

Also added the property `static` to <ApiLink name="QuoteResponse" />, <ApiLink name="QuoteCreateRequest" />, <ApiLink name="PolicyResponse" />, and <ApiLink name="PolicySnapshotResponse" />

<Callout>
  The `POST` versions of the above endpoints differ from `PUT` in that they will fail if there is already static data on the entity at the time of the request.
</Callout>

Search [#search-4]

Integrated the new Socotra Insurance Suite search service.

New endpoints:

* <ApiLink name="fetchSearchResults" />
* `fetchSearchConfiguration`

New entities:

* <ApiLink name="SearchRequest" />
* <ApiLink name="SearchTermRequest" />
* <ApiLink name="SearchServiceResponse" />
* <ApiLink name="SearchResultResponse" />
* `SearchSummaryResponse`
* `SearchConfiguration`
* `EntitySearchConfiguration`

Webhook Failure Handling [#webhook-failure-handling]

Functionality to handle failed webhook events has been added.

New endpoints:

* <ApiLink name="fetchDivertedEvent" />
* <ApiLink name="fetchMultipleDivertedEvents" />
* <ApiLink name="resendDivertedEvent" />
* <ApiLink name="deleteDivertedEvent" />
* <ApiLink name="unsuspendWebhook" />

New entities:

* <ApiLink name="DivertedEventResponse" />
* <ApiLink name="RetryStrategyCreateRequest" />
* <ApiLink name="RetryStrategyResponse" />
* <ApiLink name="RetryStrategyUpdateRequest" />
* <ApiLink name="FailureHandlingCreateRequest" />
* <ApiLink name="FailureHandlingUpdateRequest" />
* <ApiLink name="FailureHandlingResponse" />

Other changes:

* Added the `failureHandling` property to <ApiLink name="CreateWebhookRequest" /> and <ApiLink name="WebhookResponse" />
* Added `removeFailureHandling` to <ApiLink name="UpdateWebhookRequest" />

Passwords [#passwords]

* Added endpoint <ApiLink name="resetUserPassword" />
* Added the optional `temporaryPassword` property to <ApiLink name="UserCreateRequest" />, <ApiLink name="UserUpdateRequest" />, and <ApiLink name="UserResponse" />

Other Changes [#other-changes-13]

* Added endpoint <ApiLink name="fetchAffectedTransactions" /> to find which transactions have been affected by a transaction, such as those that were reversed and/or reapplied as a result of an out-of-sequence transaction. Also added <ApiLink name="AffectedTransaction" /> for the response.
* Added the `transactionLocator` property to <ApiLink name="DelinquencyReference" />
* Changed the name of the `completedTime` property of <ApiLink name="InstallmentJobData" /> to `completedAt`
* Added the properties `referenceDocumentLocator`, `segmentLocator`, and `termLocator` to <ApiLink name="DocumentInstanceResponse" />

February 28, 2024 [#february-28-2024]

Disbursements [#disbursements]

Added a new Disbursements controller, including endpoints:

* <ApiLink name="createDisbursement" />

* <ApiLink name="updateDisbursement" />

* <ApiLink name="updateDisbursementReplaceData" />

* <ApiLink name="fetchDisbursement" />

* <ApiLink name="fetchMultipleDisbursements" />

* <ApiLink name="validateDisbursement" />

* <ApiLink name="approveDisbursement" />

* <ApiLink name="executeDisbursement" />

* <ApiLink name="rejectDisbursement" />

* <ApiLink name="resetDisbursement" />

* <ApiLink name="reverseDisbursement" />

* <ApiLink name="discardDisbursement" />

Added entities:

* <ApiLink name="DisbursementUpdateReplaceDataRequest" />
* <ApiLink name="DisbursementResponse" />
* <ApiLink name="DisbursementUpdateReplaceDataRequest" />

Added configuration for:

* <ApiLink name="DisbursementRef">
    Disbursements
  </ApiLink>
* <ApiLink name="PaymentRef">
    Payments
  </ApiLink>

Other Changes [#other-changes-14]

* Added a new endpoint to copy a quote: <ApiLink name="copyQuote" />
* Added a new endpoint to fetch the "local stack" of issued transactions for a policy: <ApiLink name="fetchIssuedTransactions" />
* The <ApiLink name="PaymentCreateRequest" /> and <ApiLink name="PaymentUpdateRequest" /> entities have added properties `type`, `currency`, `addTargets`, and `removeTargets`, but has removed `targetLocator`, `name`, and `targetType`.
* Added the <ApiLink name="fetchPolicySnapshot" /> endpoint along with <ApiLink name="PolicySnapshotResponse" /> and <ApiLink name="TransactionSnapshotResponse" /> entities.
* Added the `issuedTime` peroperty to <ApiLink name="PolicyTransactionResponse" />
* Added the `tag` property to <ApiLink name="PropertyRef">extension data properties</ApiLink> in configuration.
* Changed the `CreditResponse` entity to <ApiLink name="PaymentResponse" />.
* Removed the Parameters `date`, `byStaticName`, and `key` from the <ApiLink name="fetchLookupTableInZipFormat" /> endpoint.
* Added `currency` properties to the entities <ApiLink name="PaymentCreateRequest" />, <ApiLink name="PaymentUpdateRequest" />, <ApiLink name="LedgerAccountResponse" />, and <ApiLink name="AccountingTransactionResponse" />.
* <ApiLink name="Installment" /> now has a `reversalOfTransactionLocator`
  property, but `installmentState` and `amount` have been removed.

February 23, 2024 [#february-23-2024]

* Marked the `baseLapseOn` and `lapseConflictHandling` properties of the configuration item <ApiLink name="DelinquencyPlanRef" /> as `deprecated`. These will be removed in an upcoming release.

February 21, 2024 [#february-21-2024]

* Changed the name of the `CreditResponse` entity to <ApiLink name="PaymentResponse" />
* Added the <ApiLink name="fetchTableRecord" /> endpoint
* Added the <ApiLink name="PaymentRef">payments</ApiLink> and <ApiLink name="DisbursementRef">disbursements</ApiLink> properties to <ApiLink name="ConfigurationRef" />

February 8, 2024 [#february-8-2024]

Changed Endpoints [#changed-endpoints]

* <ApiLink name="addElementsToQuote" /> has changed the type of its `elements`
  property to
  <ApiLink name="ElementCreateRequest">ElementCreateRequest\[]</ApiLink>
* <ApiLink name="updateAccountReplaceData" /> has changed its request type to
  <ApiLink name="AccountUpdateReplaceDataRequest" />
* <ApiLink name="updateUser" /> has changed its request type to
  <ApiLink name="UserUpdateRequest" />

Changed Entities [#changed-entities]

* <ApiLink name="QuoteCreateRequest" /> has changed the type of its `elements`
  property to
  <ApiLink name="ElementCreateRequest">ElementCreateRequest\[]</ApiLink>

February 6, 2024 [#february-6-2024]

Added Endpoints [#added-endpoints]

* `fetchInvoiceJobDataForQuotes`
* `fetchInvoiceJobDataForPolicies`

Removed Endpoints [#removed-endpoints]

* `issueNextInvoiceForAccount`
* `fetchLedgerAccountLineItems`

Added Entities [#added-entities]

* `InvoiceGenerationJob`

Changed Entities [#changed-entities-1]

* <ApiLink name="PaymentResponse" /> has new property `currency`

* <ApiLink name="InstallmentItem" /> has property `staticElementLocator` renamed
  to `staticElementLocator`

* <ApiLink name="InvoiceItemResponse" /> has the types of properties
  `chargeCategory` and `chargeType` both changed to `string`

* <ApiLink name="Installment" /> has these properties renamed:

* `generateDate` => `generateTime`

* `dueDate` => `dueTime`

* `installmentStartDate` => `installmentStartTime`

* `installmentEndDate` => `installmentEndTime`

* <ApiLink name="InstallmentLatticeFrame" /> has these properties renamed:

* `generationDate` => `generateTime`

* `dueDate` => `dueTime`

* `installmentStart` => `installmentStartTime`

* `installmentEnd` => `installmentEndTime`

* `coverageStart` => `coverageStartTime`

* `coverageEnd` => `coverageEndTime`

* <ApiLink name="ConfigurationRef" /> has removed property `defaults`


# Release Notes



import Image from 'next/image';

<Callout>
  The structure and use of the API does not change when names of entities or endpoint operation IDs change. These changes are typically made for clarity and consistency.
</Callout>

All changes to the API listed here are also reflected in our [Open API definition file](/other-resources/open-api-specification).

{/* TODO: Document https://socotra.atlassian.net/browse/KERN-3822 */}

Upcoming Releases [#upcoming-releases]

This section provides advanced notice of updates in upcoming releases. It does not represent a comprehensive list of changes in a release, and all items are subject to change prior to the release date.

September 30, 2026 [#september-30-2026]

Removal of Deprecated List Query Parameter [#removal-of-deprecated-list-query-parameter]

The `extended` query parameter is being phased out from all `/list` API endpoints. This parameter previously gated access to the new response model, `ListPageResponse`. Going forward, `ListPageResponse` becomes the default and only response shape for these endpoints.

**Migration Path**

Starting now:

* Pass `extended=true` on any `/list` endpoint to opt into the new `ListPageResponse` model.
* `ListPageResponse<T>` wraps the previous flat list in a structured payload with two fields: `items` (the page of results) and `listCompleted` (a boolean indicating whether the returned page is the last one, meaning no further pages to fetch).
* Update your integrations to consume `ListPageResponse` while the legacy flat-list response is still available as the default.

On September 30, 2026:

* The `extended` query parameter will be removed entirely.
* `ListPageResponse` becomes the sole response shape — No change to clients already migrated.
* Clients may (and should) stop passing extended since the parameter will no longer exist.

**Recommended Action**

Migrate clients to send `extended=true` and consume `ListPageResponse` before September 30, 2026. After the cutover, drop the `extended` query parameter from your calls. The response shape stays the same.

**Affected Endpoints**

Billing (29 endpoints)

* `GET /credits/list`
* `GET /writeOffs/list`
* `GET /shortfallCredits/list`
* `GET /creditDistributions/list`
* `GET /creditDistributions/{locator}/invoices/list`
* `GET /installments/quotes/{quoteLocator}/list`
* `GET /installments/policies/{policyLocator}/list`
* `GET /installments/transactions/{transactionLocator}/list`
* `GET /jobs/installments/quotes/{locator}/list`
* `GET /jobs/installments/transactions/{locator}/list`
* `GET /jobs/invoices/accounts/{locator}/list`
* `GET /jobs/delinquencies/invoices/{invoiceLocator}/list`
* `GET /jobs/delinquencies/{delinquencyLocator}/list`
* `GET /financialInstruments/list`
* `GET /holds/accounts/{accountLocator}/list`
* `GET /disbursements/list`
* `GET /payments/list`
* `GET /payments/{locator}/invoices/list`
* `GET /accounting/ledgerAccounts/cash/list`
* `GET /installmentLattices/policies/{policyLocator}/list`
* `GET /delinquencies/accounts/{accountLocator}/list`
* `GET /delinquencies/policies/{policyLocator}/list`
* `GET /delinquencies/invoices/{invoiceLocator}/list`
* `GET /invoices/{locator}/payments/list`
* `GET /invoices/{locator}/creditDistributions/list`
* `GET /invoices/{locator}/credits/list`
* `GET /invoices/quotes/{quoteLocator}/list`
* `GET /invoices/policies/{policyLocator}/list`
* `GET /invoices/accounts/{accountLocator}/list`

Events (1 endpoint)

* `GET /webhooks/list`

Aux Data (2 endpoints)

* `GET /mediadata/{locator}/list`
* `GET /mediadata/search/{referenceType}/{referenceLocator}/list`

Plugins (1 endpoint)

* `GET /logs/list`

Documents (6 endpoints)

* `GET /documents/segment/{locator}/list`
* `GET /documents/segment/{locator}/jobs/list`
* `GET /documents/transaction/{locator}/list`
* `GET /documents/transaction/{locator}/jobs/list`
* `GET /documents/quote/{locator}/list`
* `GET /documents/quote/{locator}/jobs/list`

Resources (3 endpoints)

* `GET /groups/list`
* `GET /resources/list`
* `GET /resources/type/{type}/list`

Users (5 endpoints)

* `GET /roles/list`
* `GET /users/list`
* `GET /users/basic/list`
* `GET /tenants/list`
* `GET /tenants/mytenants/list`

Policies (10 endpoints)

* `GET /accounts/list`
* `GET /accounts/{locator}/quotes/list`
* `GET /accounts/{locator}/policies/list`
* `GET /accounts/{locator}/policies/snapshot/list`
* `GET /policies/{locator}/issuedTransactions/list`
* `GET /policies/{locator}/terms/list`
* `GET /quickquotes/list`
* `GET /quickquotes/group/{locator}/list`
* `GET /quotes/list`
* `GET /quotes/group/{locator}/list`

Total: 57 endpoints across 8 services.

***

**Past Releases**

September 2, 2026 [#september-2-2026]

UI Enhancements [#ui-enhancements]

Users can now edit document names in the UI before attaching documents.

<Image src="/images/edit-document-name.png" alt="Edit Document Name" width={7032} height={4456} unoptimized />

New API Endpoints [#new-api-endpoints]

The <ApiLink name="downloadScheduleItemsCsv">Download Quote Schedule Items</ApiLink> and <ApiLink name="downloadTransactionScheduleItemsCsv">Download Transaction Schedule Items</ApiLink> API endpoints can be used to download schedule items in CSV file format via a `StreamingResponseBody<string>` response for quotes and policy transactions, respectively.

Bug Fixes [#bug-fixes]

{/* KERN-8669 */}

* Fixed an issue that caused the <ApiLink name="getResourceSelections">Fetch Resource Selections</ApiLink> API endpoint to return a `500` response instead of a `404` response when an invalid `referenceLocator` is provided.

August 26, 2026 [#august-26-2026]

New Feature: Public Skills [#new-feature-public-skills]

[Socotra public skills](https://github.com/socotra/socotra-skills) transform insurance product descriptions into working products, including tenant configurations, data models, and plugin implementations for validation, pricing, and underwriting using AI agents and the [Socotra MCP server](/ai-guide/mcp-server/overview). See the [Socotra Public Skills](/ai-guide/public-skills/public-skills-overview) feature guide for more information.

Error Code Update [#error-code-update]

Response `errorCode` `214045` has changed to `214043` for the following API endpoints when targeting an existing table:

* `POST /resource/{tenantLocator}/rangeTables`
* `POST /resource/{tenantLocator}/tables`
* `PATCH /resource/{tenantLocator}/tables/...`
* `PATCH /resource/{tenantLocator}/rangeTables/...`

Other Enhancements [#other-enhancements]

* Documents can now be <ApiLink name="softRemoveDocument">soft-deleted</ApiLink>, meaning they will no longer be attached to any entities (such as quotes or policies) to which they are currently attached, but will remain accessible within the system. See the [Document Management](/features/documents/document-management#deleting-documents) feature guide for more information.
* The migration service now allows for the migration of transactions with effective dates after a cancellation.

Bug Fixes [#bug-fixes-1]

{/* KERN-8635, DOC-833, KERN-8653 */}

* Fixed an issue that triggered delinquency events during a moratorium.
* Fixed an issue that displayed incorrect change instruction schemas on the Policy Transactions API reference page.
* Fixed an issue that caused the Cancellation Plugin to fail when only a flat charge is present.

August 19, 2026 [#august-19-2026]

New Feature: Resource Locking [#new-feature-resource-locking]

The `LockingResourceSelector` forces specified managed [resources](/configuration/resources/versioned-resource-selection) to remain unchanged for a term or quote following initial selection. This selector contains all [Resource Selector](/configuration/plugins/overview#resource-selector) methods, in addition to a `lock()` method that forces the system to use specified resource instances for a term or quote. See the [Versioned Resource Selection](/configuration/resources/versioned-resource-selection#locked-resources) feature guide for more information.

Documentation Enhancements [#documentation-enhancements]

* Reporting documentation has been updated to include a new high-level [overview](/features/reporting/reporting-overview) of Socotra's reporting offerings, along with additional details across existing pages such as [replication guidance](/features/reporting/reporting-overview#data-replication-to-your-data-infrastructure) and [schema conventions](/features/reporting/tables#schema-conventions).

Other Enhancements [#other-enhancements-1]

* The Socotra [MCP Server](/ai-guide/mcp-server/overview) will now be enabled by default for all business accounts in the Sandbox environment.
* [Migration](/features/migration) processing logic now includes validation to prevent the migration of [out-of-sequence transactions](/features/policy-management/out-of-sequence-transactions).

Bug Fixes [#bug-fixes-2]

{/* UX-5808 */}

* Fixed an issue that prevented term numbers from appearing in the UI.

August 12, 2026 [#august-12-2026]

Data Fetcher Enhancements [#data-fetcher-enhancements]

The [Plugin Data Fetcher](/configuration/plugins/overview#data-fetcher) can now be used to retrieve contacts through the `getQuoteContacts()`, `getPolicyContacts()`, and `getAccountContacts()` methods.

Documentation Enhancements [#documentation-enhancements-1]

All API reference pages now display automatically-generated JSON examples for request and response objects based on our current API specifications.

<Image src="/images/example-json.png" alt="Example JSON" width={7032} height={4456} unoptimized />

Bug Fixes [#bug-fixes-3]

{/* KERN-8552 */}

* Fixed an issue that caused the <ApiLink name="updateAccount">updateAccount</ApiLink> API endpoint to return a configuration error.

August 5, 2026 [#august-5-2026]

Documentation Enhancements [#documentation-enhancements-2]

* New documentation detailing the [events service](/configuration/plugins/overview#events-service) and [money service](/configuration/plugins/overview#money-service) has been added to the [Plugins Overview](/configuration/plugins/overview) feature guide.

Bug Fixes [#bug-fixes-4]

{/* KERN-8525 */}

* Fixed an issue that prevented the `document.failed` and `document.copyOnIssue.ready` events from firing.

July 29, 2026 [#july-29-2026]

Data Lake Enhancements [#data-lake-enhancements]

The following tables have been added to the [Data Lake](/features/reporting/datalake):

* [quote\_preferences](/features/reporting/tables#quote_preferences)
* [external\_cash\_transactions](/features/reporting/tables#external_cash_transactions)
* [financial\_instruments](/features/reporting/tables#financial_instruments)

An issue that prevented some unique policy change instruction records from being persisted in the [Data Lake](/features/reporting/datalake) [policy\_transaction\_change\_instructions](/features/reporting/tables#policy_transaction_change_instructions) table has been fixed by updating its composite primary key to include `transaction_locator`, resulting in the regeneration of all historical data in the table.

Cardinality is now provided in the [Data Lake Table Index](/features/reporting/tables) for any relationships between tables.

Documentation Enhancements [#documentation-enhancements-3]

* The [Resource Selector](/configuration/plugins/overview#resource-selector) guide has been improved as part of a rollout of updated plugin documentation. New examples have been added demonstrating how to use the `ResourceSelector` to retrieve table data, constraints, and secrets.

Other Enhancements [#other-enhancements-2]

* The `disburseExcess` configuration property is now required for <ApiLink name="ExcessCreditPlanRef">ExcessCreditPlanRef</ApiLink> configuration objects.

Aux Data Key Limit [#aux-data-key-limit]

A limit of 500 keys per request will now be enforced when creating or updating [aux data](/api/aux-data/aux-data) through the [Add Aux Data](/api/aux-data/aux-data#add-aux-data) API endpoint.

Bug Fixes [#bug-fixes-5]

{/* KERN-8379, KERN-7683 */}

* Fixed an issue that allowed payments to move between the `cancelled` state and `failed` state.
* Fixed an issue that rejected requests to the <ApiLink name="fetchPreferencesForATransaction">Fetch Preferences For A Transaction</ApiLink> API endpoint for policy transactions in the `draft` or `initialized` state, which also caused the [Precommit Plugin](/configuration/plugins/precommit) to fail.

July 22, 2026 [#july-22-2026]

Documentation Enhancements [#documentation-enhancements-4]

* The [Plugins Overview](/configuration/plugins/overview) feature guide has been improved as part of a rollout of updated plugin documentation.

Other Enhancements [#other-enhancements-3]

* The `document.copyOnIssue.ready` [event](/configuration/general-topics/events) will now be emitted when documents attached to a quote are copied and attached to the resulting policy when the quote is issued. See the [Event Definitions](/configuration/general-topics/event-definitions#document-events) index for more information.

July 15, 2026 [#july-15-2026]

Socotra Assistant Configuration [#socotra-assistant-configuration]

The [Socotra Assistant](/ai-guide/assistant/overview) can now be configured through the top-level <ApiLink name="AssistantRef">AssistantRef</ApiLink> configuration object. This configuration allows the assistant to authenticate requests performed on behalf of a tenant and controls how inbound emails are routed to [tasks](/features/work-management/tasks) in the [email intake workflow](/ai-guide/assistant/email-intake). See the [Socotra Assistant Configuration](/configuration/general-topics/assistant) guide for more information.

Integrations Plugin [#integrations-plugin]

The Integrations Plugin allows you to customize email delivery logic used by the [Socotra Assistant](/ai-guide/assistant/overview). See the [Integrations Plugin](/configuration/plugins/integrations) feature guide for more information.

New Login Page [#new-login-page]

The new login page provides a more uniform, branded, and streamlined experience when entering a username and password. An example of the new login page can be found [here](/getting-started/log-into-socotra#steps).

This page has been available by request for existing business accounts since the [March 25, 2026](#march-25-2026) release and will now become the default experience for all business accounts. This change will be rolled out gradually, beginning with this release.

Policy Transaction Extension Data [#policy-transaction-extension-data]

Extension data can now be associated with policy transactions through <ApiLink name="TransactionDataChangeInstructionCreateRequest">TransactionDataChangeInstructionCreateRequest</ApiLink> objects or the <ApiLink name="patchTransactionData">Patch Transaction Data</ApiLink> API endpoint to accommodate custom data that relates to an entire policy transaction. Policy transaction extension data can be configured through the `data` property at the top level of each <ApiLink name="TransactionTypeRef">TransactionTypeRef</ApiLink> configuration object.

See the [Policy Transactions](/features/policy-management/policy-transactions#policy-transaction-extension-data) feature guide for more information.

July 8, 2026 [#july-8-2026]

Installment Grouping [#installment-grouping]

* The <ApiLink name="InstallmentGroupingDetails" /> configuration object can now be used to control installment grouping logic when the system generates invoices. See the [Invoicing](/features/billing/invoicing#grouping-installments) feature guide for more information.

Data Lake Enhancements [#data-lake-enhancements-1]

The following fields have been added to the listed [Data Lake](/features/reporting/datalake) tables, resulting in the regeneration of all historical data in each table:

* [invoice\_items](/features/reporting/tables#invoice_items) - `unsettled_time_utc`
* [policy\_preferences](/features/reporting/tables#policy_preferences) - `autopay_lead_days`
* [tasks](/features/reporting/tables#tasks) - `source`, `tag`

The following new [Data Lake](/features/reporting/datalake) tables have been provided to better support reporting for [Work Management](/features/work-management/work-management-overview) capabilities:

* [task\_history](/features/reporting/tables#task_history)
* [user\_association\_history](/features/reporting/tables#user_association_history)

Documentation Enhancements [#documentation-enhancements-5]

* Our new [Transactions and Billing](/learning/transactions-and-billing) guide examines Socotra's billing system through interactive lessons based on a downloadable configuration and Postman collection.
* The [Autopay Plugin](/configuration/plugins/autopay) feature guide has been improved as part of a rollout of updated plugin documentation.
* The [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing) feature guide has been improved as part of a rollout of updated plugin documentation.

Other Enhancements [#other-enhancements-4]

* As the system processes out-of-sequence transactions, any change instructions for elements that no longer exist as a result of reapplied transactions will be ignored by the system to allow processing to continue. See the [Out-of-Sequence Transactions](/features/policy-management/out-of-sequence-transactions) feature guide for more information.

July 1, 2026 [#july-1-2026]

New Task Dashboard Experience: Beta Launch [#new-task-dashboard-experience-beta-launch]

The new task dashboard experience beta is now available, which introduces enhanced filtering capabilities and task summary cards to help underwriters triage and manage work more efficiently. This release also introduces portfolios, which provide a consolidated view of all user associations. The dashboard also includes performance enhancements resulting in faster load times, particularly for teams managing higher task volumes.

Contact your Socotra representative to enable the beta version of the task dashboard.

<Image src="/images/new-task-dashboard.png" alt="The new task dashboard" width={7032} height={4456} unoptimized />

New Built-In Data Type: Object [#new-built-in-data-type-object]

The new built-in `object` data type accommodates more complex data models out of the box, bypassing the need to configure [custom data types](/configuration/data-extensions/custom-data-types) when defining [extension data](/configuration/data-extensions/overview) and [Automation Plugin](/configuration/plugins/automation) request and response objects. See the [Data Extension Types](/configuration/data-extensions/data-extension-types) guide for more information.

New Document Triggers [#new-document-triggers]

The `declined`, `rejected`, and `refused` document lifecycle states can now be configured as document triggers. See the [Documents](/configuration/resources/documents#policy-document-workflow) feature guide for more information.

New API Endpoint [#new-api-endpoint]

The [Fetch Credential Status](/api/business-accounts/authentication#fetch-credential-status) API endpoint can be used to check if a user currently has a password or a temporary password enabled.

Documentation Enhancements [#documentation-enhancements-6]

Documentation on reversing multiple transactions has been added to the [Policy Transactions](/features/policy-management/policy-transactions#reversing-multiple-transactions) feature guide.

Bug Fixes [#bug-fixes-6]

{/* KERN-8333, KERN-8337, KERN-8302 */}

* Fixed an issue that triggered a delinquency based on open invoice credits.
* Fixed an issue that prevented the `producerCode` associated with a policy from being copied to the resulting quote when using the [Create Quote From Policy](/api/quotes/quotes#create-quote-from-policy) API endpoint.

June 24, 2026 [#june-24-2026]

Documentation Enhancements [#documentation-enhancements-7]

Data Lake Table Index [#data-lake-table-index]

The [Data Lake Table Index](/features/reporting/tables) has been updated to include clear column attributes such as `PK`, `Index`, `Relationship`, and `Discriminator`, along with mappings for all columns that reference other tables. It also includes all enum values for system-defined fields, along with indications of which field values are defined within configuration.

Delta Files [#delta-files]

The [Delta Files Feature Guide](/features/reporting/delta-files#data-availability) has been updated to include more information about the new `dataProcessedThroughTime` property, which can be used to guarantee completeness of data across delta file tables.

Automation Plugin [#automation-plugin]

The [Automation Plugin](/configuration/plugins/automation) feature guide has been updated to provide additional information on the `PluginExecutionContext` and `AutomationPluginContextData` classes, logging, and support for custom data types.

Search Updates [#search-updates]

The following updates have been made to [Search](/features/search) capabilities:

* Tasks and user associations are now searchable entities
* New features such as date field operators and sorting are now provided for certain entities

Deprecations [#deprecations]

The following deprecated features have been permanently removed with this release:

* `ParamsChangeInstruction#inherit_settings` - This API object has been deprecated since May 2024
* `Payment#state()` - This plugin method has been replaced by the `paymentState()` method, and has been deprecated since July 2024

Shortfall Write-Off Reversals [#shortfall-write-off-reversals]

Shortfall write-offs can no longer be reversed using the <ApiLink name="reverseWriteOff">Reverse a Write-Off</ApiLink> API endpoint. Only manually created write-offs support this operation.

To reverse a shortfall write-off, reverse the parent payment or credit distribution using the <ApiLink name="reversePayment">Reverse a Posted Payment</ApiLink> or <ApiLink name="reverseCreditDistribution">Reverse Credit Distribution</ApiLink> API endpoints. This will automatically reverse all associated write-offs.

See the [Write-Offs](/features/billing/write-offs#reversal-support) feature guide for more information.

June 17, 2026 [#june-17-2026]

New Documentation Experience [#new-documentation-experience]

The new documentation experience previously available at [docs-beta.socotra.com ](https://docs-beta.socotra.com) during the beta period is now the default experience on [docs.socotra.com ](https://docs.socotra.com).

Some content page URLs differ from the legacy documentation site, but redirects are in place to route old URLs to their corresponding new pages. The published OpenAPI specification also includes some minor revisions and additional schema context.

The new documentation experience includes:

* **Refreshed design** - Modernized interface with a right-side navigation panel, dark mode, and more
* **Socotra Assistant** - Our AI assistant is built directly into the docs for fast, in-context help
* **AI-friendly format** - Markdown-based source makes it easier to use docs alongside AI tools

Feedback on the new documentation experience is welcome. Please share any comments with your Socotra representative.

New Feature: Preferred Quotes [#new-feature-preferred-quotes]

A maximum of one quote locator can now be marked as a `preferredQuoteLocator` within each quote group, which can be used to indicate that the specified quote is the most likely quote to be issued. See the [Quote Groups](/features/policy-quotation/quote-groups#PreferredQuotes) feature guide for more information.

Data Lake Enhancements [#data-lake-enhancements-2]

On Friday, May 29, we released a change to Data Lake and Delta Files in the sandbox environment that prevents unnecessary no-op record updates. On Friday, June 12, we released this change to production environments. This change makes update timestamps more accurate and improves replication efficiency.

As part of this release, Data Lake records and Delta Files in each production environment, across all business accounts and tenants, have been successfully deleted and regenerated, with resulting `datalake_updated_timestamp` and `datalake_created_timestamp` values reflecting the time of data regeneration.

Other Enhancements [#other-enhancements-5]

* When a reversal charge is created, all tags associated with the original charge will now be copied and associated with the reversal charge. See the [Flat Charges](/features/billing/flat-charges#InvoicingBehavior) feature guide for more information.
* The `endTime` will now be automatically calculated for quotes if no value for `endTime` is provided when creating or updating quotes. See the [Quotes](/features/policy-quotation/quotes#CalculatingEndTime) feature guide for more information.
* The `accountLocator` associated with a quote can now be updated when updating quotes. See the [Quotes](/features/policy-quotation/quotes#UpdatingAccountLocator) feature guide for more information.
* Policy transaction data now includes an `expirationTime`. See the [Policy Transaction Stack](/features/policy-management/policy-transaction-stack#TransactionData) guide for more information.

June 10, 2026 [#june-10-2026]

Producer Management Enhancements [#producer-management-enhancements]

The [producer management](/features/producer-management/producer-management-overview) feature has been updated to support the following functionality:

* Producers can now be associated with [licenses](/features/producer-management/licenses) and [appointments](/features/producer-management/appointments), which authorize producers to conduct business in relation to specific [products ](/getting-started/create-a-tenant-configuration-file#what-is-an-insurance-product) and [jurisdictions](/features/jurisdictions).
* Products can now be configured to require producers associated with a quote or policy transaction to have a valid license or appointment when an underwriting request is processed.

Bug Fixes [#bug-fixes-7]

{/* KERN-7683, KERN-8131 */}

* Fixed an issue that caused calls to the <ApiLink name="fetchPreferencesForATransaction" /> API endpoint to fail for transactions in the `draft` or `validated` state.
* Fixed an issue that allowed installments to have an `autopayTime` earlier than the `generateTime`.

June 3, 2026 [#june-3-2026]

New Feature: External Numbering Support [#new-feature-external-numbering-support]

The Socotra Insurance Suite now supports quote and policy numbering by external systems. See the [External Numbering Support](/configuration/general-topics/external-numbering-support) feature guide for more information.

Other Enhancements [#other-enhancements-6]

* Diary entries can now be associated with elements within a quote or policy segment through the <ApiLink name="createDiaryForSegmentElement" /> and <ApiLink name="createDiaryForQuoteElement" /> API endpoints. See the [Diaries](/features/work-management/diaries) feature guide for more information.
* The <ApiLink name="updateInstallments" /> API endpoint can be used to modify the `generateTime`, `dueTime`, and `autopayTime` of uninvoiced installments. See the [Invoicing](/features/billing/invoicing#installmentTiming) feature guide for more information.
* Invoice consolidation on cancellation functionality can now be configured through <ApiLink name="InvoicingPlanRef" /> configuration objects. See the [Invoicing](/features/billing/invoicing#InvoiceConsolidation) feature guide for more information.

Data Lake Updates in Sandbox [#data-lake-updates-in-sandbox]

On Friday, May 29, we released a change to Data Lake and Delta Files in the sandbox environment that prevents unnecessary no-op record updates. This change made update timestamps more accurate and improved replication efficiency.

As part of this release, Data Lake records and Delta Files in sandbox, across all business accounts and tenants, have been deleted and regenerated.

The production release for this feature is expected to follow in mid-June.

Bug Fixes [#bug-fixes-8]

{/* KERN-8145 */}

* Fixed an issue that prevented updates to FNOLs after enabling data anonymization.

May 27, 2026 [#may-27-2026]

New Feature: Socotra Assistant Email Intake Workflow [#new-feature-socotra-assistant-email-intake-workflow]

The Socotra Assistant can now intercept emails and extract email data to assist with the underwriting process. See the [Email Intake Workflow](/ai-guide/assistant/email-intake) feature guide for more information.

New Documentation Experience: Beta Launch [#new-documentation-experience-beta-launch]

The updated Socotra documentation experience launched in beta at [docs-beta.socotra.com ](https://docs-beta.socotra.com). See the New Documentation Experience (Beta) section above for details on what's new and the beta timeline.

Other Enhancements [#other-enhancements-7]

The `description` field for <ApiLink name="MoratoriumRef">moratoriums</ApiLink> now has a character limit of 1024. Previously, the character limit was 512.

Deprecations [#deprecations-1]

The following deprecated features have been permanently removed with this release:

* `AutopayPluginRequest` - This single-parameter plugin request constructor has been replaced by the two-parameter constructor (Invoice, boolean), and has been deprecated since July 2025
* `ChargeRef#category` - Enum values `commission`, `flatPremium`, `flatTax`, `flatCommission`, and `flatCededPremium` for this configuration field have been deprecated since January 2025, and all flat charge categories are now handled through flat fee functionality
* `InstallmentPlanDetails` - Constructors for this plugin object have been kept to support backwards compatibility of older deployments, and have been deprecated since May 2025
* `InstallmentPlanRef#invoiceFeeAmounts` - This configuration field is now handled through the `InvoicingPlanRef` object, deprecated since March 2025
* `DelinquencyEventConfiguration#offsetBasis` - The enum value `delinquencyCreation` for this configuration field has been deprecated since November 2024
* `WriteOffTolerancePlan` - This configuration object has been replaced by the `ShortfallTolerancePlanRef` object, and has been deprecated since March 2024

In preparation for forthcoming configuration versioning capabilities, <ApiLink name="DeploymentMetadata" /> has been updated to include a new `staticVersionLocator` property.

May 20, 2026 [#may-20-2026]

Documentation Updates [#documentation-updates]

* New details on issuance policy transactions and reversal policy transactions have been added to the [Execute policy transactions](/getting-started/execute-policy-transactions#policyTransaction) guide.

Deprecations [#deprecations-2]

The following deprecated features have been permanently removed with this release:

* `BillingTrigger` - The `accept` value for this configuration object has been deprecated since September 2025
* `BillingPreferences` - This API request object has been deprecated since July 2024
* `PolicyInvoiceSummary` - This API response object has been replaced by the `invoiceSummaries` field within the `InvoiceDetailsResponse` object, and has been deprecated since February 2025
* `transactionLocator` - The `transactionLocator` field within the `InvoiceItemResponse` API response object has been replaced by the `transactionLocators` field, and has been deprecated since January 2026
* `Invoice#state()` - This plugin method has been replaced by the `invoiceState()` method, and has been deprecated since August 2024
* `DelinquencyReferenceType#quote` - This plugin enum and API response enum was previously used for billing on quote acceptance, which is not supported anymore, and has been deprecated since June 2025

Bug Fixes [#bug-fixes-9]

{/* KERN-8005 */}

* Fixed an issue that caused account validation to succeed when required fields were missing.

May 13, 2026 [#may-13-2026]

Producer Management Enhancements [#producer-management-enhancements-1]

The producer management feature has been updated to support the following functionality:

* Associating a producer code with a quote or policy transaction
* Viewing producer code history
* Customizing the underwriting flag that will be automatically added to a quote or policy transaction if the associated producer code or the producers associated with the producer code are invalid

See the [Producer Management](/features/producer-management/producer-management-overview) feature guide for more information.

Other Enhancements [#other-enhancements-8]

Today's release changes the way billing operates at the time of quote issuance to ensure billing consistency across the policy lifecycle.

Historically, because we could trigger billing at quote acceptance (deprecated), billing at quote issuance was also centered around the quote entity. Going forward, billing at issuance will be centered around the policy issuance transaction, meaning billing is now always initiated when the issuance transaction is issued, rather than when the quote moves to the `issued` state. As a result, all billing operations now reference a policy rather than a quote.

Key changes:

**Default billing trigger configuration property has been removed**

* The `defaultBillingTrigger` configuration <ApiLink name="ConfigurationRef">property</ApiLink> has been removed and will no longer be accepted in tenant configs.
* Any tenants that still have `defaultBillingTrigger` set must remove it to avoid deployment failures.

**Quote accounting reference type has been removed**

* The `GET /billing/{tenant}/accounting/ledgerAccounts/quote/{locator}` API <ApiLink name="fetchLedgerAccount">endpoint</ApiLink> is no longer valid.
* Clients querying ledger account balances for a policy by its quote locator should switch to `GET /billing/{tenant}/accounting/ledgerAccounts/policy/{locator}`.

**Installment job response properties have been removed**

* The `jobType` and `referenceType` fields are no longer returned in <ApiLink name="fetchInstallmentsJobDataForQuotes">installment job API</ApiLink> list <ApiLink name="InstallmentJobDataListResponse">responses</ApiLink>:
* `GET /billing/{tenant}/jobs/installments/quotes/{locator}/list`
* `GET /billing/{tenant}/jobs/installments/transactions/{locator}/list`

**Data Lake implications**

* The `charge_locator` in the `installment_items` table now reflects `policy_element_charges.locator` rather than `quote_element_charges.locator`. Historical records are not impacted.
* The `reference_type` in `ledger_accounts`, `ledger_account_line_items`, and `fa_transaction_account_lines` no longer returns a value of `quote`. Historical records are not impacted.

We recommend ensuring that the `defaultBillingTrigger` is not present in any configurations, which could impact deployment.

May 6, 2026 [#may-6-2026]

New Feature: Negative Invoice Processing [#new-feature-negative-invoice-processing]

Accounts can now be configured to automatically settle open, unsettled invoices using credits that originated from negative invoices. See the [Negative Invoice Processing](/features/billing/excess-credits#NegativeInvoiceProcessing) feature guide for more information.

New Feature: Custom Schedule Item Processing [#new-feature-custom-schedule-item-processing]

The Deserialization Plugin can be used to define asynchronous processing logic for large lists of schedule items. See the [Custom Schedule Item Processing](/features/schedules#CustomScheduleItemProcessing) feature guide for more information.

Documentation Updates [#documentation-updates-1]

* New details on list endpoints and pagination have been added to the [API Overview](/api) guide.

Bug Fixes [#bug-fixes-10]

{/* KERN-7952, KERN-7838, KERN-7767, KERN-7792, KERN-7881 */}

* Fixed an issue that caused CSV-formatted delta files to be duplicated when processing more than one file per generation job.
* Fixed an issue that caused automatic policy renewals to fail.
* Fixed an issue that prevented write-off generation during migrations.
* Fixed an issue that caused invoice `dueTime` to be off by 1 hour when the due date occurs on the DST start date.
* Fixed an issue that caused invoices to remain open after a write-off.

April 29, 2026 [#april-29-2026]

New Feature: Quote Groups [#new-feature-quote-groups]

Quote groups can be used to categorize quote variants that represent a single prospective contract or marketing opportunity. See the [Quote Groups](/features/policy-quotation/quote-groups) feature guide for more information.

Documentation Updates [#documentation-updates-2]

* New details on retrieving policy transaction descriptions have been added to the [Policy Transaction Stack](/features/policy-management/policy-transaction-stack) feature guide.

April 22, 2026 [#april-22-2026]

New Feature: Tenant Events [#new-feature-tenant-events]

Custom scheduled events now support tenant-level events in addition to policy-level events. See the [Custom Scheduled Events](/configuration/general-topics/scheduled-events#TenantEvents) feature guide for more information.

Other Enhancements [#other-enhancements-9]

* [Invoice Consolidation on Cancellation](/features/billing/invoicing#InvoiceConsolidation): When a cancellation [transaction](/features/policy-management/policy-transactions) is issued, the system will consolidate all remaining uninvoiced installments for the cancelled period into the next eligible installment for that period. Invoice [previews](/features/preview-operations) will also reflect this change. This consolidation logic is the default system behavior for all customers. See the [Invoicing](/features/billing/invoicing#InvoiceConsolidation) feature guide for more information.

Documentation Updates [#documentation-updates-3]

* External documents, which are documents manually attached through the <ApiLink name="attachDocument">Attach Document</ApiLink> API endpoint, can be deleted using the <ApiLink name="deleteDocument">Delete Document</ApiLink> API endpoint. See the [Document Management](/features/documents/document-management#DeletingDocuments) guide for more information.

Bug Fixes [#bug-fixes-11]

{/* KERN-7781 */}

* Fixed an issue that prevented failed migrations from recovering.

April 15, 2026 [#april-15-2026]

Documentation Updates [#documentation-updates-4]

* The [Cancellation Plugin](/configuration/plugins/cancellation) feature guide has been improved as part of a rollout of updated plugin documentation.
* The [Producer Management](/features/producer-management/producer-management-overview) feature guide has been updated to provide additional information on numbering plans and the lifecycle for producers and producer codes.

April 8, 2026 [#april-8-2026]

Documentation Updates [#documentation-updates-5]

* The [Underwriting Plugin](/configuration/plugins/underwriting) and [Installments Plugin](/configuration/plugins/installments) feature guides have been improved as part of a rollout of updated plugin documentation.
* Additional details have been added to the upcoming deprecation notices to help our customers replace deprecated functionality scheduled for permanent removal.

Bug Fixes [#bug-fixes-12]

{/* KERN-7304, KERN-7153 */}

* Fixed an issue that caused the <ApiLink name="fetchUnderwritingFlagsForTransaction">Fetch Underwriting Flags</ApiLink> API endpoint to return incorrect underwriting flag locators.
* Fixed an issue that prevented the system from enforcing [numbering plans](/configuration/general-topics/entity-numbering).

April 1, 2026 [#april-1-2026]

Data Lake Enhancements [#data-lake-enhancements-3]

The following tables have been added to [Data Lake](/features/reporting/datalake) to support reporting for the [Producer Management](/features/producer-management/producer-management-overview) feature set:

* [producers](/features/reporting/tables#producers)
* [producer\_data\_extensions](/features/reporting/tables#producer_data_extensions)
* [producer\_hierarchy](/features/reporting/tables#producer_hierarchy)
* [producer\_codes](/features/reporting/tables#producer_codes)
* [producer\_code\_data\_extensions](/features/reporting/tables#producer_code_data_extensions)

Bug Fixes [#bug-fixes-13]

{/* KERN-7687 */}

* Fixed an issue that prevented the [Precommit Plugin](/configuration/plugins/precommit) from modifying producer codes.

March 25, 2026 [#march-25-2026]

New Feature: Producer Management [#new-feature-producer-management]

Producer management refers to a set of features within Socotra designed to support producers such as brokers and agents. See the [Producer Management](/features/producer-management/producer-management-overview) feature guide for more information.

Data Lake Enhancements [#data-lake-enhancements-4]

* The following fields were added to the listed [Data Lake](/features/reporting/datalake) tables, resulting in the regeneration of all historical data in each table:
  * [policy\_segment\_elements](/features/reporting/tables#policy_segment_elements) - `original_effective_time_utc`
  * [policy\_element\_charges](/features/reporting/tables#policy_element_charges) - `invoicing`, `handling`
  * [quote\_element\_charges](/features/reporting/tables#quote_element_charges) - `invoicing`, `handling`
  * [disbursements](/features/reporting/tables#disbursements) - `disbursement_number`

* Fixed an issue in the Gross Written Premium (GWP) [Metric](/features/reporting/metrics) returned by the <ApiLink name="getGWP">Fetch GWP Metrics API</ApiLink> by updating its definition to properly account for out-of-sequence (OOS) and reversal transactions, ensuring historical periods are not retroactively modified.

Other Enhancements [#other-enhancements-10]

{/* KERN-7507 */}

* For newly created business accounts, the new login page will present a more uniform, branded, and streamlined experience when entering a username and password. An example of the new login page can be seen [here ](/getting-started/log-into-socotra#steps). The new login page is available for existing business accounts upon request.
* Reinstatements will no longer be reapplied for out-of-sequence cancellations, yielding more intuitive results in the vast majority of real-world scenarios, such as flat cancellations. Following this change, users will need to manually create and issue any reinstatements required after issuing an out-of-sequence cancellation.
* New fields have been added to the `InvoiceDetailsResponse` object: `settledTime` and `unsettledTime`.

Bug Fixes [#bug-fixes-14]

{/* KERN-7546 */}

* Fixed an issue that caused a server error when refusing a renewal transaction.

March 18, 2026 [#march-18-2026]

New Features: Workgroups, Auto-Assign, and Workplans [#new-features-workgroups-auto-assign-and-workplans]

* [Workgroups](/features/work-management/workgroups) are hierarchical groupings of tasks, users, and entities such as quotes and policies.
* [Auto-Assign](/features/work-management/workgroups#AutoAssign) automatically assigns tasks and creates associations.
* [Workplans](/features/work-management/workplans) are templates that automatically create tasks and assign tasks in response to system events.

Data Lake Enhancements [#data-lake-enhancements-5]

* The `group_locator` field in the [Data Lake](/features/reporting/datalake) [quotes](/features/reporting/tables#quotes) table has been updated from `non-nullable` to `nullable` to support an upcoming feature, and two new fields `invoice_fee_amount` and `anonymized_time_utc` have been added, resulting in the regeneration of all historical data in the table.
* A fix for an issue preventing subpayments from being reflected in the [Data Lake](/features/reporting/datalake) [payments](/features/reporting/tables#payments) and [payment\_data\_extensions](/features/reporting/tables#payment_data_extensions) tables has been released, resulting in the regeneration of all historical data in both tables.

Bug Fixes [#bug-fixes-15]

{/* KERN-7008 */}

* Fixed an issue that prevented transaction locators from appearing for flat charges when viewing invoices.

March 11, 2026 [#march-11-2026]

New Feature: Socotra Assistant [#new-feature-socotra-assistant]

The Socotra Assistant is an AI-powered agent that automates the underwriting workflow within the Operations Workbench and performs tasks such as extracting data from documents, checking for missing or invalid data, and generating underwriting insights.

See the [Socotra Assistant](/ai-guide/assistant/overview) feature guide for more information.

UI Enhancements [#ui-enhancements-1]

The work management dashboard now displays a link to view all tasks if no tasks are assigned to you.

Data Lake Enhancements [#data-lake-enhancements-6]

* New [Data Lake](/features/reporting/datalake) tables are now available for [affected\_transactions](/features/reporting/tables#affected_transactions) and [installment\_settings](/features/reporting/tables#installment_settings).
* A performance fix was made to the [quote\_element\_tree](/features/reporting/tables#quote_element_tree) and [policy\_element\_tree](/features/reporting/tables#policy_element_tree) [Data Lake](/features/reporting/datalake) tables, resulting in the regeneration of all historical data in each table.
* The `producer_code` and `producer_code_of_record` fields were from the [Data Lake](/features/reporting/datalake) [policies](/features/reporting/tables#policies) table and added to the [segments](/features/reporting/tables#segments) table to support an upcoming feature set.
* The following fields were added to the listed [Data Lake](/features/reporting/datalake) tables, resulting in the regeneration of all historical data in each table:
  * [policies](/features/reporting/tables#policies) - `coverage_end_time_utc`, `invoice_fee_amount`, `anonymized_time_utc`
  * [segments](/features/reporting/tables#segments) - `producer_code`, `producer_code_of_record`, `anonymized_time_utc`
  * [installments](/features/reporting/tables#installments) - `installment_lattice_locator`, `installment_settings_locator`, `reversal_of_locator`, `migrated_from_locator`, `term_locator`, `autopay_time_utc`, `enhanced_by_plugin`
  * [payments](/features/reporting/tables#payments) - `payment_number`, `payment_mode`, `aggregate_payment_locator`, `reversed_by`, `retry_plan_name`, `next_request_time_utc`, `anonymized_time_utc`

March 4, 2026 [#march-4-2026]

Bug Fixes [#bug-fixes-16]

{/* KERN-7185, KERN-7454 */}

* Fixed an issue that generated an additional invoice after migration.
* Fixed an issue that caused an internal server error when validating a policy transaction.
* An incorrect data type for the `reference_locator` field in the [diaries](/features/reporting/tables#diaries) table has been fixed, resulting in the regeneration of all historical data in the table.
* An incorrect nullable indicator for the `datalake_updated_timestamp` field in the [tasks](/features/reporting/tables#tasks) table has been fixed, resulting in the regeneration of all historical data in the table.

February 25, 2026 [#february-25-2026]

Data Lake Enhancements [#data-lake-enhancements-7]

* An issue causing incorrect values for `grace_started_at` and `grace_end_at` in the [Data Lake](/features/reporting/datalake) [delinquencies](/features/reporting/tables#delinquencies) table has been fixed, resulting in the regeneration of all historical data in the table.
* New [Data Lake](/features/reporting/datalake) tables are now available for [policy\_status](/features/reporting/tables#policy_status) and [delinquency\_references](/features/reporting/tables#delinquency_references).

Config SDK Enhancements [#config-sdk-enhancements]

API client stability has been improved in Config SDK v0.6.9.

Bug Fixes [#bug-fixes-17]

{/* KERN-7438 */}

* Fixed an issue that prevented failed migrations from recovering.

February 18, 2026 [#february-18-2026]

Config SDK Enhancements [#config-sdk-enhancements-1]

The [Config SDK template ](https://github.com/socotra/config-sdk-template) has been updated to make testing easier. This version of the Config SDK template uses Config SDK v0.6.9 by default.

Data Lake Enhancements [#data-lake-enhancements-8]

The following tables have been added to [Data Lake](/features/reporting/datalake) to support reporting for the [Work Management](/features/work-management/work-management-overview) feature set:

* [tasks](/features/reporting/tables#tasks)
* [task\_references](/features/reporting/tables#task_references)
* [user\_qualifications](/features/reporting/tables#user_qualifications)
* [user\_associations](/features/reporting/tables#user_associations)
* [diaries](/features/reporting/tables#diaries)

Bug Fixes [#bug-fixes-18]

{/* KERN-7365, KERN-7293 */}

* Fixed an issue that caused a compilation error when executing the `validateConfig` and `refreshReferenceDatamodel` Gradle tasks.
* Fixed an issue that prevented the [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher) from retrieving transaction pricing data.

February 11, 2026 [#february-11-2026]

Documentation Updates [#documentation-updates-6]

* The [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot) and [Document Selection Plugin](/configuration/plugins/document-selection) feature guides have been improved as part of a rollout of updated plugin documentation.

Other Enhancements [#other-enhancements-11]

* Installment locators are now included in <ApiLink name="InvoicePreviewResponse">invoice preview responses</ApiLink>.

Bug Fixes [#bug-fixes-19]

{/* KERN-7314 */}

* Fixed an issue that resulted in incorrect invoice details after a reversal transaction.

February 4, 2026 [#february-4-2026]

Data Lake Enhancements [#data-lake-enhancements-9]

New fields have been added to [Data Lake](/features/reporting/datalake) to support [Work Management](/features/work-management/work-management-overview) reporting:

* The `task_locator` field has been added to the [policy element underwriting flags](/features/reporting/tables#policy_element_underwriting_flags) and [quote element underwriting flags](/features/reporting/tables#quote_element_underwriting_flags) tables.

Other Enhancements [#other-enhancements-12]

* The `completedAt` and `completedBy` attributes have been added to <ApiLink name="Task">Tasks</ApiLink>.
* Name length limits for configuration elements have been adjusted. See the [Configuration Deployment](/configuration/general-topics/deployment#configuration_element_name_length_limits) guide for more information.

January 28, 2026 [#january-28-2026]

Documentation Updates [#documentation-updates-7]

* The [Validation Plugin](/configuration/plugins/validation) and [Rating Plugin](/configuration/plugins/rating) feature guides have been improved as part of a rollout of updated plugin documentation.

Bug Fixes [#bug-fixes-20]

{/* KERN-7221, KERN-7188 */}

* Fixed an issue that prevented billing mode changes from taking effect.
* Fixed an issue that generated incorrect events when an invoice is settled with a credit distribution and a shortfall write-off.

January 21, 2026 [#january-21-2026]

New Feature: Jurisdictions [#new-feature-jurisdictions]

The [resource selection](/configuration/resources/versioned-resource-selection) process now automatically selects resource instances for products based on jurisdiction. See the [Jurisdictions](/features/jurisdictions) guide for more details.

Data Lake Enhancements [#data-lake-enhancements-10]

New fields have been added to [Data Lake](/features/reporting/datalake) to support an upcoming feature set:

* The `producer_code` field has been added to the [policies](/features/reporting/tables#policies) and [quotes](/features/reporting/tables#quotes) tables.
* The `producer_code_of_record` field has been added to the [policies](/features/reporting/tables#policies) table.

Other Enhancements [#other-enhancements-13]

* The [Auto-Renewal Plugin](/features/policy-management/renewal-management#auto_renewal_plugin) can now be implemented both globally and at the product level.

Bug Fixes [#bug-fixes-21]

{/* KERN-7136, KERN-7151 */}

* Fixed an issue that caused policy snapshots to display incorrect preferences.
* Fixed an issue that resulted in incorrect invoice data after a billing mode change and an [out-of-sequence](/features/policy-management/out-of-sequence-transactions) change.

January 14, 2026 [#january-14-2026]

Data Lake Enhancements [#data-lake-enhancements-11]

* The `jurisdiction` field has been added to the [policies](/features/reporting/tables#policies) and [quotes](/features/reporting/tables#quotes) tables in [Data Lake](/features/reporting/datalake) to support upcoming feature sets.
* The `static_locator` and `reapplication_of_locator` fields have been added to the [transactions](/features/reporting/tables#transactions) table in [Data Lake](/features/reporting/datalake).

Bug Fixes [#bug-fixes-22]

{/* KERN-7001, KERN-7005 */}

* Fixed an issue that applied billing mode changes to the wrong billing period.
* Fixed an issue that caused the due time of certain invoices to be unintentionally backdated when the billing mode is modified.

January 8, 2026 [#january-8-2026]

Data Lake Enhancements [#data-lake-enhancements-12]

* New [Data Lake](/features/reporting/datalake) tables are now available for [ledger account line items](/features/reporting/tables#ledger_account_line_items) and [financial transaction account lines](/features/reporting/tables#fa_transaction_account_lines).

Bug Fixes [#bug-fixes-23]

{/* KERN-7086, KERN-7087, KERN-7040, KERN-6982 */}

* Fixed an issue that caused invoices to be generated multiple times for the same billing period.
* Fixed an issue with automatic credit distribution when the billing mode is modified.
* Fixed an issue that prevented surcharges from appearing in invoices displayed in the Operations Workbench.
* Fixed an issue with the Installments Plugin that caused an incorrect due date to appear in invoices.

December 17, 2025 [#december-17-2025]

Transaction Charge Bundling [#transaction-charge-bundling]

Flat and retention charges with `next` invoicing can now be bundled with invoices corresponding to a specific transaction. When bundling is enabled, charges will be billed on the next invoice with installments originating from the specified transaction, ensuring transaction-related fees are invoiced together. See the transaction bundling guides for [flat](/features/billing/flat-charges#transaction_flat_charge_bundling) and [retention](/features/billing/retention-charges#transaction_retention_charge_bundling) charges for more details.

API Updates [#api-updates]

* The `recordCount` and `md5HashSum` fields have been added to the <ApiLink name="DeltaFile" /> object to assist with the reconciliation of [delta files](/features/reporting/delta-files).

<Callout>
  This is the final 2025 release. There will be no release on December 24, and no release the following week (December 31). The next release will be available on Thursday, January 8.
</Callout>

December 10, 2025 [#december-10-2025]

Moratoriums Reporting Updates [#moratoriums-reporting-updates]

The following updates have been made to Moratoriums reporting in Data Lake and Delta Files:

* The `is_deleted` field has been removed from the `moratorium_statuses` table. This table now reflects the status of any policy or quote, rather than only those eligible for Moratoriums.
* Delta Files now include three separate `transformationTable` values for Moratoriums (`DataLakeMoratoriums`, `DataLakeMoratoriumStatuses`, `DataLakeMoratoriumElections`), rather than a single value (`DataLakeMoratoriumReports`).

Documentation Updates [#documentation-updates-8]

* New documentation has been created for the [Range Tables](/configuration/resources/range-tables) feature. Range Tables provide range-based and interpolated table lookup capabilities.
* The [Precommit Plugin](/configuration/plugins/precommit) feature guide has been improved as part of a rollout of updated plugin documentation. Keep an eye out for more improvements to our plugin documentation over the course of the next few releases.

December 3, 2025 [#december-3-2025]

New Feature: Tenant Roles [#new-feature-tenant-roles]

Tenant roles allow admins to grant tenant-specific permissions to users. See the [Tenant Roles](/features/security/roles-and-permissions#tenant_roles) guide for more details.

API Updates [#api-updates-1]

* Failed billing jobs can now be retried using the <ApiLink name="retryFailedTransactions">Retry Failed Transactions</ApiLink> API endpoint. See the [Installment Lattices](/features/billing/installments-and-installment-lattices#retrying_failed_billing_jobs) guide for more details.

Other Enhancements [#other-enhancements-14]

* [Delta files](/features/reporting/delta-files) are now available in CSV format, providing more seamless ingestion into data warehouses.
* [Data Lake](/features/reporting/datalake) tables are now available for ledger accounts and financial accounting transactions.

Bug Fixes [#bug-fixes-24]

{/* KERN-6511 */}

* Fixed an issue that prevented the <ApiLink name="fetchInvoiceDetails">Fetch Invoice Details</ApiLink> API endpoint from returning `elementType`.

November 19, 2025 [#november-19-2025]

Config SDK Upgrade Requirement [#config-sdk-upgrade-requirement]

Config SDK developers are now required to upgrade to the latest [Config SDK release (v0.6.8) ](https://github.com/socotra/config-sdk-template/packages/2234611) and Java 21.

API Updates [#api-updates-2]

* The `excludeRetired` and `excludeActive` filtering options are now available when calling the <ApiLink name="fetchResourceGroups">Fetch all Resource Groups</ApiLink> API endpoint.

<Callout>
  There will be no release on November 26. The next release will be available on Wednesday, December 3.
</Callout>

November 12, 2025 [#november-12-2025]

New Feature: Automation Plugin (Beta) [#new-feature-automation-plugin-beta]

The Automation Plugin is a new feature that allows you to implement custom business logic, create your own Socotra API endpoints, define request and response objects, and send HTTP requests to both third-party and Socotra API endpoints. See the [Automation Plugin](/configuration/plugins/automation) guide for more details.

API Updates [#api-updates-3]

* New endpoints have been added to the Events API to support the management of [failed scheduled events](/api/events/events).
* A new endpoint has been added to the Documents API to support <ApiLink name="fetchDocumentsForTerm">fetching documents by term</ApiLink>.

Other Enhancements [#other-enhancements-15]

* The `AccountMigrationRequest` entity now includes the `AccountingMigrationRequest` field to support the <ApiLink name="AccountMigrationRequest">migration</ApiLink> of account balances.
* The `staticLocator` field has been added to <ApiLink name="PolicyTransactionResponse">policy transactions</ApiLink>. The `staticLocator` field refers to the locator of the original transaction and will remain unchanged for a policy transaction, even when a policy transaction is reversed and reapplied.
* The getTermSubsegmentSummaries() method has been added to the [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher), allowing users to view a summary for each segment in a term.

<Callout type="warn">
  **Upcoming Config SDK Upgrade Required:** As previously mentioned, we are targeting the release of November 19th to upgrade our services from Java 17 to Java 21. To ensure compatibility, all developers must upgrade to the latest [Config SDK release (v0.6.8) ](https://github.com/socotra/config-sdk-template/packages/2234611) and update their local environments to Java 21 by this date.
</Callout>

November 5, 2025 [#november-5-2025]

Documentation Updates [#documentation-updates-9]

* New documentation has been created for [service accounts](/features/security/authentication#service_accounts). Service accounts are used by software integrations to access Socotra API endpoints using [Personal Access Tokens (PATs)](/features/security/personal-access-tokens).
* Our feature guide on [First Notice of Loss (“FNOL”)](/features/claims/fnol) has been updated to clarify that an FNOL in the `onClaim` state will revert to the `validated` state if any of its data is modified.

Bug Fixes [#bug-fixes-25]

{/* KERN-6738 */}

* Fixed an issue that prevented Fivetran from recognizing data lake tables that use an unsupported format for primary keys.

<Callout type="warn">
  **Upcoming Config SDK Upgrade Required:** As previously mentioned, we are targeting the release of November 19th to upgrade our services from Java 17 to Java 21. To ensure compatibility, all developers must upgrade to the latest [Config SDK release (v0.6.8) ](https://github.com/socotra/config-sdk-template/packages/2234611) and update their local environments to Java 21 by this date.
</Callout>

October 29, 2025 [#october-29-2025]

Bug Fixes [#bug-fixes-26]

{/* KERN-6655 */}

* Fixed an issue that caused previously invoiced installments to appear in <ApiLink name="previewInvoicesForTransaction">invoice previews</ApiLink> for [migrated](/features/migration) policies.

<Callout type="warn">
  **Upcoming Config SDK Upgrade Required:** As previously mentioned, we are targeting the release of November 19th to upgrade our services from Java 17 to Java 21. To ensure compatibility, all developers must upgrade to the latest [Config SDK release (v0.6.8) ](https://github.com/socotra/config-sdk-template/packages/2234611) and update their local environments to Java 21 by this date.
</Callout>

October 22, 2025 [#october-22-2025]

Cancellation Plugin [#cancellation-plugin]

The new [Cancellation Plugin](/configuration/plugins/cancellation) allows adjustments to the amount retained at policy cancellation through the creation of [retention charges](/features/billing/retention-charges). This supports enforcement of minimum earned premium plans, short-rate penalties, and other fees or refunds according to custom business rules at cancellation.

New Data Security Features (Beta) [#new-data-security-features-beta]

The new [Data Access Controls](/features/security/data-access-controls), [Data Masking](/features/security/data-masking), and [Data Anonymization](/features/security/data-anonymization) features provide enhanced capabilities for managing sensitive data, allowing admins to control field-level and entity-level access by user role, redact sensitive data in responses and UI, and anonymize data for analytics and compliance. See the [Security Feature Guide](/features/security/security-overview) for details.

As part of this release, the existing [Data Access Controls APIs](/api/configuration-and-development/data-access-controls) have been deprecated and replaced with the new [Data Access APIs](/api/configuration-and-development/data-access).

Service Accounts [#service-accounts]

A service account is a new type of user enabling secure, programmatic API access. Service accounts have no login credentials and authenticate using Personal Access Tokens (PATs).

Admins create service accounts by setting the `serviceAccount` boolean in the <ApiLink name="UserCreateRequest" /> to `true`, then generate PATs for them using the new <ApiLink name="createServiceAccountAuthToken" /> API.

Delta File Generation Schedule Update [#delta-file-generation-schedule-update]

Delta files are now generated at most once every two hours following Data Lake updates, rather than immediately after each update. If an update occurs within two hours of the previous delta file generation, the system will generate the next set once the interval has elapsed. See the [Delta File](/features/reporting/delta-files) guide for details.

Bug Fixes [#bug-fixes-27]

{/* KERN-6658 */}

* Fixed an issue that caused redeployments to fail when an extension data field was changed from optional to required with a `defaultValue` specified.

<Callout type="warn">
  **Upcoming Config SDK Upgrade Required:** We are targeting the release of November 19th to upgrade our services from Java 17 to Java 21. To ensure compatibility, all developers must upgrade to the latest [Config SDK release (v0.6.8) ](https://github.com/socotra/config-sdk-template/packages/2234611) and update their local environments to Java 21 by this date.
</Callout>

October 15, 2025 [#october-15-2025]

Search Enhancements for Entity Numbers [#search-enhancements-for-entity-numbers]

Search requests for [entity numbers](/configuration/general-topics/entity-numbering) now offer improved flexibility and discoverability. Non-alphanumeric symbols are now ignored during entity number searches, allowing users to search with or without symbols. For example, searches for `PA-000001` or `PA000001` will return the same results. In addition, relevancy scores for entity number matches are now boosted to ensure they appear prominently in search results.

See the [Search](/features/search) feature guide for more information.

<Callout>
  Search requests must now use `entity_number` as the `fieldName` for all entity number search requests, regardless of entity type. To maintain compatibility, update any entity number search implementations to use the new syntax. For example, `policy_number:PA-000001` or `quote_number:PA-000001` must be updated to `entity_number:PA-000001`.
</Callout>

Data Lake Consolidated Schema [#data-lake-consolidated-schema]

A consolidated schema containing data for all tenants within the business account is now available as an option to users when enabling Data Lake. See the [Data Lake](/features/reporting/datalake) guide for details.

Other Enhancements [#other-enhancements-16]

* [Diary](/features/work-management/diaries) records may now be accessed from within plugins using the [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher) `getDiaries()` method.
* [Subpayments](/api/billing/payments) within an aggregate payment may now be applied directly to invoice items by setting the `containerType` of any `CreditItem` in its `targets` to `invoiceItem`.
* [Billing Holds](/features/billing/billing-holds) now emit events throughout their life cycle. See the [Event Definitions](/configuration/general-topics/event-definitions) page for more information.

Bug Fixes [#bug-fixes-28]

{/* KERN-6543 */}

* Underwriting flags can no longer be added to transactions in terminal states.

October 8, 2025 [#october-8-2025]

Moratoriums Reporting [#moratoriums-reporting]

[Data Lake](/features/reporting/datalake) now includes [Moratoriums](/features/moratoriums/moratoriums) tables containing moratorium details, quote and policy opt-in and opt-out records, and lists of affected quotes and policies.

Bug Fixes [#bug-fixes-29]

{/* KERN-6513, KERN-6509, KERN-6094 */}

* Fixed an issue where the `originalEffectiveTime` on migrated policies incorrectly updated to the latest renewal date.
* Migration payloads containing more than one issuance transaction will no longer pass validation.
* Fixed an issue where issuance transaction invoice previews failed to generate for migrated policies.

October 1, 2025 [#october-1-2025]

Config SDK Enhancements [#config-sdk-enhancements-2]

A new [Config SDK release (v0.6.8) ](https://github.com/socotra/config-sdk-template/packages/2234611) includes the following updates:

* A new `createArchive` task that creates a deployable configuration archive for deployment.
* Support for [bootstrap resources](/configuration/general-topics/bootstrap) in the `socotra-config`.
* Fixed a bug in the `uploadBundleAndBuild` auxiliary task that could cause config deployment attempts to fail.

`createArchive` has been introduced as a convenience since it is no longer expected to have a `plugins` directory under `socotra-config`; instead, canonical plugin code continues to live under `src/`. All Config SDK tasks pulling deployed configs will automatically place the plugin code in `src/` exclusively, and will use code from that directory whenever creating an archive for deployment. If you wish to create a config for deployment, we recommend using `createArchive` instead of manually copying files from `src/` and `socotra-config`.

The [Config SDK template ](https://github.com/socotra/config-sdk-template) has been updated to pull `v0.6.8` by default. **Java 21, not 17, is now required to use the Config SDK**.

See the [Configuration SDK Guide](/configuration/general-topics/configuration-sdk) for details.

Other Enhancements [#other-enhancements-17]

* The [Payment Execution Service](/features/billing/payment-execution-service) now supports Stripe as a payment provider.
* Fields may now be rendered in the UI as visible but not editable using the `readOnly` tag. See the [Rendering Customizations](/ui-sdk/components/rendering-customizations) guide for details.
* The [Credit Distributions](/api/billing/credit-distribution) entity is now available in [Data Lake](/features/reporting/datalake).
* <ApiLink name="EarlyInvoicingResponse" /> now contains a
  `candidateInstallmentsCount` property that shows the number of candidate
  installments intended to be invoiced.

September 24, 2025 [#september-24-2025]

Underwriting Flag Enhancements [#underwriting-flag-enhancements]

New granular permissions and corresponding APIs enable users to create or clear individual underwriting flags of each level (`block`, `decline`, `reject`, `approve`, and `info`) for [Quotes](/api/quotes/quotes) and [Transactions](/api/policy-management/policy-transactions).
Each permission for adding or clearing underwriting flags has its own API endpoint requiring the corresponding permission.

UI Customizations [#ui-customizations]

The new <ApiLink name="DisplayHintsRef">Display Hints</ApiLink> entity supports UI customization of names and ordering for <ApiLink name="CoverageTermOptionRef">Coverage Term Options</ApiLink> and <ApiLink name="TransactionTypeRef">Transaction Types</ApiLink> through the `displayName` and `displayOrder` attributes. This entity will be proliferated to other configuration entities in future releases.

Bug Fixes [#bug-fixes-30]

{/* KERN-6349 */}

* Fixed an issue where flat charges added to invoices via the <ApiLink name="addCharges" /> API with a `policyLocator` specified in the request were incorrectly applied within the account.

September 17, 2025 [#september-17-2025]

New Feature: Moratoriums (BETA) [#new-feature-moratoriums-beta]

Moratoriums is a new feature that enables the temporary suspension of certain policy and billing operations across a designated group of policies, supporting compliance with regulatory or business requirements. See the [Moratoriums Guide](/features/moratoriums/moratoriums) for details.

New Feature: Socotra MCP Server [#new-feature-socotra-mcp-server]

Socotra's new MCP server unlocks automated workflows and AI-powered operations for users by enabling quick and secure integrations of their Socotra Insurance Suite business accounts with AI applications. See the [MCP Server Guide](/ai-guide/mcp-server/overview) for details.

Contact your Socotra representative to request access to the MCP Server for your business account.

Notice: Payment Execution Service Changes [#notice-payment-execution-service-changes]

We are making breaking changes to the recently released [Payment Execution Service APIs](/api/billing/payment-execution) to ensure a more consistent and flexible design moving forward.

* The <ApiLink name="fetchPaymentProviderConfiguration" />, <ApiLink name="updatePaymentProviderConfiguration" />, and <ApiLink name="inactivatePaymentProviderConfiguration" /> endpoints now use a `paymentProviderLocator` in the URL instead of `paymentProvider`. These endpoints return a <ApiLink name="PaymentProvider" /> object with the following properties: `locator`, `paymentServiceProvider`, and `paymentProviderState`.
* The <ApiLink name="FinancialInstrumentConfigurationRequest" /> and <ApiLink name="FinancialInstrumentConfigurationResponse" /> objects for the <ApiLink name="fetchPaymentExecutionConfigurationForFinancialInstrument" />, <ApiLink name="addPaymentExecutionConfigurationForFinancialInstrument" />, and <ApiLink name="updatePaymentExecutionConfigurationForFinancialInstrument" /> endpoints now use `paymentServiceProvider` instead of `paymentProviderLocator`.

Other Enhancements [#other-enhancements-18]

{/* KERN-6380, 6292, 6270 */}

* More granular permissions (`validate`, `price`, `underwrite`, `accept`, and `issue`) are available for the corresponding [Quote](/api/quotes/quotes) and [Transaction](/api/policy-management/policy-transactions) lifecycle endpoints.
* Search performance has been significantly improved for data extension fields and numbering plan values.
* [Payments](/api/billing/payments) may be applied directly to invoice items by setting the `containerType` of any `CreditItem` in its `targets` to `invoiceItem`. The ability to apply subpayments directly to invoice items as part of aggregate payments will be included in a future release.

September 10, 2025 [#september-10-2025]

Data Lake Enhancements [#data-lake-enhancements-13]

As previously announced, this release introduces [Data Lake](/features/reporting/datalake) improvements. Key changes include:

* **Multi-Tenant Schema**: Added a `tenant_locator` field to all tables and created new composite primary keys that combine the tenant locator with existing keys to enable future consolidated reporting across multiple Business Account tenants.

* **Soft Deletion**: Introduced soft deletion capability with a new `deleted` field on tables subject to record deletion, improving change management and enabling future support for additional [Delta File](/features/reporting/delta-files) formats like CSV.

* **Enhanced Change Detection**: Added an index to the `datalake_updated_timestamp` field for more efficient change detection and data ingestion.

* **Improved Data Extension Keys**: Replaced auto-increment `id` primary keys with composite keys (tenant locator + entity locator + hashed field name) to ensure unique record identification and accurate updates.

Documentation Updates [#documentation-updates-10]

* The [Underwriting Plugin guide](/configuration/plugins/underwriting) has been enhanced to include comprehensive best practices for interpreting, adding, and clearing underwriting flags via the plugin.

Bug Fixes [#bug-fixes-31]

{/* KERN-6270 */}

* The `issuedTime` on a migrated transaction will now be set to the value from the <ApiLink name="TransactionMigrationRequest" /> when provided, defaulting to the segment `startTime` only when the transaction `issuedTime` is not specified in the request.

September 4, 2025 [#september-4-2025]

New Features: Autopay and Payment Execution Service [#new-features-autopay-and-payment-execution-service]

The new [Autopay](/features/billing/autopay) and [Payment Execution Service](/features/billing/payment-execution-service) feature set streamlines payment workflows by enabling automated generation of payment requests and execution through third-party payment providers.
In addition, our [Security Topic](/features/security/security-overview) now includes a [PCI Compliance Statement](/features/security/pci-compliance-statement) outlining Socotra's position on PCI Compliance.

Other Changes [#other-changes]

* The Preview Invoices endpoints for <ApiLink name="previewInvoicesForQuote">Quotes</ApiLink>, <ApiLink name="previewInvoicesForStatelessQuote">Stateless Quotes</ApiLink>, and <ApiLink name="previewInvoicesForTransaction">Transactions</ApiLink> now include a `count` query parameter to request the number of invoices to preview.
* The [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot) is now called for documents configured with a `rendering` value of `prerendered`, allowing the metadata of the given document instance to be set programmatically.

Upcoming Data Lake Enhancements [#upcoming-data-lake-enhancements]

As previously announced, the next release on September 10th includes [Data Lake](/features/reporting/datalake) improvements that will require a period of downtime and data regeneration for this feature set. Key changes include:

* **Multi-Tenant Schema**: Adding a `tenant_locator` field to all tables and creating new composite primary keys that combine the tenant locator with existing keys to enable future consolidated reporting across multiple Business Account tenants.

* **Soft Deletion**: Introducing soft deletion capability with a new `deleted` field on tables subject to record deletion, improving change management and enabling future support for additional [Delta File](/features/reporting/delta-files) formats like CSV.

* **Enhanced Change Detection**: Adding an index to the `datalake_updated_timestamp` field for more efficient change detection and data ingestion.

* **Improved Data Extension Keys**: Replacing auto-increment `id` primary keys with composite keys (tenant locator + entity locator + hashed field name) to ensure unique record identification and accurate updates.

Bug Fixes [#bug-fixes-32]

{/* KERN-6294 */}

* Fixed an issue where installments were not generated when renewal transactions were reapplied after out-of-sequence endorsements.

August 27, 2025 [#august-27-2025]

Feature Enhancement: Target End State for Excess Credit Distributions [#feature-enhancement-target-end-state-for-excess-credit-distributions]

This enhancement enables custom workflows before execution of automatic distributions of excess funds by allowing users to specify a target end state for system-generated disbursements via the new `advanceDisbursementTo` property. See the [Excess Credits Guide](/features/billing/excess-credits) for details.

New Data Lake Entities [#new-data-lake-entities]

Data Lake tables are now available for installment items, credit items, and aux data. See the [Data Lake Guide](/features/reporting/datalake) for details.

Security Documentation Update [#security-documentation-update]

Our [security documentation](/features/security/security-overview) has been expanded and reorganized to provide clear, comprehensive, and user-friendly guides on security management within the Socotra Insurance Suite and your own applications.

Bug Fixes [#bug-fixes-33]

{/* KERN-6140, KERN-5979, KERN-6163, KERN-6117, KERN-5863 */}

* Fixed an issue where plugins failed to create tasks that set blocking underwriting flags.
* Negative invoice items are now settled immediately upon invoice generation.
* Plugins can now create coverages without an assigned locator by assigning a system-generated ULID locator.
* Resolved a syntax error in the `DataLakePolicyCoverageTerms` Data Lake transformation table.
* Prevented generation of empty consolidated documents when no subdocuments are available.

<Callout>
  **Upcoming Data Lake Changes:** The previously announced enhancements to Data Lake are scheduled for the release of September 10th. Individual customer communications are ongoing, please reach out to your Socotra representative if more details are needed.
</Callout>

August 20, 2025 [#august-20-2025]

*Internal changes only for this release.*

API Docs Cleanup [#api-docs-cleanup]

References to the previously deprecated `billingTrigger` have been removed from the API documentation, including the `BillingTriggerUpdateRequest` entity and the `updatePolicyBillingTrigger` endpoint.

<Callout>
  **Upcoming Data Lake Changes:** The previously announced enhancements to Data Lake are now scheduled for the release of September 10th. Individual customer communications are ongoing, please reach out to your Socotra representative if more details are needed.
</Callout>

August 13, 2025 [#august-13-2025]

New Feature: Auto Credit Application [#new-feature-auto-credit-application]

The new [Auto Credit Application](/features/billing/auto-credit-application) feature allows for automatic application of excess account credit balances to open invoices, streamlining the billing process. This feature is enabled by default for new accounts and can be configured per account.

August 6, 2025 [#august-6-2025]

Config Validation Requirement [#config-validation-requirement]

A longstanding configuration requirement is that Custom Data Types must be defined in `CamelCase`. It is now also a requirement that when such data types are referenced in the configuration, they must exactly match the defined name. This change will impact only new configuration deployments and redeployments; existing deployed tenant configurations will continue to function. See the section on [Configuration Case Sensitivity](/configuration/general-topics/deployment#configuration-case-sensitivity) for a complete overview.

Quote and Transaction Reset Clarification [#quote-and-transaction-reset-clarification]

We have updated the [quote](/features/policy-quotation/quotes#quote-reset) and [transaction](/features/policy-management/policy-transactions#trx-reset) flow overviews to clarify that quote and transactions in the `accepted` state must first be `refused` before they can be reset.

Bug Fixes [#bug-fixes-34]

{/* KERN-5925 & KERN-5926 */}

* Addressed a rounding issue leading to charge amounts in the <ApiLink name="fetchTermSummaryByTermNumber">Term Summary</ApiLink> API to be some pennies off.
* Addressed a related issue where flat charges were prorated across segments in the same <ApiLink name="fetchTermSummaryByTermNumber">Term Summary</ApiLink> API.

<Callout>
  **Upcoming Data Lake Changes:** Some upcoming enhancements to Data Lake, targeted for the August 27th release, will require some downtime and a data regeneration period for that feature set. Your Socotra representative will be in touch with more details, and we will post further details ahead of the release.
</Callout>

July 30, 2025 [#july-30-2025]

New Feature: Schedules (BETA) [#new-feature-schedules-beta]

Schedules is a new feature that supports the efficient creation, rating and management of very large list of like-typed items, which can be used in various contexts such as policy transactions and quotes. See the [Schedules Guide](/features/schedules) for details.

Feature Enhancement: Granular Write Offs [#feature-enhancement-granular-write-offs]

This enhancement to the existing invoice write-off functionality allows users to write off specific invoice items or partial amounts, rather than only the remaining balance of the invoice. See the [Write-Offs Guide](/features/billing/write-offs) for details.

Open API Response Name Change [#open-api-response-name-change]

The response name in the [Open API definition file](/other-resources/open-api-specification) has been updated from `InstallmentInternal` to `Installment` for the following endpoints: <ApiLink name="fetchInstallmentsForQuote" />, <ApiLink name="fetchInstallmentsForPolicy" />, and <ApiLink name="fetchInstallmentsForPolicyTransaction" />.

Bug Fixes [#bug-fixes-35]

{/* KERN-5905 */}

* Fixed a bug where reinstated policies were still reflecting a policy status of `cancelled`.

<Callout>
  **Upcoming Data Lake Changes:** Some upcoming enhancements to Data Lake, targeted for the release of August 27th 2025, will include some downtime and a data regeneration period for that feature set. Your Socotra representative will be in touch with more details, and we will post further details ahead of the release.
</Callout>

July 23, 2025 [#july-23-2025]

Billing Preview for Stateless Quotes [#billing-preview-for-stateless-quotes]

A preview of prospective installments or invoices may now be generated for hypothetical quotes. See the [Previews Guide](/features/preview-operations) for more information.

Notice: Upcoming Open API Response Name Change [#notice-upcoming-open-api-response-name-change]

In the forthcoming release on July 30, 2025, the response name in the [Open API definition file](/other-resources/open-api-specification) will be updated from `InstallmentInternal` to `Installment` for the following endpoints: <ApiLink name="fetchInstallmentsForQuote" />, <ApiLink name="fetchInstallmentsForPolicy" />, and <ApiLink name="fetchInstallmentsForPolicyTransaction" />.

Bug Fixes [#bug-fixes-36]

{/* KERN-5856, KERN-5788 */}

* Fixed a bug that prevented the update of loss information on a validated FNOL.
* Fixed a bug that caused an error when distributing very small amounts across many installments (e.g., 0.5 over 200) by assigning that amount to the first installment.

July 16, 2025 [#july-16-2025]

Installments Plugin [#installments-plugin]

The new [Installments Plugin](/configuration/plugins/installments) allows for more flexible installment scheduling, enabling the creation of installments at times that do not align with the current [Installment Lattice](/features/billing/installments-and-installment-lattices).

Migration Client Release and Updated Guidance [#migration-client-release-and-updated-guidance]

* A new version of the [Migration Client](/features/migration#migration-client) is available to download from the [config-sdk template package index ](https://github.com/socotra/config-sdk-template/packages/2312294), featuring improved retry logic and updated configuration template.
* The [Migration Guide](/features/migration) now includes a complete tutorial, along with an overview and tutorial specific to the Migration Client. These resources make use of our new [migration-tutorial ](https://github.com/socotra/migration-tutorial) repository, which includes assets necessary to get hands-on with a full end-to-end migration.

New Task Creation Methods [#new-task-creation-methods]

Tasks can now be created through Underwriting Flag creation and plugin execution. See the [Tasks Guide](/features/work-management/tasks) for more details.

July 9, 2025 [#july-9-2025]

New Feature: Custom Scheduled Events [#new-feature-custom-scheduled-events]

Custom events can now be scheduled to run at specified times or intervals and paired with webhooks to initiate workflows. See the [Custom Scheduled Events Guide](/configuration/general-topics/scheduled-events) for details.

New Feature: Policy Holds [#new-feature-policy-holds]

Policy holds can now be defined to prevent the processing of policy transactions. See the [Policy Holds Guide](/features/policy-management/policy-holds) for details.

Documentation Updates [#documentation-updates-11]

The [UI SDK documentation](/ui-sdk) now includes details of the [DataPropertyForm](/ui-sdk/components/data-property-form) component.

Notice: Autoclean of Abandoned Tenants Introduced to Sandbox [#notice-autoclean-of-abandoned-tenants-introduced-to-sandbox]

In order to maintain a clean and efficient environment, this release introduces an automated cleanup process to retire inactive tenants in sandbox.
Any tenants without plugin activity in the past 30 days will be considered inactive and subsequently retired, and the 30 day clock begins today.

For tenants that require an exception from this process, please contact your Socotra representative.

July 2, 2025 [#july-2-2025]

Deprecation: Quote Delinquency Reference [#deprecation-quote-delinquency-reference]

New delinquencies will no longer include a <ApiLink name="DelinquencyReference" /> with `referenceType` of `quote`, and the `getDelinquenciesForQuote` endpoint is now deprecated. Existing delinquencies with a `quote` reference will remain retrievable.

June 25, 2025 [#june-25-2025]

Documentation Updates [#documentation-updates-12]

* The [Events Guide](/configuration/general-topics/events) now includes details on [defining and emitting custom events](/configuration/general-topics/events#custom-events).

Notice: Autoclean of Abandoned Tenants to be Introduced to Sandbox [#notice-autoclean-of-abandoned-tenants-to-be-introduced-to-sandbox]

In order to maintain a clean and efficient environment, the forthcoming release of July 9, 2025 will introduce an automated cleanup process to retire inactive tenants.
Any tenants without plugin activity in the past 30 days will be considered inactive and subsequently retired, and the 30 day clock will start July 9, 2025.

For tenants that require an exception from this process, please contact your Socotra representative.

Bug Fixes [#bug-fixes-37]

{/* KERN-5599 */}

* Fixed a bug where <ApiLink name="getFnolByNumber">fetching FNOL</ApiLink> by entity number did not return all data for the entity.

June 18, 2025 [#june-18-2025]

New Work Management Feature Set [#new-work-management-feature-set]

Introducing the first release of Socotra's major new Work Management feature set, which supports associations between users and entities such as accounts and quotes, and the ability to assign users specific tasks. See the [Work Management Guide](/features/work-management/work-management-overview) for more details.

Numbering Support for New Entity Types [#numbering-support-for-new-entity-types]

You can now configure automatic numbering for the following new entity types:

* Payments
* Tasks

Cancellation at Existing Policy End Time [#cancellation-at-existing-policy-end-time]

The system now supports a cancellation transaction effective time that matches the policy's existing end time, which is useful to distinguish between policies that were explicitly cancelled versus those allowed to expire.

Other Enhancements [#other-enhancements-19]

* `createdAt` and `createdBy` properties will now be returned in the <ApiLink name="QuoteResponse" />
* The system now supports change instructions as part of a reinstatement transaction, allowing reinstatement of a policy with changes to coverages or other data. See the <ApiLink name="reinstatePolicy" /> endpoint for details.
* You can now fetch the invoices associated with a payment that was later reversed, using the `includeReversed` query parameter on the <ApiLink name="fetchInvoicesTargetedByAPayment" /> endpoint.

Bug Fixes [#bug-fixes-38]

{/* KERN-5573 */}

* Fixed a bug where `defaultRegion` was not being applied on Quote validation

June 11, 2025 [#june-11-2025]

New Document Features: Snippets and Custom Fonts [#new-document-features-snippets-and-custom-fonts]

You can now configure reusable content for inclusion in documents, and have custom typefaces. See the [Dynamic Documents Guide](/features/documents/dynamic-documents) for details.

New Data Lake Entities: Claims [#new-data-lake-entities-claims]

Data Lake has been expanded to include information about claims and related FNOL entities. See the [Data Lake Guide](/features/reporting/datalake) for details.

Documentation Updates [#documentation-updates-13]

* The [UI SDK documentation](/ui-sdk) has been extensively revised and brought up-to-date with current capabilities.
* The [Coverage Checks Feature Guide](/features/claims/coverage-checks) details coverage check functionality for [first notice of loss ("FNOL")](/features/claims/fnol).
* The document consolidation feature now has [its own expanded guide](/features/documents/document-consolidation).
* A new Feature Guide is available for [Payment Shortfall Handling](/features/billing/payment-shortfall-handling), which helps settle invoices that have minimal remainder amounts after payments are applied.

June 4, 2025 [#june-4-2025]

Bug Fixes [#bug-fixes-39]

{/* KERN-5530, KERN-545 */}

* Introducing a `numberingString` in a <ApiLink name="RegionRef" /> configuration is now a [safe](/configuration/general-topics/redeployment#redeployment_safety) deployment change.
* Copied quotes will now have a [number](/configuration/general-topics/entity-numbering) assigned if the governing `numberingTrigger` is `creation`.

May 28, 2025 [#may-28-2025]

Bug Fix: FNOL Numbering [#bug-fix-fnol-numbering]

{/* KERN-5424 */}

Fixed a bug preventing the automatic generation of a [number](/configuration/general-topics/entity-numbering) for an FNOL when `autoValidate` is `true`.

May 21, 2025 [#may-21-2025]

Search Summary Enhancement [#search-summary-enhancement]

You can now supply a set of strings in the `fields` array of a <ApiLink name="SearchRequest" />, which will cause the `searchSummary` map in the <ApiLink name="SearchResultResponse" /> to be populated with fields matching a string in the array, along with the associated value.

See the [Field Augmentation section of the Search Guide](/features/search#search-request-fields) for details.

Bug Fix: Document Consolidation [#bug-fix-document-consolidation]

{/* KERN-5395 */}

A consolidated document will still be produced if one or more of its sub-documents are unavailable, with the consolidated document simply omitting such sub-documents. This can occur if the [Document Selection Plugin](/configuration/plugins/document-selection) skips generation of some documents.

May 14, 2025 [#may-14-2025]

Policy Locators in Billing Events [#policy-locators-in-billing-events]

Billing events now include associated `policyLocators`, given as an array that will include up to 5 relevant policies and a `listCompleted` indicator. See the ["Payloads" section of the Events Guide](/configuration/general-topics/events#event-payloads) for details. You can see the complete listing of events and associated payloads on the [Event Definitions](/configuration/general-topics/event-definitions) page.

Bug Fixes [#bug-fixes-40]

{/* KERN-5404, KERN-5320 */}

* Updated excess credit handling to behave as expected when encountering one or more partially-paid invoices.
* Fixed a bug causing existing `auxDataSettings` to be wiped out when redeploying a partial configuration with no `auxDataSettings`.

May 7, 2025 [#may-7-2025]

New Feature: Invoice Fees [#new-feature-invoice-fees]

Invoice fees make it easy to configure the automatic addition of a flat charge to invoices. See the [Invoice Fees](/features/billing/invoicing#invoice-fees) section of the [Invoicing Guide](/features/billing/invoicing) for details.

New Diary Associations [#new-diary-associations]

[Diary entries](/features/work-management/diaries) can now be linked to underwriting flags, accounts, and invoices.

Update: Numbering [#update-numbering]

Entity numbers can now be assigned to accounts and quotes on creation.

April 30, 2025 [#april-30-2025]

New Feature: Document Consolidation [#new-feature-document-consolidation]

With document consolidation, you can configure an assemblage of documents to be produced as single unit. See the [Documents Guide](/configuration/resources/documents) for details.

Quick Quotes API Update [#quick-quotes-api-update]

Quick quote API responses, such as <ApiLink name="QuickQuoteResponse" />, now include an optional `validationResult` which can be inspected if post-validation endpoint requests fail due to a quick quote never having passed validation.

billingTrigger Deprecation [#billingtrigger-deprecation]

`billingTrigger` is deprecated. Billing is always triggered while issuing a quote or transaction, and after the May 7 release, attempts to set `billingTrigger` to anything other than `issue` will be blocked.

Deprecated Jobs API Endpoints Removed [#deprecated-jobs-api-endpoints-removed]

The deprecated `fetchEarlyInvoicingJob` and `fetchEarlyInvoicingJobsForAccount` endpoints have been removed. All invoicing jobs can now be fetched with <ApiLink name="fetchInvoicingJob" /> and <ApiLink name="fetchInvoicingJobsForAccount" />.

Bug Fixes [#bug-fixes-41]

{/* KERN-5104, KERN-5252 */}

* Updated error message to indicate full set of unexpected document names if such documents are erroneously returned by the [document selection plugin](/configuration/plugins/document-selection).
* Fixed a bug preventing the generation of expected negative installment items when a cancellation transaction is preceded by a non-cost-bearing transaction.

April 23, 2025 [#april-23-2025]

Media Data [#media-data]

{/* KERN-5032 */}

You can now upload various media data to Socotra and create associations with entities, in much the same way as with [contacts](/features/contacts). See the [Media Data Guide](/features/work-management/media) and [API documentation](/api/aux-data/media) for details.

Search Updates [#search-updates-1]

{/* KERN-4595 */}

Search has been enhanced in several ways:

* You can now search for [contacts](/features/contacts), [diaries](/features/work-management/diaries), [first notice of loss ("FNOL")](/features/claims/fnol), and [payments](/features/billing/payments).
* For entities supporting [numbering](/configuration/general-topics/entity-numbering), you can search by number, and will see the number exposed in the result search summary.
* The "fuzzy" default behavior is more intuitive, accounting for "starts with" when scoring results.
* Filtering on start and end creation time is available.

See the [Search Feature Guide](/features/search) for details.

Coverage Terms Data Model Update [#coverage-terms-data-model-update]

[Coverage terms](/features/policy-management/coverage-terms) are now represented in the data model as `Map<String, Object>` instead of `Map<String, String>`. This allows fetches of validated entries to use actual expected types for coverage term values, instead of representing all values as strings. The introduction of "value" coverage terms, as opposed to "options", necessitated this change. It should have no effect on creation or update requests.

Configuration Redeployment Update [#configuration-redeployment-update]

It is now possible to add new, required [data extensions](/configuration/data-extensions/overview) on redeployment, as long as you supply default values. The platform will apply the default value on subsequent transactions as needed if a value is not explicitly defined.

See the [Redeployment Guide](/configuration/general-topics/redeployment) for additional details.

April 16, 2025 [#april-16-2025]

Policy Status [#policy-status]

{/* KERN-4943 */}

You can now view a policy's status and stay apprised of status changes via the event stream. See the [Policy Status Guide](/features/policy-management/policy-status) for details.

Note that policy statuses will not be backfilled; statuses will only be included for new policies and when transactions to existing policies prompt the platform to update the status.

Bug Fixes [#bug-fixes-42]

{/* KERN-5161, KERN-5099 */}

* Fixed a bug preventing documents from generating as expected on reversal and out-of-sequence (OOS) transactions.
* Constraint table lookups with decimal values as keys will now work as expected, with a value-based test for equality. For example, if a table has a key value `340.98000`, values `340.98000`, `340.980`, and `340.98` will match it.

April 9, 2025 [#april-9-2025]

Search Update [#search-update]

Searches by policy locator or account locator now include any associated first notice of loss (FNOL) records.

More Contact Associations [#more-contact-associations]

{/* KERN-4945 */}

[Contacts](/features/contacts) can now be linked to policies, quotes, and quick quotes.

Ad-Hoc Execution of Precommit Plugin [#ad-hoc-execution-of-precommit-plugin]

{/* KERN-4922 */}

The [precommit plugin](/configuration/plugins/precommit) can be invoked manually via API for draft quotes and draft or initialized transactions.

Full Stateless Pricing of Quote and Transactions [#full-stateless-pricing-of-quote-and-transactions]

{/* KERN-4883 */}

The [previews](/features/preview-operations) feature has been expanded to allow for stateless pricing of quotes and transactions. See the [Quotes API](/api/quotes/quotes) and [Policy Transactions API](/api/policy-management/policy-transactions) for preview endpoint details.

Bug Fixes [#bug-fixes-43]

{/* KERN-5177, KERN-5173, KERN-5174, KERN-5165, KERN-5141, KERN-5013 */}

* Updated logic to ensure that data masking rules are followed for policy change transactions; for example, a user with a lower-privilege masking level cannot add coverages that have fields restricted above that user's level.
* Users with a certain masking level are allowed to modify fields on entities at that level or below, even if the element has some data extensions at a higher masking level.
* Fixed unexpected `500` error on calls to <ApiLink name="fetchDocumentsJobForQuote" />.
* Configuration redeployment will now succeed if a regular expression rule for a field is removed, effectively widening allowed values for the field.
* <ApiLink name="addElementsToQuickQuote" /> persists newly added elements as
  expected.
* It is now possible to alter a payment's `paymentMode` from `aggregate` to `normal` when using <ApiLink name="updatePaymentOverwriteData" /> to update a payment.

April 2, 2025 [#april-2-2025]

Notice: Classic Early Invoicing Endpoint Deprecation [#notice-classic-early-invoicing-endpoint-deprecation]

Over the last few months, we have been working on some upcoming features related to flat charges and invoice fees. To provide the best possible API design as part of this, we are making some API changes.

* The existing `fetchEarlyInvoicingJob` and `fetchEarlyInvoicingJobsForAccount` endpoints will be removed as of the April 30th 2025 release. See the deprecation notice from February 12, 2025.
* The existing <ApiLink name="fetchInvoicingJob" /> and <ApiLink name="fetchInvoicingJobsForAccount" /> endpoints have been refactored to accommodate both early and immediate triggers for invoice generation.

*Internal changes only for this release.*

March 26, 2025 [#march-26-2025]

New Features [#new-features]

* [Aggregate payments](/features/billing/payments#aggregate-payments) allow you spread payments across accounts, supporting a wide range of use cases without compromising the ability to trace cash flows through the system.
* With [flat charges](/features/billing/flat-charges), you can invoice charges directly through the billing system and easily handle a variety of fee arrangements.
* [Previews](/features/preview-operations) allow you to view the outcome of certain key operations without committing to the changes.

Bug Fixes [#bug-fixes-44]

{/* KERN-5098, KERN-5029 */}

* Fixed a bug causing access tokens with an `expiresAt` in the future from being accepted as expected.
* `suppressRenderingData` now works as expected for all applicable [Documents API](/api/documents) endpoints, including <ApiLink name="fetchDocumentsForTransaction" />.

March 19, 2025 [#march-19-2025]

*Internal changes only for this release.*

March 12, 2025 [#march-12-2025]

New Feature: Data Lake Delta Files [#new-feature-data-lake-delta-files]

Easily sync Socotra Data Lake tables with your own infrastructure using [Data Lake Delta Files](/features/reporting/delta-files)! This feature allows you to list and retrieve SQL-based Data Lake diffs, ensuring accurate and efficient table replication into your own data platform.

New Data Lake Entities: Billing [#new-data-lake-entities-billing]

Data Lake now exposes a number of billing tables. See the [updated schema and guide](/features/reporting/datalake) for details.

Configuration Deployments API Update [#configuration-deployments-api-update]

{/* KERN-4882 */}

You can now upload configuration files with brackets (`[]`) in the filename.

Classic Endpoint List Behavior Deprecation [#classic-endpoint-list-behavior-deprecation]

Over the last few months, we have posted notices about [impending updates to our list endpoint behavior](#list-endpoint-semantics-notice). The "classic" behavior for list endpoints is to return a simple array of objects; however, to better facilitate pagination, we have established a new convention in which list endpoints will return an object with a `listComplete` property and the `items` array (example: <ApiLink name="InvoiceListResponse" />). Our API documentation has been following this new convention, which you will observe when setting the URL query parameter `extended` to `true` on list requests.

We recommend that you revise API client code to use `extended=true` and consume paged responses accordingly.

Classic list behavior is deprecated. Starting with the **May 14 Socotra release**, all list endpoint responses will be returned with the `extended=true` form, and the query parameter will no longer have a functional effect.

March 5, 2025 [#march-5-2025]

New Feature: First Notice of Loss [#new-feature-first-notice-of-loss]

The First Notice of Loss ("FNOL") feature allows you to capture key loss details before the formal claims process begins. See the [FNOL Guide](/features/claims/fnol) and [API documentation](/api/claims) for details.

New Feature Guides [#new-feature-guides]

* [Single Sign-On (SSO)](/configuration/general-topics/identity-providers)
* [Regions Configuration and Usage](/configuration/general-topics/regions)

February 26, 2025 [#february-26-2025]

Bug Fix [#bug-fix]

{/* KERN-4784 */}

If a <ApiLink name="QuoteCreateRequest">quote is created</ApiLink> with a specific `timezone` and no explicit `endTime`, the quote's `timezone` will be used as the basis for determining the `endTime`.

February 19, 2025 [#february-19-2025]

Rating Plugin Interface Update [#rating-plugin-interface-update]

The rating plugin interface has been updated so that `rate` or `referenceRate` do not need to be provided on `RatingItems` if an absolute `amount` is provided instead. See additional details in [prior release notes](#plugin-interface-changes-notice).

Invoices API Update [#invoices-api-update]

Invoice records returned by the [Invoices API](/api/billing/invoices) list endpoints will no longer contain `invoiceItems`. An invoice and its `invoiceItems` will still be obtainable by <ApiLink name="getInvoiceWithItems">fetching an invoice with its items</ApiLink>.

Resource Selection Update [#resource-selection-update]

In plugins, you can now set a specific time for the resource selector to use as its reference point, like this:

```java
Optional<VehicleTypeFactor> tableRecord = ResourceSelectorFactory.getInstance()
      .getSelector(Instant.now())
      .getTable(VehicleTypeFactor.class)
      .getRecord(VehicleTypeFactor.makeKey("toyota", "corolla", 2010));
```

Bug Fixes [#bug-fixes-45]

{/* KERN-4812, KERN-4796 */}

* Revised misleading error message on attempts to create users with invalid characters in the `userName`. The new error message clearly identifies the username as invalid, and why.
* Updated quote validation to check whether an invalid timezone was provided.

February 12, 2025 [#february-12-2025]

Policy Transactions API Update [#policy-transactions-api-update]

The <ApiLink name="fetchAffectedTransactions" /> list of <ApiLink name="AffectedTransaction" /> will no longer include reapplied transactions. Instead, the `reapplicationOfLocator` on the <ApiLink name="PolicyTransactionResponse" /> will have the locator of the transaction being reapplied.

Jobs API Endpoint Deprecations [#jobs-api-endpoint-deprecations]

The `fetchEarlyInvoicingJob` and `fetchEarlyInvoicingJobsForAccount` endpoints are deprecated.

Bug Fix [#bug-fix-1]

{/* KERN-4722 */}

The `policy.quote.update` event will now fire when adding, modifying, or deleting elements.

Forthcoming Changes [#forthcoming-changes]

* [Invoices API](/api/billing/invoices): in next week's release, invoice records returned by list endpoints will no longer contain `invoiceItems`. An invoice and its `invoiceItems` will still be obtainable by <ApiLink name="getInvoiceWithItems">fetching an invoice with its items</ApiLink>.
* Plugin interface and list endpoint semantics update: see the January 22 release notes for details on [impending changes to the rating plugin interface](#plugin-interface-changes-notice) and [list endpoint semantics](#list-endpoint-semantics-notice) throughout the Socotra API.

February 5, 2025 [#february-5-2025]

Account Constraints [#account-constraints]

You can now configure [constraints](/configuration/data-extensions/data-extension-constraints) for data extensions on [accounts](/features/accounts). See the [Accounts API](/api/accounts) for details on corresponding constraint evaluation endpoints.

Documents API Update [#documents-api-update]

[Documents API](/api/documents) fetch endpoints have a new `suppressRenderingData` option. When set to `true`, the API allows you to fetch 100 items per page instead of 10, but items will not include metadata or rendering data.

Forthcoming Plugin Interface Changes [#forthcoming-plugin-interface-changes]

See [the January 22 release notes](#plugin-interface-changes-notice) for details on impending changes to the rating plugin interface and list endpoint semantics throughout the Socotra API.

January 29, 2025 [#january-29-2025]

*Internal changes only for this release.*

See last week's release notes for details on impending changes to the rating plugin interface and list endpoint semantics throughout the Socotra API.

January 22, 2025 [#january-22-2025]

<span id="plugin-interface-changes-notice" />

Forthcoming Plugin Interface Changes [#forthcoming-plugin-interface-changes-1]

To facilitate upcoming support for flat charges and invoice fees, `RatingItem` objects returned from the rating plugin will no longer be required to have `rate` or `referenceRate` properties if an absolute `amount` is provided instead.

Existing plugin code that reads `rate()` or `referenceRate()` will need to recognize the returned values as `Optional`.

```java
// code that is currently valid but will need to be updated after this change is deployed:
BigDecimal rate = ratingItem.rate();

// equivalent code after this change is deployed:
Optional<BigDecimal> rate = ratingItem.rate();
```

In the `DocumentDataSnapshot` plugin, the following properties will also become optional, and will need to be handled in a similar way:

* `InvoiceItemSummary.elementType`
* `InvoiceItemSummary.elementStaticLocator`
* `InvoiceItem.elementStaticLocator`

**The provisional release date for these changes is February 19.**

We are analyzing deployed configurations to assess customer impact and ensure that configurations are updated for compatibility in coordination with this change rollout. Of course, deployment attempts after this change will fail with a compilation error if plugin code has not been updated to handle `Optional` types correctly.

Please contract your Socotra representative if you have any questions. We will provide additional updates about this impending change in subsequent release notes.

<span id="list-endpoint-semantics-notice" />

List Endpoint Semantics Update [#list-endpoint-semantics-update]

As indicated in prior release notes ("Changes to Paged List Fetch Semantics"), Socotra is moving to a convention in which list results are not simply an array of items but an object containing the results array and an indicator `listCompleted` property to facilitate results pagination.

The new response format is documented for individual list endpoints (e.g. <ApiLink name="fetchMultipleAccounts" />), and is obtained by setting the optional `extended` query parameter to `true`. Soon, all such endpoints will behave as though `extended` is `true` by default, and we will remove that query parameter and access to the original list response style.

We recommend that client code be updated to use `extended=true` in all list fetches so that response consumption is brought in line with the new standard. In upcoming release notes, we will provide a reminder and a date on which the `extended=true` response style will become the default.

January 15, 2025 [#january-15-2025]

Underwriting Event Payload Updates [#underwriting-event-payload-updates]

The following underwriting event payloads will no longer include arrays of underwriting flags:

* <ApiLink name="QuoteManuallyUnderwrittenEventData" />
* <ApiLink name="QuoteUnderwrittenEventData" />
* <ApiLink name="TransactionManualUnderwritingEventData" />
* <ApiLink name="TransactionUnderwritingEventData" />

Underwriting flags on quotes and transactions can be fetched through the API, where they are exposed in <ApiLink name="QuoteUnderwritingFlagsResponse" /> and <ApiLink name="TransactionUnderwritingResponse" />, respectively.

Other Changes [#other-changes-1]

* `timezone` has been added to <ApiLink name="QuoteUpdateRequest" />.
* There is now a <ApiLink name="addSAMLIdentityProvider">dedicated SAML identity provider creation endpoint</ApiLink> and corresponding <ApiLink name="SAMLIdentityProviderCreateRequest" />.

January 8, 2025 [#january-8-2025]

New Feature: Availability [#new-feature-availability]

The availability feature facilitates the introduction and retirement of products, data extensions, policy elements, and coverage terms, supporting a variety of use cases. See the [Availability Guide](/configuration/general-topics/availability) for details.

New Feature: Contact Management [#new-feature-contact-management]

Contact management brings the ability to define contacts and manage them in association with system entities. See the [Contact Management Feature Guide](/features/contacts) for details.

New Static Data Endpoints [#new-static-data-endpoints]

The following endpoints allow for fetching static data on quotes and policies, including historical values:

* <ApiLink name="fetchStaticDataForPolicy" />
* <ApiLink name="listStaticDataForPolicy" />
* <ApiLink name="fetchStaticDataForQuote" />
* <ApiLink name="listStaticDataForQuote" />

Underwriting Update [#underwriting-update]

* <ApiLink name="UnderwritingFlagCreateRequest" /> and
  <ApiLink name="UnderwritingFlagResponse" /> now have a `tag` property.

December 18, 2024 [#december-18-2024]

User Management API Update [#user-management-api-update]

An optional `email` property has been added to <ApiLink name="UserCreateRequest" />, <ApiLink name="UserUpdateRequest" />, and <ApiLink name="UserResponse" />.

<Callout>
  This is the final 2024 release. There will be no release on 2024-Dec-25, and no release the following week (2025-Jan-01). The next release will be available Wednesday, 2025-Jan-08.
</Callout>

December 11, 2024 [#december-11-2024]

Migration API update [#migration-api-update]

{/* KERN-4359 */}

The [Migration API](/api/migration) now allows you to specify Aux Data for importation with <ApiLink name="AuxDataMigrationRequest" />.

Identity Providers API update [#identity-providers-api-update]

{/* KERN-4414 */}

<ApiLink name="IdentityProviderResponse" /> now includes a `callbackUrl`
property.

December 4, 2024 [#december-4-2024]

New Feature: Data Lake (Beta) [#new-feature-data-lake-beta]

Data Lake provides a relational view of your book of business in Socotra, enabling a wide range of reporting applications. See the [Data Lake Guide](/features/reporting/datalake) for details.

New Feature: Value-Based Coverage Terms [#new-feature-value-based-coverage-terms]

Until now, values to be associated with a [coverage term](/features/policy-management/coverage-terms) had to be defined as a finite set of `options` in the configuration. To support use cases requiring variable values -- such as a computed quantity based on various factors -- a coverage term may now be configured to take a `value` described as a <ApiLink name="PropertyRef" />, instead of `options`. See the [Coverage Terms Guide](/features/policy-management/coverage-terms) for details.

Other Changes [#other-changes-2]

{/* KERN-4319, KERN-4362 */}

* Use of the precommit plugin for delinquency events (method signature `PreCommitDelinquencyEventsResponse preCommit(PreCommitPlugin.DelinquencyEventsRequest request)`) is now deprecated.
* Both "startsWith" and "fuzzy" searches are case-insensitive.

Bug Fixes [#bug-fixes-46]

{/* KERN-4274, KERN-4074, KERN-3909 */}

* Pascal casing for account names is now enforced.
* `graceEndAt` now accounts for `gracePeriodDays` if that value is set in the precommit plugin for delinquency, with `graceEndAt` taking precedence if it is also set in the plugin.
* [Deployments API](/api/configuration-and-development/deployments): <ApiLink name="validateConfig" /> and <ApiLink name="formatConfig" /> responses include a `content-type: application/zip` header.

November 20, 2024 [#november-20-2024]

New Feature: Early Invoicing [#new-feature-early-invoicing]

* Early invoicing allows invoices to be created and sent before the generate time of the installments that they are based on.
* See the [Early Invoicing Feature Guide](/features/billing/early-invoicing) for details.

<Callout>
  There will be no release on 2024-Nov-27. The next release will be on 2024-Dec-04.
</Callout>

November 13, 2024 [#november-13-2024]

New Feature: Delinquency Events [#new-feature-delinquency-events]

* Delinquency events are a new feature that supports extending delinquency processes with additional extensions.
* For interacting with events directly, the <ApiLink name="fetchDelinquencyEvents" /> and <ApiLink name="updateDelinquencyEvent" /> endpoints are added, along with responses <ApiLink name="DelinquencyEventsResponse" /> and <ApiLink name="DelinquencyEventResponse" />
* The endpoint <ApiLink name="fetchDelinquencyEventJobs" /> and response types <ApiLink name="DelinquencyEventJobDataListResponse" /> and <ApiLink name="DelinquencyEventJobData" /> have been added for job information.
* See the [Delinquency Events Feature Guide](/features/billing/delinquency-events) for details.

November 6, 2024 [#november-6-2024]

Constraint Tables [#constraint-tables]

* There is now an option to use any column (not just the first column) of a constraint table as a list of distinct values for [constraints evaluation](/configuration/data-extensions/data-extension-constraints). Use of the first column is implicit if there is no `where` clause. To enable other columns, set the `makeDistinct` property in the <ApiLink name="ConstraintColumnRef">column definition</ApiLink> to `true`.
* For consistency with other validation checks on configuration deployment, validation of constraint column names is now case sensitive as well. Column names in the constraints definition have to match case with column name in the associated constraint table definition.

Quote Events [#quote-events]

* Events have been added to signal changes to static data for quotes.
* The new event types are `policy.quote.staticdata.add`, `policy.quote.staticdata.replace`, and `policy.quote.staticdata.update`, each of which emit a <ApiLink name="QuoteEventData" /> object.

Optional Properties [#optional-properties]

The following properties are now marked as optional:

* <ApiLink name="CoverageTermOptionRef" />: `tag`
* <ApiLink name="PaymentRef" /> and <ApiLink name="PaymentResponse" />: `data`
* <ApiLink name="CreateEndpointRequest" />: `headers`

October 30, 2024 [#october-30-2024]

Constraints with Custom Data Types [#constraints-with-custom-data-types]

Data extension constraints have been extended to include nested custom data objects. Constraining arrays of custom data objects is not yet supported.

Additional Changes to Paged List Fetch Semantics [#additional-changes-to-paged-list-fetch-semantics]

The following endpoints have been updated to align with list endpoint semantics as described in recent release notes:

* <ApiLink name="getMigrationMappings" /> returns
  <ApiLink name="AccountMigrationIdMappingsListResponse" />
* <ApiLink name="listAccountMigrations" /> returns
  <ApiLink name="ListPageResponseAccountMigrationResponse" />
* <ApiLink name="getMigrationFailures" /> returns
  <ApiLink name="ListPageResponseMigrationFailuresResponse" />
* <ApiLink name="fetchWebhooks" /> returns
  <ApiLink name="WebhookListResponse" />

Deployments [#deployments]

To better accommodate common zip file creation patterns on various systems, configuration deployment will no longer fail if the configuration archive contains an extra top-level directory.

October 23, 2024 [#october-23-2024]

Data Access Controls [#data-access-controls]

* Security features are now available to restrict users' access to system data based on specific Products or Regions, or designated extension data.
* See the [Data Access Controls feature guide](/configuration/general-topics/data-access-controls) and [Data Access Controls API guide](/api/configuration-and-development/data-access-controls) for details.

Webhooks Security Features [#webhooks-security-features]

* Webhooks are now security enabled: The entities <ApiLink name="CreateEndpointRequest" />, <ApiLink name="UpdateEndpointRequest" />, and <ApiLink name="EndpointResponse" /> have added properties `secret`, `tag`, `secureSsl`, and `hmacEnabled`.
* See the [Security Features section of the Webhooks configuration guide](/configuration/general-topics/webhooks#webhooksSecurity) for implementation details.

Yet More Changes to Paged List Fetch Semantics [#yet-more-changes-to-paged-list-fetch-semantics]

Similar to the endpoints that were enhanced last week, when fetching entities with any of the following endpoints, a new query parameter is available called `extended`. Setting `extended` to `true` means that the return object will not be a bare array of entities, but rather a List Contents object that includes an indicator that the list is complete. The following endpoints have been changed:

* <ApiLink name="fetchMultipleBasicUsers" /> returns
  <ApiLink name="BasicUserListResponse" /> (and, `UserBasicResponse` has been
  renamed to <ApiLink name="BasicUserResponse" />)
* <ApiLink name="fetchTenants" /> returns <ApiLink name="TenantListResponse" />
* <ApiLink name="fetchInvoicesForPolicy" />,
  <ApiLink name="fetchInvoicesForAccount" />,
  <ApiLink name="fetchInvoicesForQuote" />,
  <ApiLink name="fetchInvoicesTargetedByACreditDistribution" /> and
  <ApiLink name="fetchInvoicesTargetedByAPayment" /> return
  <ApiLink name="InvoiceListResponse" />
* <ApiLink name="fetchInstallmentsForPolicy" />,
  <ApiLink name="fetchInstallmentsForPolicyTransaction" />,
  <ApiLink name="fetchInstallmentsForQuote" /> return
  <ApiLink name="InstallmentListResponse" />
* <ApiLink name="fetchInstallmentLatticesByPolicyLocator" /> returns
  <ApiLink name="InstallmentLatticeListResponse" />
* <ApiLink name="fetchMultiplePayments" /> and
  <ApiLink name="fetchPaymentsForAnInvoice" /> return
  <ApiLink name="PaymentListResponse" />
* <ApiLink name="fetchMultipleDisbursements" /> returns
  <ApiLink name="DisbursementListResponse" />
* <ApiLink name="fetchMultipleCreditDistributions" /> and
  <ApiLink name="fetchCreditDistributionsForAnInvoice" /> return
  <ApiLink name="CreditDistributionListResponse" />
* <ApiLink name="getDelinquenciesForAccount" />, getDelinquenciesForQuote,
  <ApiLink name="getDelinquenciesForPolicy" /> and
  <ApiLink name="getDelinquenciesForInvoice" /> return
  <ApiLink name="DelinquencyListResponse" />
* <ApiLink name="fetchCredits" /> and
  <ApiLink name="fetchCreditsForAnInvoice" /> return
  <ApiLink name="CreditListResponse" />
* <ApiLink name="fetchMultipleShortfallCredits" /> returns
  <ApiLink name="ShortfallCreditListResponse" />
* <ApiLink name="fetchMultipleWriteOffs" /> returns
  <ApiLink name="WriteOffListResponse" />
* <ApiLink name="fetchAllHoldsForAnAccount" /> returns
  <ApiLink name="HoldListResponse" />
* <ApiLink name="listFinancialInstruments" /> returns
  <ApiLink name="FinancialInstrumentListResponse" />
* <ApiLink name="fetchMultipleLedgerCashAccounts" /> returns
  <ApiLink name="LedgerAccountListResponse" />
* <ApiLink name="fetchInstallmentsJobDataForTransactions" />,
  <ApiLink name="fetchInstallmentsJobDataForQuotes" /> return
  <ApiLink name="InstallmentJobDataListResponse" />
* <ApiLink name="fetchDelinquencyGraceJob" /> returns
  <ApiLink name="GraceJobDataListResponse" />
* <ApiLink name="fetchCreateDelinquenciesJobDataForInvoice" /> returns
  <ApiLink name="DelinquencyCreateJobDataListResponse" />

The [Open API descriptor file](/other-resources/open-api-specification) and documentation for endpoints expresses these responses as if the `extended` property were set to `true`.

<Callout>
  Later, the `extended` property will be deprecated, and then removed and the default behavior will be as if it were `true`. Until then, the default value for this flag is `false`.
</Callout>

Other Changes [#other-changes-3]

* There is a new [Feature Guide for Dynamic Documents](/features/documents/dynamic-documents)!
* There is a new block of example code provided for the [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot#documentDataSnapshotExample) configuration guide.
* The <ApiLink name="InvoiceItemResponse" /> entity has new property `invoiceItemLocators`.
* The <ApiLink name="InvoiceItemPreview" /> entity has new optional properties `policyLocator`, `quoteLocator`, `chargeCategory`, `chargeType`, and `transactionLocators`.

October 16, 2024 [#october-16-2024]

Entity Numbering [#entity-numbering]

* Several system entities, including accounts, policies, quotes, policy terms, invoices, and disbursements can now have automatically generated numbers, for use on printed documents, portal and app screens, etc.
* This provides a much easier, human-readable identifier compared to locators.
* Numbers are ideal for use in customer service and similar situations.
* See the [Entity Numbering Feature Guide](/configuration/general-topics/entity-numbering) for details.

More Changes to Paged List Fetch Semantics [#more-changes-to-paged-list-fetch-semantics]

When fetching entities with any of the following endpoints, a new query parameter is available called `extended`. Setting `extended` to `true` means that the return object will not be a bare array of entities, but rather a List Contents object that includes an indicator that the list is complete. The following endpoints have been changed:

* <ApiLink name="fetchMyTenants" /> returns
  <ApiLink name="TenantListResponse" />
* <ApiLink name="fetchDocumentsForTransaction" />,
  <ApiLink name="fetchDocumentsForSegment" />, and
  <ApiLink name="fetchDocumentsForQuote" /> return
  <ApiLink name="DocumentListResponse" />
* <ApiLink name="fetchMultipleDocumentsJobsForTransaction" />,
  <ApiLink name="fetchMultipleDocumentsJobsForSegment" />, and
  <ApiLink name="fetchMultipleDocumentsJobsForQuote" /> return
  <ApiLink name="DocumentJobListResponse" />
* <ApiLink name="fetchMultipleUsers" /> returns
  <ApiLink name="UserListResponse" />.
* <ApiLink name="fetchMultipleRoles" /> returns
  <ApiLink name="RoleListResponse" />.
* <ApiLink name="fetchMultipleResources" /> returns
  <ApiLink name="ResourceListResponse" />
* <ApiLink name="fetchResourceGroups" /> returns
  <ApiLink name="ResourceGroupListResponse" />

Other Changes [#other-changes-4]

* The <ApiLink name="InvoiceItemPreview" /> entity has added fields `policyLocator`, `quoteLocator`, `chargeCategory`, `chargeType`, and `transactionLocators` properties.
* The <ApiLink name="InvoiceItemResponse" /> entity has new property `transactionLocators`.
* The <ApiLink name="DeployedConfigMetadata" /> entity's `pluginVersionStatus` has type changed from `map<string,string>` to `map<string,map<string,string>>`.

October 9, 2024 [#october-9-2024]

New Feature Guides [#new-feature-guides-1]

* [Delinquency Feature Guide](/features/billing/delinquency)
* [Billing Holds Feature Guide](/features/billing/billing-holds)

Other Changes [#other-changes-5]

* Added new <ApiLink name="fetchTenantLevelCashBalance" /> endpoint.
* Added new property `clearedAt` to <ApiLink name="UnderwritingFlagResponse" />.

October 2, 2024 [#october-2-2024]

* Added the property `category` to <ApiLink name="ElementResponse" />, to indicate in which of the main categories the element is. This can be `product`, `policyLine`, `exposureGroup`, `exposure`, or `coverage`.
* Added the <ApiLink name="formatConfig" /> endpoint to convert a configuration's property casing to match requirements.
* Added the `resetToDraft` query parameter for the <ApiLink name="resetTransaction" /> endpoint. If `true`, then the transaction will revert to draft state and the generated segment data, including elements and data, will be discarded. If `false` (the default), then the transaction will revert to `initialized` state and the segment data will be retained. This is useful to preserve the locator data for generated elements.

September 25, 2024 [#september-25-2024]

New Getting Started Guide! [#new-getting-started-guide]

* See the new [Getting Started Guide](/getting-started/introduction-to-socotra) for a step-by-step introduction to configuring and using Socotra.

New Migration Feature Guide [#new-migration-feature-guide]

* See the new [Migration Feature Guide](/features/migration) for more details about data migration projects.

Invoice Documents [#invoice-documents]

* Documents can now be configured to renender when invoices are generated, similarly to how policy documents are created.
* See the [Invoice Rendering](/features/billing/invoicing#invoiceRendering) topic for details.

Other Changes [#other-changes-6]

* Enabled support for [reinstatement with a gap](/features/policy-management/reinstatements#reinstatementWithGap).
* Added a new feature guide for [automatic handling of excess credits](/features/billing/excess-credits).
* Extended the [Quick Quotes Feature Guide](/features/policy-quotation/quick-quotes) with additional details.
* Clarified in the [Rounding Service Feature Guide](/features/financials/rounding-service) that the configuration for rounding mode is limited to data extensions.
* Marked the following properties as optional:
  * <ApiLink name="UnderwritingFlagResponse" />: `elementLocator`
  * <ApiLink name="QuoteUnderwritingFlagsResponse" />: `clearedFlags`

September 18, 2024 [#september-18-2024]

External Documents [#external-documents]

You can now attach documents created from outside Socotra to quotes, policies, terms, segments, and transactions. See the [Document Management Feature Guide](/features/documents/document-management) and [Documents API Guide](/api/documents) for details.

Other Changes [#other-changes-7]

* On <ApiLink name="PolicyResponse" />, the `latestSegmentLocator` has been added to indicated the last segment on the policy based on issued transactions.
* The <ApiLink name="TermResponse" /> entity has added property `termNumber`.
* The <ApiLink name="addElementsToPolicyWithTransaction" /> endpoint's request type has been changed to <ApiLink name="ElementResponse">ElementResponse\[]</ApiLink>.
* On <ApiLink name="ConfigurationRef" />, the `defaultRegion` property has been deprecated and marked as optional.
* For these configuration entities, the `displayName` is now marked as optional.
  * <ApiLink name="AuxDataSettingsRef" />
  * <ApiLink name="BillingPlanRef" />
  * <ApiLink name="ChargeRef" />
  * <ApiLink name="CoverageTermOptionRef" />
  * <ApiLink name="CoverageTermRef" />
  * <ApiLink name="DataTypeRef" />
  * <ApiLink name="DelinquencyPlanRef" />
  * <ApiLink name="DisbursementRef" />
  * <ApiLink name="DocumentConfigRef" />
  * <ApiLink name="ElementRef" />
  * <ApiLink name="InstallmentPlanRef" />
  * <ApiLink name="PaymentRef" />
  * <ApiLink name="ProductRef" />
  * <ApiLink name="PropertyRef" />
  * <ApiLink name="RegionRef" />

Older Changes [#older-changes]

See the [release notes archive](/other-resources/release-notes-archive) for older release notes.


# Overview



EC React is a powerful, schema-driven framework for building
enterprise-grade insurance applications. This library provides a
comprehensive suite of dynamic forms and UI components designed to
accelerate development and handle the full spectrum of policy lifecycle
operations with unparalleled flexibility.

Core Philosophy [#core-philosophy]

At its core, this library is engineered to translate Socotra’s flexible
data model directly into a rich, interactive user interface. By
leveraging your unique data model, we dynamically generate complex
forms, eliminating the need to manually build and maintain forms for
every product or data variation. This schema-driven approach ensures
that as your insurance products evolve, your UI adapts automatically,
dramatically reducing development overhead and increasing speed to
market.

Our components are built with modern, robust technologies including
**React** , **TypeScript** , **Shadcn UI** , and **Tailwind CSS** ,
ensuring a developer-friendly, performant, and highly customizable
experience.

Key Features [#key-features]

* **Schema-Driven UI**: Forms for quotes, policies, accounts, and
  transactions are generated dynamically from your data model, not
  hardcoded.
* **Complex Logic Handling**: Built-in support for sophisticated
  insurance workflows, including constraint evaluation for real-time
  field dependency updates.
* **Highly Customizable**: A powerful `tag` system allows for deep
  customization of field behavior directly from the data model—from
  conditional visibility to special UI controls like multi-select and
  currency inputs.
* **Enterprise-Ready**: Designed to handle the intricate details of
  policy administration, including endorsements, payments,
  disbursements, and renewals.
* **Modern Tech Stack**: A clean, modern, and performant codebase that
  is a pleasure to work with and extend.

Installation [#installation]

This monorepo contains three core packages that can be installed from
`npm`. For most applications, you will want to install all three:

* `@socotra/ec-react-components`: The main library of schema-driven
  React components.
* `@socotra/ec-react-schemas`: TypeScript interfaces and `zod`
  schemas for all data models.
* `@socotra/ec-react-utils`: Helper functions for data transformation
  and API requests.

Install all packages with a single command:

```sh
npm i @socotra/ec-react-components @socotra/ec-react-schemas @socotra/ec-react-utils
```

For detailed setup instructions, such as Tailwind CSS configuration for
the component library, please see the `README.md` file within each
individual package directory.


# EC React Schemas



Schemas for the Socotra Insurance Suite [#schemas-for-the-socotra-insurance-suite]

This package provides a comprehensive collection of `zod` schemas that
define the core data structures for Socotra’s Enterprise Components.
These schemas are fundamental to ensuring type safety, data integrity,
and validation across the platform, from backend services to frontend
components.

Core Philosophy [#core-philosophy]

Zod Schemas are powerful tools for data validation and type inference.
They are used to define the structure of the data that is passed into
and out of the library. They are also used to define the structure of
the data that is stored in the database.

By leveraging the power of Zod, we can ensure that the data that is
passed into and out of the library is always valid and of the correct
type. This is especially important for complex data structures that are
used in the library, such as policies, accounts, and transactions.

Key Features [#key-features]

* **Domain Schemas:** Business-specific data models (e.g., Policies,
  Invoices, Accounts).
* **Config Schemas:** Structures for configuration objects (e.g.,
  Product and UI configurations).
* **Service Schemas:** Data contracts for API requests and responses.
* **Shared Schemas:** Common, reusable data structures used across
  multiple domains.

***

Installation [#installation]

This package has a peer dependency on `zod`. Install both packages in
your project:

```sh
npm i @socotra/ec-react-schemas zod
```

***

Usage [#usage]

Import schemas directly from the package to use them for data
validation, type inference, or in conjunction with libraries like
`react-hook-form`.

```ts
import { policyResponseSchema } from '@socotra/ec-react-schemas';
import { z } from 'zod';

type Policy = z.infer<typeof policyResponseSchema>;

function validatePolicy(data: unknown): Policy {
	return policyResponseSchema.parse(data);
}
```

***

Available Schemas [#available-schemas]

Accounts [#accounts]

**account-request.ts**

| Zod Schema               | Type                   |
| ------------------------ | ---------------------- |
| `accountStateEnumSchema` | `AccountStateEnum`     |
| `accountCreateSchema`    | `AccountCreateRequest` |
| `accountUpdateSchema`    | `AccountUpdateRequest` |

Billings [#billings]

**credit-distribution-request-schema.ts**

| Zod Schema                        | Type                        |
| --------------------------------- | --------------------------- |
| `creditDistributionRequestSchema` | `CreditDistributionRequest` |

**credit-distribution-response-schema.ts**

| Zod Schema                         | Type                         |
| ---------------------------------- | ---------------------------- |
| `creditDistributionResponseSchema` | `CreditDistributionResponse` |

**credit-distribution-reverse-request.ts**

| Zod Schema                               | Type                               |
| ---------------------------------------- | ---------------------------------- |
| `creditDistributionReverseRequestSchema` | `CreditDistributionReverseRequest` |

**credit-distribution-schemas.ts**

| Zod Schema                          | Type                          |
| ----------------------------------- | ----------------------------- |
| `creditDistributionStateEnumSchema` | `CreditDistributionStateEnum` |

**delinquency-schemas.ts**

| Zod Schema                           | Type                       |
| ------------------------------------ | -------------------------- |
| `advanceLapseToEnumSchema`           |                            |
| `delinquencyLevelEnumSchema`         |                            |
| `delinquencyStateEnumSchema`         |                            |
| `delinquencyReferenceTypeEnumSchema` |                            |
| `delinquencySettingsSchema`          | `DelinquencySettings`      |
| `delinquencyReferenceSchema`         | `DelinquencyReferenceType` |
| `delinquencyResponseSchema`          | `DelinquencyResponse`      |
| \\                                   | `AdvanceLapseTo`           |
| \\                                   | `DelinquencyLevel`         |
| \\                                   | `DelinquencyState`         |
| \\                                   | `DelinquencyReference`     |

**invoice-response-schema.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `invoiceItemResponseSchema` | `InvoiceItemResponse` |
| `invoiceResponseSchema`     | `InvoiceResponse`     |

**invoice-schemas.ts**

| Zod Schema               | Type           |
| ------------------------ | -------------- |
| `invoiceStateEnumSchema` |                |
| \\                       | `InvoiceState` |

**ledger-account-response-schema.ts**

| Zod Schema                    | Type                    |
| ----------------------------- | ----------------------- |
| `ledgerAccountResponseSchema` | `LedgerAccountResponse` |

**ledger-account-schemas.ts**

| Zod Schema                              | Type                              |
| --------------------------------------- | --------------------------------- |
| `ledgerAccountReferenceTypeEnumSchema`  | `LedgerAccountReferenceTypeEnum`  |
| `ledgerAccountAccountingTypeEnumSchema` | `LedgerAccountAccountingTypeEnum` |
| `ledgerAccountLineItemSchema`           | `LedgerAccountLineItem`           |

**payment-request-schema.ts**

| Zod Schema             | Type             |
| ---------------------- | ---------------- |
| `PaymentRequestSchema` | `PaymentRequest` |

**payment-schemas.ts**

| Zod Schema                          | Type                          |
| ----------------------------------- | ----------------------------- |
| `creditItemContainerTypeEnumSchema` | `CreditItemContainerTypeEnum` |
| `creditItemSchema`                  | `CreditItem`                  |
| `transactionMethodEnumSchema`       | `TransactionMethodEnum`       |
| `paymentStateEnumSchema`            |                               |
| \\                                  | `paymentStateEnum`            |

Charges [#charges]

**charge-enums.ts**

| Zod Schema                 | Type             |
| -------------------------- | ---------------- |
| `chargeCategoryEnumSchema` |                  |
| `chargeCategorySchema`     | `ChargeCategory` |

**charge-response-schema.ts**

| Zod Schema             | Type             |
| ---------------------- | ---------------- |
| `chargeResponseSchema` | `ChargeResponse` |

Config [#config]

**account-evaluate-constraints-request.ts**

| Zod Schema                                | Type                                |
| ----------------------------------------- | ----------------------------------- |
| `accountEvaluateConstraintsRequestSchema` | `AccountEvaluateConstraintsRequest` |

**account-schema.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `accountConfigSchema`       | `AccountConfigRecord` |
| `accountConfigRecordSchema` |                       |
| \\                          | `AccountConfig`       |

**auto-renewal-plan-schema.ts**

| Zod Schema                     | Type              |
| ------------------------------ | ----------------- |
| `autoRenewalPlanSchema`        | `AutoRenewalPlan` |
| `autoRenewalPlanRecordsSchema` |                   |

**bootstrap.ts**

| Zod Schema                     | Type                        |
| ------------------------------ | --------------------------- |
| `bootstrapResourceGroupSchema` | `BootstrapResourceGroup`    |
| `bootstrapResourceInstance`    | `BootstrapResourceInstance` |
| `bootstrapResourcesSchema`     | `BootstrapResources`        |
| `bootstrapSchema`              | `Bootstrap`                 |

**constraint-schema.ts**

| Zod Schema               | Type               |
| ------------------------ | ------------------ |
| `constraintConfigSchema` | `ConstraintConfig` |

**constraint-tables-schema.ts**

| Zod Schema               | Type               |
| ------------------------ | ------------------ |
| `constraintTablesSchema` | `ConstraintTables` |

**coverage-terms-schema.ts**

| Zod Schema                  | Type                        |
| --------------------------- | --------------------------- |
| `CoverageTermValueSchema`   | `CoverageTermValue`         |
| `coverageTermOptionSchema`  | `CoverageTermOption`        |
| `coverageTermSchema`        | `CoverageTermsConfigRecord` |
| `coverageTermsRecordSchema` |                             |
| \\                          | `CoverageTermsConfig`       |

**data-model-schema.ts**

| Zod Schema        | Type        |
| ----------------- | ----------- |
| `dataModelSchema` | `DataModel` |

**data-type-schema.ts**

| Zod Schema              | Type                   |
| ----------------------- | ---------------------- |
| `dataTypeConfigSchema`  | `DataTypeConfigRecord` |
| `dataTypesRecordSchema` |                        |
| \\                      | `DataTypeConfig`       |

**delinquency-plan-schema.ts**

| Zod Schema                     | Type              |
| ------------------------------ | ----------------- |
| `delinquencyLevelSchema`       |                   |
| `advanceLapseToSchema`         |                   |
| `delinquencyPlanSchema`        | `DelinquencyPlan` |
| `delinquencyPlanRecordsSchema` |                   |

**element-schema.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `elementConfigSchema`       | `ElementConfigRecord` |
| `elementConfigRecordSchema` |                       |
| \\                          | `ElementConfig`       |

**dependency-map-response.ts**

| Zod Schema                    | Type                    |
| ----------------------------- | ----------------------- |
| `dependencyMapResponseSchema` | `DependencyMapResponse` |

**evaluate-constraint-request.ts**

| Zod Schema                         | Type                         |
| ---------------------------------- | ---------------------------- |
| `evaluateConstraintsRequestSchema` | `EvaluateConstraintsRequest` |

**evaluate-constraint-response.ts**

| Zod Schema                          | Type                          |
| ----------------------------------- | ----------------------------- |
| `evaluateConstraintsResponseSchema` | `EvaluateConstraintsResponse` |

**field-schema.ts**

| Zod Schema                | Type                |
| ------------------------- | ------------------- |
| `fieldConfigSchema`       | `FieldConfigRecord` |
| `fieldConfigRecordSchema` |                     |
| \\                        | `FieldConfig`       |

**payment-schema.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `paymentConfigSchema`       | `PaymentConfig`       |
| `paymentConfigRecordSchema` | `PaymentConfigRecord` |

**product-schema.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `productConfigSchema`       | `ProductConfigRecord` |
| `productConfigRecordSchema` |                       |
| \\                          | `ProductConfig`       |

**quantifiers.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `quantifiersSchema`         | `Quantifiers`         |
| `optionalQuantifiersSchema` | `OptionalQuantifiers` |

**reversal-type-schema.ts**

| Zod Schema                     | Type                       |
| ------------------------------ | -------------------------- |
| `reversalCreditTypeEnumSchema` | `ReversalCreditTypeEnum`   |
| `reversalTypeSchema`           | `ReversalType`             |
| `reversalTypesRecordsSchema`   |                            |
| \\                             | `ReversalTypeConfigRecord` |

**tenant-schema.ts**

| Zod Schema               | Type               |
| ------------------------ | ------------------ |
| `tenantBaseConfigSchema` | `TenantBaseConfig` |

**transaction-types-schema.ts**

| Zod Schema                      | Type                          |
| ------------------------------- | ----------------------------- |
| `transactionTypeCategorySchema` | `TransactionTypeCategory`     |
| `transactionTypeSchema`         | `TransactionType`             |
| `transactionTypesRecordsSchema` |                               |
| \\                              | `TransactionTypeConfigRecord` |

Documents [#documents]

**document-response.ts**

| Zod Schema                       | Type                       |
| -------------------------------- | -------------------------- |
| `documentInstanceResponseSchema` | `DocumentInstanceResponse` |

Policies [#policies]

**policy-schemas.ts**

| Zod Schema                       | Type                   |
| -------------------------------- | ---------------------- |
| `policyBillingLevelEnumSchema`   |                        |
| `policyBillingTriggerEnumSchema` |                        |
| \\                               | `PolicyBillingLevel`   |
| \\                               | `PolicyBillingTrigger` |

**policy-snapshot-response.ts**

| Zod Schema                     | Type                     |
| ------------------------------ | ------------------------ |
| `policySnapshotResponseSchema` | `PolicySnapshotResponse` |

**policy-term-response.ts**

| Zod Schema                  | Type                        |
| --------------------------- | --------------------------- |
| `policyTermResponseSchema`  | `PolicyTermResponse`        |
| `policyTermSummaryResponse` | `PolicyTermSummaryResponse` |

**policy-term-schemas.ts**

| Zod Schema                | Type                |
| ------------------------- | ------------------- |
| `documentSummarySchema`   | `DocumentSummary`   |
| `elementSummarySchema`    | `ElementSummary`    |
| `subsegmentSummarySchema` | `SubsegmentSummary` |

**term-schemas.ts**

| Zod Schema                | Type                |
| ------------------------- | ------------------- |
| `documentSummarySchema`   | `DocumentSummary`   |
| `elementSummarySchema`    | `ElementSummary`    |
| `subsegmentSummarySchema` | `SubsegmentSummary` |
| \\                        | `DocumentState`     |
| \\                        | `DocumentReference` |

**term-summary.ts**

| Zod Schema          | Type          |
| ------------------- | ------------- |
| `termSummarySchema` | `TermSummary` |

**transaction-snapshot-response.ts**

| Zod Schema                          | Type                          |
| ----------------------------------- | ----------------------------- |
| `segmentResponseSchema`             | `SegmentResponse`             |
| `transactionSnapshotResponseSchema` | `TransactionSnapshotResponse` |

**transaction-underwriting-response.ts**

| Zod Schema                             | Type                                   |
| -------------------------------------- | -------------------------------------- |
| `transactionUnderwritingFlagsResponse` | `TransactionUnderwritingFlagsResponse` |

Quotes [#quotes]

**quote-price-response.ts**

| Zod Schema                       | Type                       |
| -------------------------------- | -------------------------- |
| `quotePriceChargeCategoryEnum`   |                            |
| `quotePriceChargeResponseSchema` | `QuotePriceChargeResponse` |
| `quotePriceResponseSchema`       | `QuotePriceResponse`       |
| \\                               | `QuotePriceChargeCategory` |

**quote-request.ts**

| Zod Schema           | Type           |
| -------------------- | -------------- |
| `quoteRequestSchema` | `QuoteRequest` |

**quote-schemas.ts**

| Zod Schema                      | Type                  |
| ------------------------------- | --------------------- |
| `quoteStateSchema`              | `QuoteState`          |
| `quoteBillingTriggerEnumSchema` |                       |
| `quoteBillingLevelEnumSchema`   |                       |
| \\                              | `QuoteBillingTrigger` |
| \\                              | `QuoteBillingLevel`   |

**quote-underwriting-response.ts**

| Zod Schema                       | Type                             |
| -------------------------------- | -------------------------------- |
| `quoteUnderwritingFlagsResponse` | `QuoteUnderwritingFlagsResponse` |

**reset-quote-request.ts**

| Zod Schema                        | Type                    |
| --------------------------------- | ----------------------- |
| `resetQuoteFlagsActionEnumSchema` |                         |
| `resetQuoteRequestSchema`         | `ResetQuoteRequest`     |
| \\                                | `ResetQuoteFlagsAction` |

Shared [#shared]

**anchor-mode.ts**

| Zod Schema             | Type         |
| ---------------------- | ------------ |
| `anchorModeEnumSchema` |              |
| \\                     | `AnchorMode` |

**anchor-type.ts**

| Zod Schema             | Type         |
| ---------------------- | ------------ |
| `anchorTypeEnumSchema` |              |
| \\                     | `AnchorType` |

**billing-level.ts**

| Zod Schema               | Type           |
| ------------------------ | -------------- |
| `billingLevelEnumSchema` |                |
| \\                       | `BillingLevel` |

**cadence.ts**

| Zod Schema          | Type      |
| ------------------- | --------- |
| `cadenceEnumSchema` |           |
| \\                  | `Cadence` |

**currencies.ts**

| Zod Schema           | Type           |
| -------------------- | -------------- |
| `currencyEnumSchema` |                |
| \\                   | `CurrencyType` |

**days.ts**

| Zod Schema              | Type          |
| ----------------------- | ------------- |
| `dayOfWeekEnumSchema`   |               |
| `weekOfMonthEnumSchema` |               |
| \\                      | `DayOfWeek`   |
| \\                      | `WeekOfMonth` |

**document-reference-type.ts**

| Zod Schema                        | Type                |
| --------------------------------- | ------------------- |
| `documentReferenceTypeEnumSchema` |                     |
| \\                                | `DocumentReference` |

**document-state.ts**

| Zod Schema                | Type            |
| ------------------------- | --------------- |
| `documentStateEnumSchema` |                 |
| \\                        | `DocumentState` |

**element-request.ts**

| Zod Schema                   | Type                   |
| ---------------------------- | ---------------------- |
| `elementCreateRequestSchema` | `ElementCreateRequest` |
| `elementRequestSchema`       | `ElementRequest`       |

**element-response.ts**

| Zod Schema              | Type              |
| ----------------------- | ----------------- |
| `elementResponseSchema` | `ElementResponse` |

**field-values.ts**

| Zod Schema | Type             |
| ---------- | ---------------- |
| \\         | `PrimitiveValue` |
| \\         | `DataFieldValue` |

**preferences-response.ts**

| Zod Schema                  | Type                  |
| --------------------------- | --------------------- |
| `preferencesResponseSchema` | `PreferencesResponse` |

**timezones.ts**

| Zod Schema           | Type           |
| -------------------- | -------------- |
| `timezoneEnumSchema` |                |
| \\                   | `TimezoneType` |

**underwriting-flag-response.ts**

| Zod Schema                       | Type                       |
| -------------------------------- | -------------------------- |
| `underwritingFlagEnumSchema`     | `UnderwritingFlagEnum`     |
| `underwritingFlagResponseSchema` | `UnderwritingFlagResponse` |

**underwriting-flags-request.ts**

| Zod Schema                             | Type                             |
| -------------------------------------- | -------------------------------- |
| `underwritingFlagCreateRequestSchema`  | `UnderwritingFlagCreateRequest`  |
| `underwritingFlagsUpdateRequestSchema` | `UnderwritingFlagsUpdateRequest` |

**validation-result.ts**

| Zod Schema               | Type               |
| ------------------------ | ------------------ |
| `ulidSchema`             |                    |
| `validationItemSchema`   | `ValidationItem`   |
| `validationResultSchema` | `ValidationResult` |

Transactions [#transactions]

**add-change-instruction-create-request.ts**

| Zod Schema                                | Type                                |
| ----------------------------------------- | ----------------------------------- |
| `addChangeInstructionCreateRequestSchema` | `AddChangeInstructionCreateRequest` |

**add-change-instruction-response.ts**

| Zod Schema                           | Type                           |
| ------------------------------------ | ------------------------------ |
| `addChangeInstructionResponseSchema` | `AddChangeInstructionResponse` |

**delete-change-instruction-create-request.ts**

| Zod Schema                                   | Type                                   |
| -------------------------------------------- | -------------------------------------- |
| `deleteChangeInstructionCreateRequestSchema` | `DeleteChangeInstructionCreateRequest` |

**delete-change-instruction-response.ts**

| Zod Schema                              | Type                              |
| --------------------------------------- | --------------------------------- |
| `deleteChangeInstructionResponseSchema` | `DeleteChangeInstructionResponse` |

**modify-change-instruction-create-request.ts**

| Zod Schema                                   | Type                                   |
| -------------------------------------------- | -------------------------------------- |
| `modifyChangeInstructionCreateRequestSchema` | `ModifyChangeInstructionCreateRequest` |

**modify-change-instruction-response.ts**

| Zod Schema                              | Type                              |
| --------------------------------------- | --------------------------------- |
| `modifyChangeInstructionResponseSchema` | `ModifyChangeInstructionResponse` |

**params-change-instruction-create-request.ts**

| Zod Schema                                   | Type                                   |
| -------------------------------------------- | -------------------------------------- |
| `paramsChangeInstructionCreateRequestSchema` | `ParamsChangeInstructionCreateRequest` |

**params-change-instruction-response.ts**

| Zod Schema                              | Type                              |
| --------------------------------------- | --------------------------------- |
| `paramsChangeInstructionResponseSchema` | `ParamsChangeInstructionResponse` |

**policy-transaction-response.ts**

| Zod Schema                        | Type                        |
| --------------------------------- | --------------------------- |
| `policyTransactionResponseSchema` | `PolicyTransactionResponse` |

**reset-transaction-options-request.ts**

| Zod Schema                             | Type                             |
| -------------------------------------- | -------------------------------- |
| `resetTransactionOptionsRequestSchema` | `ResetTransactionOptionsRequest` |

**transaction-enums.ts**

| Zod Schema                      | Type                  |
| ------------------------------- | --------------------- |
| `transactionStateEnumSchema`    |                       |
| `transactionCategoryEnumSchema` |                       |
| \\                              | `TransactionCategory` |
| \\                              | `TransactionState`    |

**transaction-price-response.ts**

| Zod Schema                       | Type                       |
| -------------------------------- | -------------------------- |
| `transactionPriceResponseSchema` | `TransactionPriceResponse` |

**transaction-underwriting-response.ts**

| Zod Schema                              | Type                              |
| --------------------------------------- | --------------------------------- |
| `transactionUnderwritingResponseSchema` | `TransactionUnderwritingResponse` |


# EC React Utils



Utils for the Socotra Insurance Suite [#utils-for-the-socotra-insurance-suite]

This package provides a collection of shared helper functions used
throughout the Socotra EC ecosystem. These utilities handle common tasks
such as data extraction, transformation, default value generation, and
building API requests, serving as a foundational layer for the component
and application logic.

The library is organized by function, including:

* **Data Extraction:** Functions for safely extracting nested data from
  large, complex objects.
* **Default Value Getters:** Functions for generating default values for
  forms.
* **API Request Builders:** Functions for mapping form data to API
  request payloads.
* **Miscellaneous Helpers:** A variety of other useful functions for
  data manipulation and comparison.

***

Installation [#installation]

```sh
npm i @socotra/ec-react-utils
```

This package has peer dependencies on `@socotra/ec-react-schemas` and
`zod`, which you likely have installed already.

***

Usage [#usage]

Import any utility directly from the package:

```ts
import { extractElementByType } from '@socotra/ec-react-utils';

const element = extractElementByType(quote, 'my_element_type');
```

Available Utilities [#available-utilities]

Data Extraction [#data-extraction]

| Function                                | Description                                                                                                 | Returns                             |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `getAccountEvaluatedConstraintsRequest` | Creates a request payload to evaluate constraints for an account.                                           | `AccountEvaluateConstraintsRequest` |
| `extractElementByLocator`               | Extracts the first element from a policy, quote, or transaction segment that matches the specified locator. | `Element` or `undefined`            |
| `extractElementByType`                  | Extracts the first element from a policy, quote, or transaction segment that matches the specified type.    | `Element` or `undefined`            |
| `extractElementsByType`                 | Extracts all elements from a policy, quote, or transaction segment that match the specified type.           | `Element[]`                         |
| `extractElementDataModelFromQuote`      | Extracts the data model for a specific element type from a quote response.                                  | `object` or `undefined`             |
| `extractElementDataModelFromSegment`    | Extracts the data model for a specific element type from a transaction segment.                             | `object` or `undefined`             |
| `extractElementDataModelFromType`       | Extracts the data model for a specific element type from a policy response.                                 | `object` or `undefined`             |
| `extractElementsFromQuote`              | Extracts all elements from a quote’s exposures.                                                             | `Element[]`                         |
| `extractElementsFromTransactionSegment` | Extracts all elements from a transaction segment’s exposures.                                               | `Element[]`                         |
| `extractProductDataModel`               | Extracts the data model for a specific product from a policy or quote.                                      | `object` or `undefined`             |
| `extractProductElements`                | Extracts all elements associated with a product from a policy or quote.                                     | `Element[]`                         |
| `shouldEvaluateConstraints`             | Checks if the constraints should be evaluated based on the original and new data.                           | `boolean`                           |

Default Value Getters [#default-value-getters]

| Function                                 | Description                                                                     | Returns  |
| ---------------------------------------- | ------------------------------------------------------------------------------- | -------- |
| `getCoverageTermsDefaultValues`          | Generates default values for coverage terms based on the product configuration. | `object` |
| `getDefaultAccountFormValues`            | Generates default values for the account form.                                  | `object` |
| `getDefaultDraftTransactionValues`       | Generates default values for a new draft transaction form.                      | `object` |
| `getDefaultElementValues`                | Generates default values for an element based on its data model.                | `object` |
| `getDefaultInitializedTransactionValues` | Generates default values for an initialized transaction form.                   | `object` |
| `getDefaultPolicyValues`                 | Generates default values for a new policy.                                      | `object` |
| `getDefaultQuoteValues`                  | Generates default values for a new quote.                                       | `object` |

API Request Builders [#api-request-builders]

| Function                                              | Description                                                                        | Returns                                          |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------ |
| `getAccountRequest`                                   | Transforms form data into a request payload for creating or updating an account.   | `AccountCreateRequest` or `AccountUpdateRequest` |
| `getElementRequest`                                   | Transforms form data into a request payload for creating or updating an element.   | `ElementCreateRequest` or `ElementUpdateRequest` |
| `getEvaluatedConstraintsRequest`                      | Creates a request payload to evaluate constraints for a specific element.          | `EvaluateConstraintsRequest`                     |
| `getModifyChangeInstructionCreateRequestFromFormData` | Transforms form data into a request to modify a transaction’s change instructions. | `ModifyChangeInstructionCreateRequest`           |
| `getParamsChangeInstructionCreateRequestFromFormData` | Transforms form data into a request to update the parameters of a transaction.     | `ParamsChangeInstructionCreateRequest`           |
| `getElementTransactionUpdateRequestFromFormData`      | Transforms form data into a request to update an element within a transaction.     | `ElementTransactionUpdateRequest`                |
| `getPolicyRequest`                                    | Transforms form data into a request payload for creating a new policy.             | `PolicyCreateRequest`                            |
| `getQuoteRequest`                                     | Transforms form data into a request payload for creating or updating a quote.      | `QuoteRequest`                                   |

Miscellaneous [#miscellaneous]

| Function                        | Description                                                                                | Returns                                |
| ------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------- |
| `compareData`                   | Compares two data objects and returns a list of differences.                               | `Diff[]`                               |
| `dataModelToJSONSchema`         | Converts a Socotra data model into a JSON schema for form generation.                      | `JSONSchema7`                          |
| `getElementNameByType`          | Retrieves the display name of an element based on its type from the product configuration. | `string`                               |
| `getRemoveDataFieldValues`      | Identifies fields that should be removed from a data object based on a comparison.         | `object`                               |
| `getUpdatedDataFromConstraints` | Applies the results of a constraint evaluation to a data object.                           | `object`                               |
| `parseToPrimitive`              | Safely parses a string into a boolean, number, or returns the original string.             | `string \| number \| boolean`          |
| `splitInputAndQuantifier`       | Splits a string into its core name and a quantifier suffix (e.g., `?`, `*`).               | `{ name: string; quantifier: string }` |
| `translateError`                | Translates a validation error object into a human-readable string.                         | `string`                               |


# Socotra Assistant Actions























The [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations) features a sidebar for the [Socotra Assistant](./overview.mdx), which includes a set of buttons that perform common underwriting tasks called actions. Some actions are executed by the Socotra Assistant, while others are executed without AI assistance.

The following actions are available within the Socotra Assistant sidebar:

* Extract fields from documents
* Check for missing or invalid fields
* Check underwriting rules
* Generate underwriting insights
* Create necessary documents
* Price risk
* Create underwriting summary
* Bind quote
* Issue policy

Follow the instructions [here](./getting-started.mdx) to get started with the Socotra Assistant.

Actions [#actions]

Extract fields from documents [#extract-fields-from-documents]

<img alt="Extract fields from documents" src={__img0} placeholder="blur" />

This action allows you to upload typed or hand-written documents, such as ACORD forms, and the Socotra Assistant will send them to AWS Textract, which will extract the document data. The assistant will then automatically add the extracted data to your quote, eliminating the need for underwriters to add data to quotes manually.

Once the process is complete, details about the extracted data will be displayed within the action panel.

Files must be in one of the following formats: .pdf, .png, .jpg, .jpeg, .tif, .tiff, .csv, .txt. You can upload up to 10 files at once.

Check for missing or invalid fields [#check-for-missing-or-invalid-fields]

<img alt="Check for missing or invalid fields" src={__img1} placeholder="blur" />

This action performs default validation checks and executes the [Validation Plugin](/configuration/plugins/validation) if it has been implemented.

Once the process is complete, the validation results will be displayed within the action panel, and you can ask the Socotra Assistant [chatbot](#chat) to help fix validation issues.

For example:

<img alt="Validation Example" src={__img2} placeholder="blur" />

Check underwriting rules [#check-underwriting-rules]

<img alt="Check underwriting rules" src={__img3} placeholder="blur" />

This action executes the [Underwriting Plugin](/configuration/plugins/underwriting) statelessly if it has been implemented. If the plugin has not been implemented, the quote will automatically pass this underwriting check. No AI is used for this action.

Once the process is complete, the results of the underwriting check will be displayed within the action panel.

Generate underwriting insights [#generate-underwriting-insights]

<img alt="Generate underwriting insights" src={__img4} placeholder="blur" />

This action analyzes your quote against a set of risk assessment criteria. You can upload a document containing risk assessment criteria by following the instructions below:

1. Navigate to the *System Manager* tab at the top of the page.
2. Click on *Tenants*.
3. Select a tenant.
4. Navigate to the *Assistant Configuration* tab on the left side of the page.
5. Select your product in the dropdown menu underneath the *Assistant Configuration* label.
6. Click the *Risk Assessment Criteria* tab.
7. Click the *Upload Document* button to upload a document.
8. You can edit documents using markdown formatting in the *Write* tab, and preview the final document formatting in the *Preview* tab.
9. Click the *Save* button at the bottom of the page once your changes are complete.

Files must be in .md format. You can only upload one file at a time.

Return to the Socotra Assistant sidebar and click the *Generate* button. Once the process is complete, the results of the analysis will be displayed within the action panel. Each result may contain buttons that can be used to perform relevant actions based on the result.

Create necessary documents [#create-necessary-documents]

<img alt="Create necessary documents" src={__img5} placeholder="blur" />

This action creates documents based on document templates. The Socotra Assistant will automatically add quote data to the documents. You can upload document templates by following the instructions below:

1. Navigate to the *System Manager* tab at the top of the page.
2. Click on *Tenants*.
3. Select a tenant.
4. Navigate to the *Assistant Configuration* tab on the left side of the page.
5. Select your product in the dropdown menu underneath the *Assistant Configuration* label.
6. Click the *Document Templates* tab.
7. Select a document type.
8. Click the *Upload Document* button to upload a document.
9. You can edit documents using markdown formatting in the *Write* tab, and preview the final document formatting in the *Preview* tab.
10. Click the *Save* button at the bottom of the page once your changes are complete.

Files must be in .md format. You can only upload one file at a time.

Return to the Socotra Assistant sidebar and click the *Draft* button. Once the process is complete, you can download your documents by clicking the *Download documents* button.

Price risk [#price-risk]

<img alt="Price risk" src={__img6} placeholder="blur" />

This action executes the [Rating Plugin](/configuration/plugins/rating) if it has been implemented. If the plugin has not been implemented, this action will fail. No AI is used for this action.

Create underwriting summary [#create-underwriting-summary]

<img alt="Create underwriting summary" src={__img7} placeholder="blur" />

This action creates an editable underwriting summary.

Once the process is complete, you can edit the summary, then save the summary to your notes by clicking the *Save to notes* button. Once the note has been saved, you can view the note by clicking the *View notes* button. Embedded work management must be enabled before using the notes feature.

Click the down arrow next to the *Notes* label at the top of the sidebar, then click *Socotra Assistant* to return to the Socotra Assistant.

Bind quote [#bind-quote]

<img alt="Bind quote" src={__img8} placeholder="blur" />

This action moves the quote to the `accepted` state. No AI is used for this action.

Issue policy [#issue-policy]

<img alt="Issue policy" src={__img9} placeholder="blur" />

This action moves the quote to the `issued` state and creates a policy. No AI is used for this action.

<span id="chat" />

Chat [#chat]

You can chat directly with the Socotra Assistant and ask it to perform additional tasks by clicking on the *Chat* tab in the sidebar. The chatbot uses Socotra [MCP server](/ai-guide/mcp-server/overview) tools to respond to prompts.

Here are a few example prompts:

“Copy data from a similar quote to this quote.”

“Recommend values for these fields, and add the recommended values to the quote.”

“Identify any potential issues with this quote.”

Next Steps [#next-steps]

* [Email Intake Workflow](./email-intake.mdx)

See Also [#see-also]

* [Socotra Assistant Overview](./overview.mdx)
* [Socotra Assistant Setup Guide](./setup.mdx)
* [Socotra Assistant Getting Started Guide](./getting-started.mdx)
* [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations)
* [MCP Server](/ai-guide/mcp-server/overview)


# Email Intake Workflow



















The Socotra Assistant can intercept emails and extract email data to assist with the underwriting process. This AI-assisted email intake workflow supports the following automated functionality:

* Automatically create tasks from inbound emails
* Pre-populate quote fields from submission emails
* Resolve data conflicts and validation errors by emailing brokers directly

<Callout type="warn">
  Before proceeding with this guide, contact your Socotra representative to configure the email intake workflow for your business account.
</Callout>

Creating Tasks [#creating-tasks]

When the Socotra Assistant intercepts an email related to a new quote, a new [task](/features/work-management/tasks) will be created and auto-assigned to an underwriter based on the contents of the email and the email attachments. The task type and [workgroup](/features/work-management/workgroups) used for auto-assignment are determined by the [intent plans](/configuration/general-topics/assistant#intent-plans) defined in the [Socotra Assistant configuration](/configuration/general-topics/assistant) for your tenant.

This task will appear in the *Task Dashboard* for your tenant. You can view the *Task Dashboard* by navigating to the [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations) and selecting a tenant.

<img alt="Task Dashboard" src={__img0} placeholder="blur" />

The email address of the sender will be displayed underneath the task name, a *New* tag will be displayed next to the task name, and the *Associated Work Items* column will contain an *Inquiry*.

<Callout>
  The *New* tag is only used for tasks created by the Socotra Assistant.
</Callout>

Click on the task name to open the task sidebar.

The task sidebar contains an overview of the task, in addition to the *Details* and *Activity* tabs.

<img alt="Task Sidebar" src={__img1} placeholder="blur" />

The *Activity* tab contains the email and email attachments. You can view attachment contents by clicking on an attachment.

The *Details* tab contains a *Product* field and an *Account Type* field that will be associated with a new quote. These fields will be pre-populated by the Socotra Assistant based on the contents of the email and email attachment, and can be modified if necessary.

Once you're satisfied with the *Product* and *Account Type*, click the *Find or create account* button.

The *Account selection* tab will display a list of accounts that most closely match the contents of the email and email attachments. You can search for additional accounts or create a new account if necessary. Accounts must be in the `validated` state in order to proceed. For accounts in the `draft` state, fill out the account fields and click the *Save* button to validate the account.

<img alt="Account Selection" src={__img2} placeholder="blur" />

Select a validated account and click the *Create Quote* button.

Adding Email Data to a Quote [#adding-email-data-to-a-quote]

Once the quote is created, the Socotra Assistant will automatically execute the *Import* action and begin importing the email and email attachments. Once the process is complete, quote fields will be automatically populated based on the contents of the email and email attachments, and the results of the process will be added to the *Conflicts*, *Low Confidence*, and *Extracted* dropdowns. You can manually upload additional documents and modify quote fields if necessary.

<img alt="Import" src={__img3} placeholder="blur" />

<Callout>
  Quote fields cannot be modified while the Socotra Assistant is executing the *Import* action.
</Callout>

Resolving Data Conflicts [#resolving-data-conflicts]

Click the *Conflicts* dropdown and select one of the options displayed under the relevant quote field. Click the *Resolve* button to mark the conflict as resolved. The Socotra Assistant will continue to display additional conflicts until all conflicts are marked as resolved. The file names containing the sources of each conflict are displayed in the *Conflicts* tab. The `body.txt` file refers to the contents of the email. You can view attachment contents by clicking on an attachment.

<img alt="Conflicts" src={__img4} placeholder="blur" />

Click the *Add to email* button and navigate to the *Compose* tab to draft an email asking for the information in question. Click the *Add* button, and select the relevant items to include in the email, then click the *Compose email* button to generate a draft. Click the *Enhance draft* dropdown for additional AI-assisted drafting functionality. The contents of the email can be modified manually if necessary. Click the *Send* button to send the email.

<img alt="Compose Email" src={__img5} placeholder="blur" />

Once the system intercepts a reply to this email, the relevant conflicts will be automatically marked as resolved, and the corresponding fields will be updated based on the contents of the email. You may need to reload the page to see the changes take effect.

You can view the email chain history by navigating to the *Activity* tab.

<img alt="Activity" src={__img6} placeholder="blur" />

In the *Actions* tab, click the *Low Confidence* dropdown and select dropdown items to view potentially inaccurate values along with the percentage of confidence in the accuracy of each value.

You can view all extracted data by clicking on the *Extracted* dropdown.

Resolving Validation Issues [#resolving-validation-issues]

Execute the *Validate* action by clicking the *Validate* button. Click the *Resolve in chat* functionality to fix a validation issue by chatting with the Socotra Assistant chatbot, or click the *Add to email* button and navigate to the *Compose* tab to draft an email asking for the information in question. Click the *Add* button, and select the relevant items to include in the email, then click the *Compose email* button to generate a draft. Click the *Enhance draft* dropdown for additional AI-assisted drafting functionality. The contents of the email can be modified manually if necessary. Click the *Send* button to send the email.

<img alt="Validation" src={__img7} placeholder="blur" />

See Also [#see-also]

* [Socotra Assistant Overview](./overview.mdx)
* [Socotra Assistant Setup Guide](./setup.mdx)
* [Socotra Assistant Getting Started Guide](./getting-started.mdx)
* [Socotra Assistant Actions](./actions.mdx)
* [Socotra Assistant Configuration](/configuration/general-topics/assistant)
* [Integrations Plugin](/configuration/plugins/integrations)
* [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations)


# Socotra Assistant Getting Started Guide



To get started with the [Socotra Assistant](./overview.mdx), follow the instructions below:

1. Complete the steps listed in the [setup guide](./setup.mdx).
2. Log in to the [Socotra Insurance Suite ](https://ui-ec-sandbox.socotra.com/en/operations).
3. Navigate to the *Operations Workbench* tab at the top of the page.
4. Select a tenant.
5. Navigate to the *Accounts* tab at the top of the page.
6. Select an account.
7. Select a quote. The Socotra Assistant only works with quotes that are not yet in the `issued` state.
8. Click the black *Socotra Assistant* icon on the right side of the page.
9. The Socotra Assistant sidebar will appear.

Next Steps [#next-steps]

* [Socotra Assistant Actions](./actions.mdx)

See Also [#see-also]

* [Socotra Assistant Overview](./overview.mdx)
* [Socotra Assistant Setup Guide](./setup.mdx)
* [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations)


# Socotra Assistant Overview



The Socotra Assistant is an AI-powered agent that automates the underwriting workflow within the Operations Workbench and performs tasks such as extracting data from documents, checking for missing or invalid data, and generating underwriting insights.

The [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations) features a sidebar for the Socotra Assistant, which includes a set of buttons that perform common underwriting tasks called [actions](./actions.mdx). The sidebar also includes a chatbot that can be used to instruct the assistant to perform additional tasks.

While the assistant is designed to minimize the need for manual intervention, the assistant is an entirely optional feature, and underwriters always have the option to perform underwriting tasks as they normally would. The assistant will never perform an action without human approval.

Follow the instructions [here](./getting-started.mdx) to get started with the Socotra Assistant.

<Callout>
  Currently, the Socotra Assistant only performs tasks related to underwriting quotes. In future releases, the assistant will also support post-issuance workflows, such as renewals, cancellations, and endorsements.
</Callout>

Security [#security]

Your data will never be used to train models, and your data will never be accessible to any other customers.

User Feedback [#user-feedback]

The Socotra Assistant can be configured to collect user feedback, which is used to improve the quality of the assistant for your organization only. We will only collect feedback if your organization has given us approval to do so. No feedback is collected by default.

Next Steps [#next-steps]

* [Socotra Assistant Setup Guide](./setup.mdx)

See Also [#see-also]

* [Socotra Assistant Getting Started Guide](./getting-started.mdx)
* [Socotra Assistant Actions](./actions.mdx)
* [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations)


# Socotra Assistant Setup Guide





Socotra Assistant is an AI-powered sidebar built into the [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations). It gives underwriters a set of AI-powered actions that handle the repetitive parts of the quote-to-bind workflow. It is a mature, setup-based capability that requires no code changes in order to be enabled within a customer's Socotra tenant.

During onboarding, Socotra will ask the customer to provide information about the types of documents that they want to extract data from, their underwriting risk assessment criteria, document templates, and underwriting summary template. Once all the relevant information is obtained from the customer, the Socotra AI team will typically complete setup within one week.

Onboarding Timeline Summary [#onboarding-timeline-summary]

<img alt="Onboarding Timeline Summary" src={__img0} placeholder="blur" />

Prerequisites [#prerequisites]

Before onboarding, customers must have an active Socotra tenant with a complete product configuration defined. If this prerequisite is not met, customers should contact their account executive to set up the tenant and complete product configuration before proceeding with the Socotra Assistant onboarding.

<Callout>
  Socotra Assistant is not enabled by default. The feature is controlled by a feature flag that will be enabled by the Socotra team during the onboarding process after environment selection is confirmed.
</Callout>

Onboarding Process [#onboarding-process]

Step 1: Information Collection [#step-1-information-collection]

The Socotra team will schedule a kickoff meeting with the customer to gather requirements for feature enablement and setup. The following information will be collected:

**Environment Selection & Setup**

* Rollout strategy: Enable for all users within the tenant or limit to a smaller group initially? If limiting access, identify which specific roles and users should have access to the assistant panel so permissions can be configured appropriately.

**Document Extraction**

* Document types to be processed. We currently support the following file formats: .pdf, .png, .jpg, .jpeg, .tif, .tiff, .csv, and .txt.
* Requirements for mapping extracted fields to the customer's product configuration and data model defined in their Socotra tenant.

**Underwriting Risk Assessment**

* Obtain the customer's underwriting risk assessment criteria document
* Critical vs. non-critical criteria categorization

**Draft Documents**

* Document templates (exclusion form, request for information, and underwriting summary are currently supported)

Step 2: Setup (1 Week) [#step-2-setup-1-week]

The Socotra team will enable the feature flag for the selected environment(s) and configure the Assistant based on the requirements gathered during the kickoff meeting. This process typically takes one week and includes:

* Feature flag enablement
* Document extraction prompt training and field mapping
* Risk assessment criteria upload
* Load document templates
* User access and permissions configuration
* Internal testing and validation

Step 3: Walkthrough & Training [#step-3-walkthrough--training]

After setup is complete, the Socotra team will lead a walkthrough session with the customer to demonstrate the Assistant capabilities, provide training on accessing and using the panel, and conduct hands-on testing. This session includes:

* Instructions for accessing the Socotra Assistant panel on draft quotes
* Overview of the Socotra Assistant interface and navigation
* Demonstration of each action's functionality
* Live testing with customer-provided sample documents and quotes
* User feedback mechanism demonstration
* Q\&A and troubleshooting guidance

Step 4: Production Use & Ongoing Feedback [#step-4-production-use--ongoing-feedback]

Following the walkthrough session, customers can begin using Socotra Assistant. The Socotra team will provide ongoing support through:

* Dedicated support channel for questions and issues
* Regular feedback collection to improve accuracy and performance
* Periodic check-ins to assess usage and identify optimization opportunities
* Configuration updates based on evolving customer needs

Enablement and Pricing [#enablement-and-pricing]

For questions about onboarding or pricing and to schedule a kickoff meeting, customers should contact their account executive.

Next Steps [#next-steps]

* [Socotra Assistant Getting Started Guide](./getting-started.mdx)

See Also [#see-also]

* [Socotra Assistant Actions](./actions.mdx)
* [Socotra Assistant Overview](./overview.mdx)
* [Operations Workbench ](https://ui-ec-sandbox.socotra.com/en/operations)


# MCP Server Getting Started Guide



Prerequisites [#prerequisites]

To get started using the Socotra MCP server, you'll need a valid Socotra business account and login credentials. Our MCP server uses OAuth 2.1 for authentication and authorization.
Contact your Socotra representative to request access for your business account.

Users must possess the required permissions and tenant assignments to perform certain actions through the Socotra MCP server.

Refer to our documentation on [Role-Based Access Control](/features/security/roles-and-permissions) for more information.

Installation [#installation]

The Socotra MCP server currently supports the following applications:

* [Cursor](#cursor)
* [Claude](#claude)
* [Codex](#codex)

<span id="cursor" />

Cursor [#cursor]

1. Download and install [Cursor ](https://cursor.com/en)
2. If you already have Cursor, make sure to update it to the latest version
3. Open Cursor
4. Click the *Open Settings* button in the upper right corner of the window (displayed as a gear icon)
5. Navigate to *MCP & Integrations > New MCP Server*
6. Paste this JSON into `mcp.json`:

```json
{
	"mcpServers": {
		"SocotraSandbox": {
			"url": "https://mcp-sandbox.socotra.com/mcp"
		}
	}
}
```

7. Save the file
8. Go back to the *MCP & Integrations* tab
9. You'll see `SocotraSandbox` listed in *MCP Tools*
10. Click the *Connect* button
11. The Socotra authentication page will open in your browser
12. Enter your business account name, followed by your username and password
13. Click the *Authorize* button
14. You should see a message indicating that authorization was successful
15. Open Cursor, and verify that the green circle appears next to `SocotraSandbox` listed in *MCP Tools*
16. Open a new chat by clicking the *Toggle AI Pane* button in the upper right corner of the window, then clicking the *Create a new chat* button
17. Click the *@Add Context* button
18. Select `mcp.json`
19. Cursor will now be able to use the Socotra MCP server as you send prompts

Refer to the [Cursor MCP configuration guide](https://cursor.com/docs/mcp) for more information.

<span id="claude" />

Claude [#claude]

1. Download and install [Claude Desktop ](https://claude.ai/download)
2. If you already have Claude Desktop, make sure to update it to the latest version
3. Install [Node.js and npm ](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
4. Open Claude Desktop

**Then, for pro accounts:**

5. Navigate to *Settings > Connectors*
6. Click the *Add custom connector* button
7. Set the name as Socotra and the URL as `https://mcp-sandbox.socotra.com/mcp`
8. Click the *Add* button
9. Click the *Connect* button
10. The Socotra authentication page will automatically open in your browser
11. Enter your Business Account name, followed by your username and password
12. Click the *Authorize* button
13. You should see a message indicating that authorization was successful
14. Open Claude Desktop
15. Open a new chat by clicking the *New chat* button
16. Click the *Search and tools* button
17. You should see the Socotra MCP server toggled on
18. Click on the Socotra MCP server to view available tools and toggle them as needed
19. Claude will now be able to use the Socotra MCP server as you send prompts

**Or, for free accounts:**

5. Navigate to *Settings > Developer*
6. Click the *Edit config* button
7. Paste this JSON into `claude_desktop_config.json`:

```json
{
	"mcpServers": {
		"Socotra": {
			"command": "npx",
			"args": ["-y", "mcp-remote", "https://mcp-sandbox.socotra.com/mcp"]
		}
	}
}
```

8. Save the file
9. Restart Claude Desktop
10. The Socotra authentication page will automatically open in your browser
11. Enter your Business Account name, followed by your username and password
12. Click the *Authorize* button
13. You should see a message indicating that authorization was successful
14. Open Claude Desktop
15. Open a new chat by clicking the *New chat* button
16. Click the *Search and tools* button
17. You should see the Socotra MCP server toggled on
18. Click on the Socotra MCP server to view available tools and toggle them as needed
19. Claude will now be able to use the Socotra MCP server as you send prompts

Refer to the [Claude MCP configuration guide](https://code.claude.com/docs/en/mcp-quickstart) for more information.

<span id="codex" />

Codex [#codex]

1. Install [Codex](https://learn.chatgpt.com/docs/codex/cli#getting-started)
2. If you already have Codex, make sure to update it to the latest version
3. Open the Codex configuration file by executing the following command from your terminal:

```
~/.codex/config.toml
```

4. Add the following lines to the file:

```
[mcp_servers.SocotraSandbox]
url = "https://mcp-sandbox.socotra.com/mcp"
```

5. Save the file
6. Log in to the Socotra Sandbox environment by executing the following command from your terminal:

```
codex mcp login SocotraSandbox
```

7. Codex will display an authorization link
8. Open the link in a web browser and enter the following information: Business account name, username, and password
9. Verify your connection by executing the following command from your terminal:

```
codex mcp list
```

10. Restart Codex

Refer to the [Codex MCP configuration guide](https://learn.chatgpt.com/docs/extend/mcp?surface=app) for more information.

Next Steps [#next-steps]

* [MCP Server Prompt Examples](./prompt-examples.mdx)

See Also [#see-also]

* [MCP Server Overview](/ai-guide/mcp-server/overview)
* [MCP Server Tools](./tools.mdx)


# MCP Server Overview



Model Context Protocol (MCP) is a free, open-source standard for connecting AI applications with external tools and data sources. This allows software systems like Socotra to provide LLM functionality to users in a secure way.

The Socotra MCP server connects AI applications like Claude and Cursor with data and functionality from the Socotra API, allowing users to manage their work more effectively by integrating their business accounts with AI applications.
Users can automate tasks and perform analysis based on data from their business accounts, documents like emails or spreadsheets, or publicly available data.

Overview [#overview]

Our MCP server provides two-way communication between the Socotra API and MCP clients embedded within AI applications, empowering users to build complex workflows with LLMs.

The Socotra MCP Server can be used to systematically review policy data and create tasks for human follow-up. You can:

* Search for policies using various criteria
* Review policy summaries and transaction details
* Create and update transactions, such as adding coverage or renewing a policy
* Create tasks for any policies that need attention or follow-up
* Assign tasks to appropriate users based on their qualifications
* Update tasks as work progresses

When users enter a prompt in an AI application, the LLM determines which MCP server tools to use, executes those tools using the MCP client, and then receives a response from the MCP server.
The LLM uses this response to generate a natural language response.

Next Steps [#next-steps]

* [MCP Server Tools](./tools.mdx)

See Also [#see-also]

* [MCP Server Getting Started Guide](./getting-started.mdx)
* [MCP Server Prompt Examples](./prompt-examples.mdx)


# MCP Server Prompt Examples



Here's a sequence of example prompts to help you explore the tools supported by the Socotra MCP server.

"Tell me about my tenant assignments. For each tenant, identify the line of business based on the account types and policy patterns you find."

"Find the most complex or highest-premium policy across my tenants. Analyze its coverage structure, identify any coverage gaps or unusual risk exposures, and assess whether the premium adequately reflects the risk profile based on the policy elements."

"Based on your analysis, determine what type of transaction would be most appropriate for this policy (endorsement, renewal, cancellation, etc.) and explain your reasoning. Then create the transaction with an effective date that makes business sense given the policy's current state."

"Analyze this policy's transaction history and current coverage terms. Identify any compliance issues, coverage redundancies, underwriting concerns, or premium calculation discrepancies. Prioritize these issues by severity and business impact, then suggest transactions to address the most critical problems."

"Review my current task load, and create a prioritized task for the most qualified senior underwriter to review these policy changes. Set an appropriate deadline based on the complexity of changes made and any regulatory requirements. Include a detailed task description that highlights the key issues found and changes implemented."

See Also [#see-also]

* [MCP Server Overview](/ai-guide/mcp-server/overview)
* [MCP Server Tools](./tools.mdx)
* [MCP Server Getting Started Guide](./getting-started.mdx)


# MCP Server Tools



Tools allow AI applications to access specific functionality within the Socotra Insurance Suite through our public API endpoints.

The following are tools supported by the Socotra MCP server:

Account and Policy Management [#account-and-policy-management]

* **Get Policy Summary** - Get the summary of a policy for a tenant
* **Get Accounts for Tenant** - Retrieve a list of accounts for a given tenant
* **Create Account** - Create a new account in a tenant
* **Get Policies by Account** - Get all policies associated with a specific account

Quote Management [#quote-management]

* **Get Quote Summary** - Get the summary of a quote for a tenant
* **Create Quote** - Create a quote for an account
* **Add Quote Elements** - Add elements to a draft quote
* **Update Quote** - Update existing elements in a draft quote, and validate or price it
* **Underwrite Quote** - Underwrite a priced quote
* **Issue Quote** - Issue an underwritten or accepted quote

Transaction Management [#transaction-management]

* **Create Transaction** - Create a transaction for a policy
* **Update Transaction** - Update elements in an existing transaction
* **Add Transaction Elements** - Add new elements to a draft transaction
* **Remove Transaction Elements** - Remove elements from a draft transaction

Work Management [#work-management]

* **Get Assigned Tasks** - Get the tasks assigned to the current user
* **Create Task** - Create a task for a tenant
* **Update Task** - Update task details
* **Get Task** - Get a specific task by locator with its diary entries
* **Create Association** - Create a user association with a specific reference
* **Manage User Qualifications** - Get or update user qualifications
* **Append Diary Entry** - Add a diary entry to a task

User and Access Management [#user-and-access-management]

* **Who Am I** - Get information about the current user
* **Get Tenant Users** - Get all users assigned to a specific tenant
* **Get Assigned Tenants** - Get all tenants assigned to the current user

Search [#search]

* **Search** - Search for accounts, policies, and other entities across the system

Configuration and Deployment [#configuration-and-deployment]

* **Get Configuration Metadata** - Get deployment metadata for a tenant, including the latest deployed version and plugin status
* **Fetch Configuration Datamodel** - Fetch the latest configuration definition (data model) for a tenant
* **Download Config** - Download the tenant's deployed configuration, including the data model and plugin code
* **Download Bundle** - Download the deployment bundle for the tenant's currently deployed version
* **Create Deployment Token** - Create a token used to authenticate deployment requests

Next Steps [#next-steps]

* [MCP Server Getting Started Guide](./getting-started.mdx)

See Also [#see-also]

* [MCP Server Overview](/ai-guide/mcp-server/overview)
* [MCP Server Prompt Examples](./prompt-examples.mdx)


# Socotra Public Skills Example



import Image from 'next/image';

Claude Cowork Example [#claude-cowork-example]

Build a product using the following example prompt:

"Create a new Socotra configuration with a renters insurance product. Include an optional jewelry coverage with a maximum coverage of $10,000. We want to collect the following demographic information: First name, last name, optional middle name, address, date of birth, and gender."

<Image src="/images/public-skills/1.png" alt="Step 1" width={1999} height={1254} unoptimized />

Public skills use [Socotra MCP server tools](/ai-guide/mcp-server/tools) such as `Who Am I` and `Create Deployment Token` to deploy to your tenant. Make sure you haven't reached your [PAT](/features/security/personal-access-tokens) (Personal Access Token) limit, or tenant validation and deployment will fail.

<Image src="/images/public-skills/2.png" alt="Step 2" width={1999} height={1254} unoptimized />

You can choose to deploy to an existing tenant or a new tenant.

<Image src="/images/public-skills/3.png" alt="Step 3" width={1999} height={1254} unoptimized />

Your configuration can be found in the `Outputs` folder, along with a summary file describing the output and any open questions that need to be addressed.

<Image src="/images/public-skills/4.png" alt="Step 4" width={1999} height={1254} unoptimized />

Optionally, you can navigate to the [Operations Workbench](https://ui-ec-sandbox.socotra.com/en/operations) to create quotes and issue policies.

See Also [#see-also]

* [Socotra Public Skills Overview](./public-skills-overview)
* [Socotra Public Skills Getting Started Guide](./public-skills-getting-started.mdx)
* [MCP Server Overview](/ai-guide/mcp-server/overview)
* [Personal Access Tokens](/features/security/personal-access-tokens)
* [Operations Workbench](https://ui-ec-sandbox.socotra.com/en/operations)


# Socotra Public Skills Getting Started Guide



Prerequisites [#prerequisites]

AI Agents [#ai-agents]

Socotra public skills are compatible with any AI agent that supports remote MCP and Agent Skills, including Claude Code, Claude Cowork, Codex, and Cursor.

MCP Server [#mcp-server]

Your AI agent must be connected to the [Socotra MCP server](/ai-guide/mcp-server/overview). The MCP server can generate deployment tokens and list tenants. AI agents must have a deployment token before deploying to a tenant. Agents without access to the MCP server can still generate configurations and plugin implementations but cannot deploy to tenants.

Refer to the [MCP Server Getting Started Guide](/ai-guide/mcp-server/getting-started) for installation instructions.

Before getting started with [Socotra public skills](https://github.com/socotra/socotra-skills), you'll need a business account. You can access a business account and user credentials by navigating to [https://www.socotra.com/contact-us/](https://www.socotra.com/contact-us/) and filling out the form to speak to a representative and book a demo. Alternatively, you can send an email to [sandbox@socotra.com](mailto:sandbox@socotra.com).

Installation [#installation]

Claude Code [#claude-code]

Skills can be installed through a terminal in Claude Code or a standard terminal.

Install Skills Through a Terminal in Claude Code [#install-skills-through-a-terminal-in-claude-code]

```
/plugin marketplace add socotra/ai-configuration-skills
/plugin install socotra-skills@socotra
```

Install Skills Through a Standard Terminal [#install-skills-through-a-standard-terminal]

```
claude plugin marketplace add socotra/ai-configuration-skills
claude plugin install socotra-skills@socotra
```

Add the `--scope project` flag to share the installation with your team for a given project. If you want to experiment with skills without installing anything, clone the repository and run `claude --plugin-dir /path/to/ai-configuration-skills`.

Claude Cowork [#claude-cowork]

1. Navigate to the [Socotra Skills repository](https://github.com/socotra/socotra-skills)
2. Download the ZIP file
3. Follow the instructions [here](https://support.claude.com/en/articles/13837440-use-plugins-in-claude) to upload the ZIP file

Cursor [#cursor]

1. Navigate to the [Socotra Skills repository](https://github.com/socotra/socotra-skills)
2. Download the ZIP file
3. Copy the `skill` directory to `~/.cursor/skills/`
4. Copy the `.mdc` file to `~/.cursor/rules/`
5. Add the [Socotra MCP server configuration](/ai-guide/mcp-server/getting-started#cursor) to `~/.cursor/mcp.json`

Other AI Agents [#other-ai-agents]

Clone the [Socotra Skills repository](https://github.com/socotra/socotra-skills) and point your agent at `AGENTS.md`. This file contains the step order and the path to the rules for each step. Every file below it is in plain Markdown.

* Codex and anything else that reads AGENTS.md - Nothing to configure
* Cursor — `.cursor/rules/socotra.mdc` points at `AGENTS.md`
* Claude Code from a clone — `CLAUDE.md` points at `AGENTS.md`
* Anything else with file system access — Tell it to read `AGENTS.md` first

Next Steps [#next-steps]

* [Socotra Public Skills Example](./public-skills-example.mdx)

See Also [#see-also]

* [Socotra Public Skills Overview](./public-skills-overview)
* [MCP Server Overview](/ai-guide/mcp-server/overview)
* [Socotra Skills Repository](https://github.com/socotra/socotra-skills)


# Socotra Public Skills Overview



[Socotra public skills](https://github.com/socotra/socotra-skills) transform insurance product descriptions into working products, including tenant configurations, data models, and plugin implementations for validation, pricing, and underwriting using AI agents and the [Socotra MCP server](/ai-guide/mcp-server/overview). Our public skills are designed to facilitate rapid exploration of features within the Socotra platform. New products and changes to existing products can be deployed directly to a live test tenant within minutes and without the need for manual configuration.

Skills [#skills]

| Skills               | Description                                                                                                                                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| socotra              | Orchestrates the entire process of building a working product end-to-end                                                                                                                            |
| socotra-config       | Builds the `socotra-config` folder based on your conversation with the agent, including the product structure, coverages, and account type                                                          |
| socotra-deploy       | Deploys a `socotra-config` folder to a Socotra test tenant and gives you the option of selecting an existing tenant or creating a new one                                                           |
| socotra-rating       | Generates a [Rating Plugin](/configuration/plugins/rating) implementation that prices a Socotra product using simple logic (Includes flat rates, switches, and band maps)                           |
| socotra-underwriting | Generates an [Underwriting Plugin](/configuration/plugins/underwriting) implementation that adds underwriting flags based on product rules, such as risk exclusions or referral conditions          |
| socotra-validation   | Generates a [Validation Plugin](/configuration/plugins/validation) implementation that rejects a quote or account when it violates a business rule that can't be captured in a tenant configuration |
| create-tenant        | Creates a new tenant using a validated tenant configuration                                                                                                                                         |

Self-Healing [#self-healing]

If your AI agent creates a configuration or plugin implementation that fails to pass validation rules or can't be deployed, it will automatically attempt to resolve issues up to 5 times per configuration per plugin. If issues remain after the 5th attempt, it will stop and inform the user. The user can then ask it to try another 5 times, or the user can resolve issues manually and upload the fixed configuration or plugin implementation to the agent.

Limitations [#limitations]

* Make sure you haven't reached your [PAT](/features/security/personal-access-tokens) (Personal Access Token) limit, or tenant validation and deployment will fail.
* AI agents will make assumptions. If agents are not given explicit instructions, they will attempt to add missing information without asking first.
* AI agents can generate implementations for plugins that aren't included in the above list of skills, but they will not have access to relevant plugin-specific public skills when generating implementations.
* While it's possible to use public skills when the Socotra MCP server is unavailable, plugin implementations generated this way likely won't have the necessary custom classes and will need manual adjustments before they're production-ready.

Next Steps [#next-steps]

* [Socotra Public Skills Getting Started Guide](./public-skills-getting-started.mdx)

See Also [#see-also]

* [Socotra Public Skills Example](./public-skills-example.mdx)
* [MCP Server Overview](/ai-guide/mcp-server/overview)
* [Personal Access Tokens](/features/security/personal-access-tokens)


# Aux Data API



<EndpointIndex
  names={[
  	'getAuxDataKeys',
  	'getAuxData',
  	'putAuxData',
  	'deleteAuxData',
  	'getAuxDataSize',
  ]}
  titles={{
  	getAuxDataKeys: 'Fetch Aux Data Keys for a Locator',
  	getAuxData: 'Fetch Aux Data',
  	putAuxData: 'Add Aux Data',
  	deleteAuxData: 'Delete Aux Data',
  	getAuxDataSize: 'Get the Size of Aux Data for a Tenant',
  }}
/>

Fetch Aux Data Keys for a Locator [#fetch-aux-data-keys-for-a-locator]

<ApiEndpoint name="getAuxDataKeys" title="Fetch Aux Data Keys for a Locator" />

<ApiSchema name="AuxDataKeySetResponse" />

<ApiSchema name="AuxDataKey" />

Fetch Aux Data [#fetch-aux-data]

<ApiEndpoint name="getAuxData" title="Fetch Aux Data" />

<ApiSchema name="AuxDataResponse" />

Add Aux Data [#add-aux-data]

<ApiEndpoint name="putAuxData" title="Add Aux Data" />

<ApiSchema name="AuxDataSetCreateRequest" />

<ApiSchema name="AuxDataSet" />

Delete Aux Data [#delete-aux-data]

<ApiEndpoint name="deleteAuxData" title="Delete Aux Data" />

Get the Size of Aux Data for a Tenant [#get-the-size-of-aux-data-for-a-tenant]

<ApiEndpoint name="getAuxDataSize" title="Get the Size of Aux Data for a Tenant" />

<ApiSchema name="AuxDataSizeResponse" />


## API Reference

GET /auxdata/{tenantLocator}/auxdata/{locator} — getAuxDataKeys
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (string, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 AuxDataKeySetResponse — OK

GET /auxdata/{tenantLocator}/auxdata/{locator}/{key} — getAuxData
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (string, path, required)
  key (string, path, required)
Responses:
  200 AuxDataResponse — OK

PUT /auxdata/{tenantLocator}/auxdata/{locator} — putAuxData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (string, path, required)
Request body (AuxDataSetCreateRequest):
Responses:
  200 — OK

DELETE /auxdata/{tenantLocator}/auxdata/{locator}/{key} — deleteAuxData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (string, path, required)
  key (string, path, required)
Responses:
  200 — OK

GET /auxdata/{tenantLocator}/auxdata/size — getAuxDataSize
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 AuxDataSizeResponse — OK

AuxDataKeySetResponse
Properties:
  offset (integer, required)
  count (integer, required)
  keys (AuxDataKey[], required)

AuxDataKey
Properties:
  key (string, required)
  uiType (Enum normal | hidden | readonly, required)
  auxDataSettingsName (string)

AuxDataResponse
Properties:
  locator (string, required)
  key (string, required)
  uiType (Enum normal | hidden | readonly, required)
  value (string, required)
  modificationTimestamp (datetime, required)
  expirationTimestamp (datetime)
  auxDataSettingsName (string)

AuxDataSetCreateRequest
Properties:
  auxDataSettingsName (string)
  auxData (AuxDataSet[], required)

AuxDataSet
Properties:
  uiType (Enum normal | hidden | readonly, required)
  key (string, required)
  value (string, required)

AuxDataSizeResponse
Properties:
  dataSizeKb (integer, required)

# Diary API



<EndpointIndex
  names={[
  	'fetchLatestDiaryEntryByLocator',
  	'fetchLatestDiaryEntriesByReference',
  	'fetchAllDiaryEntriesByLocator',
  	'createDiary',
  	'createDiaryForSegmentElement',
  	'createDiaryForQuoteElement',
  	'updateDiary',
  	'discardDiary',
  ]}
/>

Fetch [#fetch]

Fetch Latest Diary Entry By Locator [#fetch-latest-diary-entry-by-locator]

<ApiEndpoint name="fetchLatestDiaryEntryByLocator" />

Fetch Latest Diary Entries By Reference [#fetch-latest-diary-entries-by-reference]

<ApiEndpoint name="fetchLatestDiaryEntriesByReference" />

Fetch All Diary Entries By Locator [#fetch-all-diary-entries-by-locator]

<ApiEndpoint name="fetchAllDiaryEntriesByLocator" />

<ApiSchema name="DiaryEntryResponse" />

Creation [#creation]

Create Diary [#create-diary]

<ApiEndpoint name="createDiary" />

Create Diary For Segment Element [#create-diary-for-segment-element]

<ApiEndpoint name="createDiaryForSegmentElement" />

Create Diary For Quote Element [#create-diary-for-quote-element]

<ApiEndpoint name="createDiaryForQuoteElement" />

<ApiSchema name="DiaryEntryCreateRequest" />

Revisioning [#revisioning]

Update Diary [#update-diary]

<ApiEndpoint name="updateDiary" />

<ApiSchema name="DiaryEntryUpdateRequest" />

Discard [#discard]

Discard Diary [#discard-diary]

<ApiEndpoint name="discardDiary" />

See Also [#see-also]

* [Diaries Feature Guide](/features/work-management/diaries)


## API Reference

GET /auxdata/{tenantLocator}/diary/{locator}/latest — fetchLatestDiaryEntryByLocator
Fetches the latest revision of a single diary entry
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DiaryEntryResponse — OK

GET /auxdata/{tenantLocator}/diary/{referenceType}/{referenceLocator} — fetchLatestDiaryEntriesByReference
Fetches all of the latest revisions for a given entity
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  referenceType (string, path, required)
  referenceLocator (ulid, path, required)
  includeDiscarded (boolean, query)
Responses:
  200 DiaryEntryResponse[] — OK

GET /auxdata/{tenantLocator}/diary/{locator} — fetchAllDiaryEntriesByLocator
Fetches all revisions of a single diary entry
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 DiaryEntryResponse[] — OK

POST /auxdata/{tenantLocator}/diary/{referenceType}/{referenceLocator} — createDiary
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  referenceType (string, path, required)
  referenceLocator (ulid, path, required)
Request body (DiaryEntryCreateRequest):
Responses:
  200 DiaryEntryResponse — OK

POST /auxdata/{tenantLocator}/diary/segments/{segmentLocator}/element/{staticElementLocator} — createDiaryForSegmentElement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  segmentLocator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (DiaryEntryCreateRequest):
Responses:
  200 DiaryEntryResponse — OK

POST /auxdata/{tenantLocator}/diary/quotes/{quoteLocator}/element/{staticElementLocator} — createDiaryForQuoteElement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (DiaryEntryCreateRequest):
Responses:
  200 DiaryEntryResponse — OK

PATCH /auxdata/{tenantLocator}/diary/{locator} — updateDiary
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DiaryEntryUpdateRequest):
Responses:
  200 DiaryEntryResponse — OK

PATCH /auxdata/{tenantLocator}/diary/{locator}/discard — discardDiary
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DiaryEntryResponse — OK

DiaryEntryResponse
Properties:
  locator (ulid, required)
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy | transaction | task | fnol | invoice | account | underwritingFlag | payment | quoteGroup | inquiry | element, required)
  category (string)
  contents (string, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  updatedAt (datetime, required)
  updatedBy (uuid, required)
  diaryState (Enum active | discarded, required)

DiaryEntryCreateRequest
Properties:
  category (string)
  contents (string, required)

DiaryEntryUpdateRequest
Properties:
  category (string)
  contents (string, required)

# Media API



<EndpointIndex
  names={[
  	'fetchMediaData',
  	'fetchFile',
  	'fetchAllMediaDataByLocator',
  	'fetchLatestFile',
  	'fetchLatestMediaData',
  	'fetchLatestMediaDataByReference',
  	'createMediaData',
  	'updateMediaData',
  	'deleteMediaData',
  ]}
  titles={{
  	fetchMediaData: 'Fetch Media Data',
  	fetchFile: 'Fetch File',
  	fetchAllMediaDataByLocator: 'Fetch All Media By Locator',
  	fetchLatestFile: 'Fetch Latest File',
  	fetchLatestMediaData: 'Fetch Latest Media Data',
  	fetchLatestMediaDataByReference: 'Fetch Latest Media Data By Reference',
  	createMediaData: 'Create Media Data',
  	updateMediaData: 'Update Media Data',
  	deleteMediaData: 'Delete Media Data',
  }}
/>

Fetch [#fetch]

Fetch Media Data [#fetch-media-data]

<ApiEndpoint name="fetchMediaData" title="Fetch Media Data" />

<ApiSchema name="MediaDataEntry" />

<ApiSchema name="MediaDataEntryReference" />

Fetch File [#fetch-file]

<ApiEndpoint name="fetchFile" title="Fetch File" />

Fetch All Media By Locator [#fetch-all-media-by-locator]

<ApiEndpoint name="fetchAllMediaDataByLocator" title="Fetch All Media By Locator" />

Fetch Latest File [#fetch-latest-file]

<ApiEndpoint name="fetchLatestFile" title="Fetch Latest File" />

Fetch Latest Media Data [#fetch-latest-media-data]

<ApiEndpoint name="fetchLatestMediaData" title="Fetch Latest Media Data" />

Fetch Latest Media Data By Reference [#fetch-latest-media-data-by-reference]

<ApiEndpoint name="fetchLatestMediaDataByReference" title="Fetch Latest Media Data By Reference" />

Management [#management]

Create Media Data [#create-media-data]

<ApiEndpoint name="createMediaData" title="Create Media Data" />

Update Media Data [#update-media-data]

<ApiEndpoint name="updateMediaData" title="Update Media Data" />

Delete Media Data [#delete-media-data]

<ApiEndpoint name="deleteMediaData" title="Delete Media Data" />


## API Reference

GET /auxdata/{tenantLocator}/mediadata/{locator}/versions/{versionLocator} — fetchMediaData
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  versionLocator (ulid, path, required)
Responses:
  200 — OK

GET /auxdata/{tenantLocator}/mediadata/{locator}/versions/{versionLocator}/file — fetchFile
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  versionLocator (ulid, path, required)
Responses:
  200 — OK

GET /auxdata/{tenantLocator}/mediadata/{locator}/list — fetchAllMediaDataByLocator
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 — OK

GET /auxdata/{tenantLocator}/mediadata/{locator}/file — fetchLatestFile
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /auxdata/{tenantLocator}/mediadata/{locator} — fetchLatestMediaData
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /auxdata/{tenantLocator}/mediadata/search/{referenceType}/{referenceLocator}/list — fetchLatestMediaDataByReference
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  referenceLocator (ulid, path, required)
  referenceType (Enum diary | fnol | inquiry | policy | producer | producerAppointment | producerCode | producerLicense | quote | task | transaction | userAssociation, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 — OK

POST /auxdata/{tenantLocator}/mediadata — createMediaData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  filename (string, query, required)
  mimeType (string, query, required)
  title (string, query)
  tag (string, query)
  references (MediaDataEntryReference[], query, required)
Responses:
  200 — OK

PATCH /auxdata/{tenantLocator}/mediadata/{locator} — updateMediaData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  filename (string, query)
  mimeType (string, query)
  title (string, query)
  tag (string, query)
  referencesToAdd (MediaDataEntryReference[], query)
  referencesToRemove (MediaDataEntryReference[], query)
Responses:
  200 — OK

DELETE /auxdata/{tenantLocator}/mediadata/{locator} — deleteMediaData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

MediaDataEntry
Properties:
  locator (ulid, required)
  versionLocator (ulid)
  filename (string, required)
  title (string)
  tag (string)
  references (MediaDataEntryReference[], required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  updatedAt (datetime, required)
  updatedBy (uuid, required)

MediaDataEntryReference
Properties:
  type (Enum diary | fnol | inquiry | policy | producer | producerAppointment | producerCode | producerLicense | quote | task | transaction | userAssociation, required)
  locator (ulid, required)

# Authentication API



<EndpointIndex
  names={[
  	'createAuthToken',
  	'createServiceAccountAuthToken',
  	'fetchAuthTokens',
  	'fetchAuthTokensForUser',
  	'deleteAuthToken',
  	'deleteAuthTokenForUser',
  	'revokeUserOauthTokens',
  	'removeCredentials',
  	'fetchCredentialStatus',
  ]}
  titles={{
  	createAuthToken: 'Create an Auth Token',
  	createServiceAccountAuthToken: 'Create a Service Account Auth Token',
  	fetchAuthTokens: 'Fetch All Auth Tokens',
  	fetchAuthTokensForUser: 'Fetch Auth Tokens for a User',
  	deleteAuthToken: 'Delete an Auth Token',
  	deleteAuthTokenForUser: 'Delete an Auth Token for a Specific User',
  	revokeUserOauthTokens: 'Revoke OAuth Tokens for a User',
  	removeCredentials: 'Remove Credentials for a User',
  	fetchCredentialStatus: 'Fetch Credential Status',
  }}
/>

Creation [#creation]

Create an Auth Token [#create-an-auth-token]

<ApiEndpoint name="createAuthToken" title="Create an Auth Token" />

Create a Service Account Auth Token [#create-a-service-account-auth-token]

<ApiEndpoint name="createServiceAccountAuthToken" title="Create a Service Account Auth Token" />

<ApiSchema name="AuthTokenCreateRequest" />

Fetch [#fetch]

Fetch All Auth Tokens [#fetch-all-auth-tokens]

<ApiEndpoint name="fetchAuthTokens" title="Fetch All Auth Tokens" />

Fetch Auth Tokens for a User [#fetch-auth-tokens-for-a-user]

<ApiEndpoint name="fetchAuthTokensForUser" title="Fetch Auth Tokens for a User" />

<ApiSchema name="AuthTokenResponse" />

Fetch Credential Status [#fetch-credential-status]

<ApiEndpoint name="fetchCredentialStatus" title="Fetch Credential Status" />

<ApiSchema name="CredentialResponse" />

Deletion [#deletion]

Delete an Auth Token [#delete-an-auth-token]

<ApiEndpoint name="deleteAuthToken" title="Delete an Auth Token" />

Delete an Auth Token for a Specific User [#delete-an-auth-token-for-a-specific-user]

<ApiEndpoint name="deleteAuthTokenForUser" title="Delete an Auth Token for a Specific User" />

Revocation [#revocation]

Revoke OAuth Tokens for a User [#revoke-oauth-tokens-for-a-user]

<ApiEndpoint name="revokeUserOauthTokens" title="Revoke OAuth Tokens for a User" />

Remove Credentials for a User [#remove-credentials-for-a-user]

<ApiEndpoint name="removeCredentials" title="Remove Credentials for a User" />


## API Reference

POST /auth/users/tokens — createAuthToken
Permissions: write, token
Request body (AuthTokenCreateRequest):
Responses:
  200 string — OK

POST /auth/users/{locator}/tokens — createServiceAccountAuthToken
Permissions: custom
Parameters:
  locator (uuid, path, required)
Request body (AuthTokenCreateRequest):
Responses:
  200 string — OK

GET /auth/users/tokens — fetchAuthTokens
Permissions: read, custom
Responses:
  200 AuthTokenResponse[] — OK

GET /auth/users/{locator}/tokens — fetchAuthTokensForUser
Permissions: read, custom
Parameters:
  locator (uuid, path, required)
Responses:
  200 AuthTokenResponse[] — OK

GET /auth/users/{locator}/credentialStatus — fetchCredentialStatus
Permissions: read, custom
Parameters:
  locator (uuid, path, required)
Responses:
  200 CredentialResponse — OK

DELETE /auth/users/tokens/{tokenOrName} — deleteAuthToken
Permissions: write, custom
Parameters:
  tokenOrName (string, path, required)
Responses:
  200 — OK

DELETE /auth/users/{locator}/tokens/{tokenOrName} — deleteAuthTokenForUser
Permissions: write, custom
Parameters:
  locator (uuid, path, required)
  tokenOrName (string, path, required)
Responses:
  200 — OK

POST /auth/users/{locator}/revoke — revokeUserOauthTokens
Permissions: write, custom, revoke
Parameters:
  locator (uuid, path, required)
Responses:
  200 — OK

DELETE /auth/users/{locator}/credentials — removeCredentials
Permissions: write, custom
Parameters:
  locator (uuid, path, required)
Responses:
  200 — OK

AuthTokenCreateRequest
Properties:
  name (string, required)
  tenants (string[], required)
  permissions (string[], required)
  expiresAt (datetime, required)

AuthTokenResponse
Properties:
  name (string, required)
  tenants (string[])
  permissions (string[])
  createdAt (datetime, required)
  expiresAt (datetime, required)

CredentialResponse
Properties:
  passwordEnabled (boolean, required)
  temporaryPassword (boolean, required)
  createdAt (datetime, required)
  lastSessionStartAt (datetime, required)
  lastSessionLastAccessAt (datetime, required)

# Tenant Management API



<EndpointIndex
  names={[
  	'fetchMyTenants',
  	'fetchTenant',
  	'createTenant',
  	'fetchTenants',
  	'updateTenant',
  	'retireTenant',
  	'cloneConfigToTest',
  	'cloneConfigToProduction',
  ]}
  titles={{
  	fetchTenant: 'Fetch Tenant Details',
  	createTenant: 'Create a Tenant',
  	fetchTenants: 'Fetch all Tenants in the Environment',
  	updateTenant: 'Update a Tenant',
  	retireTenant: 'Retire a Tenant',
  	cloneConfigToTest: 'Clone to a Test Tenant',
  	cloneConfigToProduction: 'Clone to a Production tenant',
  }}
/>

Fetch My Tenants [#fetch-my-tenants]

<ApiEndpoint name="fetchMyTenants" />

<ApiSchema name="TenantListResponse" />

Fetch Tenant Details [#fetch-tenant-details]

<ApiEndpoint name="fetchTenant" title="Fetch Tenant Details" />

<ApiSchema name="TenantResponse" />

Create a Tenant [#create-a-tenant]

<ApiEndpoint name="createTenant" title="Create a Tenant" />

<ApiSchema name="TenantDeploymentResult" />

Fetch all Tenants in the Environment [#fetch-all-tenants-in-the-environment]

<ApiEndpoint name="fetchTenants" title="Fetch all Tenants in the Environment" />

Update a Tenant [#update-a-tenant]

<ApiEndpoint name="updateTenant" title="Update a Tenant" />

<ApiSchema name="TenantUpdateRequest" />

Retire a Tenant [#retire-a-tenant]

<ApiEndpoint name="retireTenant" title="Retire a Tenant" />

Cloning [#cloning]

Clone to a Test Tenant [#clone-to-a-test-tenant]

<ApiEndpoint name="cloneConfigToTest" title="Clone to a Test Tenant" />

Clone to a Production tenant [#clone-to-a-production-tenant]

<ApiEndpoint name="cloneConfigToProduction" title="Clone to a Production tenant" />

<ApiSchema name="DeploymentCloneResponse" />


## API Reference

GET /auth/tenants/mytenants/list — fetchMyTenants
Returns a list of tenants you have access to.
Permissions: custom
Parameters:
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 TenantListResponse — OK

GET /auth/tenants/{locator} — fetchTenant
Permissions: read
Parameters:
  locator (uuid, path, required)
Responses:
  200 TenantResponse — OK

POST /config/createTenant — createTenant
Permissions: create-tenant
Parameters:
  name (string, query)
  description (string, query)
Responses:
  200 TenantDeploymentResult — OK

GET /auth/tenants/list — fetchTenants
Permissions: read, list
Parameters:
  offset (integer, query)
  count (integer, query)
  type (string[], query)
  extended (boolean, query)
Responses:
  200 TenantResponse[] — OK

PATCH /auth/tenants/{locator} — updateTenant
Permissions: write
Parameters:
  locator (uuid, path, required)
Request body (TenantUpdateRequest):
Responses:
  200 TenantResponse — OK

PATCH /auth/tenants/{locator}/retire — retireTenant
Permissions: retire
Parameters:
  locator (uuid, path, required)
Responses:
  200 TenantResponse — OK

POST /config/{tenantLocator}/deployments/cloneTest — cloneConfigToTest
Permissions: cloneTest
Parameters:
  tenantLocator (uuid, path, required)
  tenantName (string, query)
  tenantDescription (string, query)
Responses:
  200 — OK

POST /config/{tenantLocator}/deployments/cloneProduction — cloneConfigToProduction
Permissions: cloneProduction
Parameters:
  tenantLocator (uuid, path, required)
  tenantName (string, query)
  tenantDescription (string, query)
Responses:
  200 — OK

TenantListResponse
Properties:
  listCompleted (boolean, required)
  items (TenantResponse[], required)

TenantResponse
Properties:
  locator (uuid, required)
  name (string, required)
  type (Enum test | production | retired | deleted, required)
  description (string)
  createdAt (datetime, required)
  createdBy (uuid, required)
  updatedAt (datetime, required)
  businessAccount (string, required)

TenantDeploymentResult
Properties:
  locator (uuid, required)
  name (string, required)
  deploymentResult (ConfigBuilderResult, required)
  bootstrapResult (BootstrapResult, required)

TenantUpdateRequest
Properties:
  name (string, required)
  description (string, required)

DeploymentCloneResponse
Properties:
  locator (uuid, required)
  deploymentResult (ConfigBuilderResult, required)
  resourceCloneStatus (Enum queued | failed, required)

# User Management API



<EndpointIndex
  names={[
  	'createUser',
  	'fetchMyUserDetails',
  	'fetchUserByName',
  	'fetchUserByLocator',
  	'fetchMultipleUsers',
  	'fetchMultipleBasicUsers',
  	'updateUser',
  	'resetUserPassword',
  	'deleteUser',
  	'createRole',
  	'getRole',
  	'updateRole',
  	'fetchMultipleRoles',
  	'deleteRole',
  	'listTenantRoles',
  	'getTenantRole',
  	'createTenantRole',
  	'updateTenantRole',
  	'deleteTenantRole',
  	'fetchAvailablePermissions',
  	'fetchUserPermissions',
  	'fetchUserTenantPermissions',
  	'getGroupedTokenPermissions',
  	'updateUserRoles',
  	'updateUserTenantAssignments',
  ]}
  titles={{
  	createUser: 'Create a User',
  	fetchMyUserDetails: 'Fetch My User Details',
  	fetchUserByName: 'Fetch a User by Name',
  	fetchUserByLocator: 'Fetch a User by Locator',
  	updateUser: 'Update a User',
  	resetUserPassword: "Reset a User's Password",
  	deleteUser: 'Delete a User',
  	createRole: 'Create a Role',
  	getRole: 'Fetch a Role',
  	updateRole: 'Update a Role',
  	fetchMultipleRoles: 'Fetch Multiple Roles',
  	deleteRole: 'Delete a Role',
  	listTenantRoles: 'Fetch Multiple Tenant Roles',
  	getTenantRole: 'Fetch a Tenant Role',
  	createTenantRole: 'Create a Tenant Role',
  	updateTenantRole: 'Update a Tenant Role',
  	deleteTenantRole: 'Delete a Tenant Role',
  	fetchAvailablePermissions: 'Fetch Available Permissions',
  	fetchUserPermissions: 'Fetch User Permissions',
  	fetchUserTenantPermissions: "Fetch a User's Tenant Permissions",
  	getGroupedTokenPermissions: 'Fetch Grouped Token Permissions',
  	updateUserRoles: 'Update User Roles',
  	updateUserTenantAssignments: "Update a User's Tenant Assignments",
  }}
/>

Users [#users]

Create a User [#create-a-user]

<ApiEndpoint name="createUser" title="Create a User" />

<ApiSchema name="UserCreateRequest" />

<ApiSchema name="UserResponse" />

Fetch My User Details [#fetch-my-user-details]

<ApiEndpoint name="fetchMyUserDetails" title="Fetch My User Details" />

Fetch a User by Name [#fetch-a-user-by-name]

<ApiEndpoint name="fetchUserByName" title="Fetch a User by Name" />

Fetch a User by Locator [#fetch-a-user-by-locator]

<ApiEndpoint name="fetchUserByLocator" title="Fetch a User by Locator" />

Fetch Multiple Users [#fetch-multiple-users]

<ApiEndpoint name="fetchMultipleUsers" />

<ApiSchema name="UserListResponse" />

Fetch Multiple Basic Users [#fetch-multiple-basic-users]

<ApiEndpoint name="fetchMultipleBasicUsers" />

<ApiSchema name="BasicUserListResponse" />

<ApiSchema name="BasicUserResponse" />

Update a User [#update-a-user]

<ApiEndpoint name="updateUser" title="Update a User" />

<ApiSchema name="UserUpdateRequest" />

Reset a User's Password [#reset-a-users-password]

<ApiEndpoint name="resetUserPassword" title="Reset a User's Password" />

Delete a User [#delete-a-user]

<ApiEndpoint name="deleteUser" title="Delete a User" />

Roles [#roles]

Create a Role [#create-a-role]

<ApiEndpoint name="createRole" title="Create a Role" />

<ApiSchema name="RoleCreateRequest" />

<ApiSchema name="RoleResponse" />

Fetch a Role [#fetch-a-role]

<ApiEndpoint name="getRole" title="Fetch a Role" />

Update a Role [#update-a-role]

<ApiEndpoint name="updateRole" title="Update a Role" />

<ApiSchema name="RoleUpdateRequest" />

Fetch Multiple Roles [#fetch-multiple-roles]

<ApiEndpoint name="fetchMultipleRoles" title="Fetch Multiple Roles" />

<ApiSchema name="RoleListResponse" />

Delete a Role [#delete-a-role]

<ApiEndpoint name="deleteRole" title="Delete a Role" />

Tenant Roles [#tenant-roles]

Fetch Multiple Tenant Roles [#fetch-multiple-tenant-roles]

<ApiEndpoint name="listTenantRoles" title="Fetch Multiple Tenant Roles" />

Fetch a Tenant Role [#fetch-a-tenant-role]

<ApiEndpoint name="getTenantRole" title="Fetch a Tenant Role" />

Create a Tenant Role [#create-a-tenant-role]

<ApiEndpoint name="createTenantRole" title="Create a Tenant Role" />

Update a Tenant Role [#update-a-tenant-role]

<ApiEndpoint name="updateTenantRole" title="Update a Tenant Role" />

Delete a Tenant Role [#delete-a-tenant-role]

<ApiEndpoint name="deleteTenantRole" title="Delete a Tenant Role" />

<ApiSchema name="ListPageResponseRoleDetails" />

<ApiSchema name="CreateTenantRoleReq" />

<ApiSchema name="PatchTenantRoleReq" />

Permissions [#permissions]

Fetch Available Permissions [#fetch-available-permissions]

<ApiEndpoint name="fetchAvailablePermissions" title="Fetch Available Permissions" />

Fetch User Permissions [#fetch-user-permissions]

<ApiEndpoint name="fetchUserPermissions" title="Fetch User Permissions" />

Fetch a User's Tenant Permissions [#fetch-a-users-tenant-permissions]

<ApiEndpoint name="fetchUserTenantPermissions" title="Fetch a User's Tenant Permissions" />

Fetch Grouped Token Permissions [#fetch-grouped-token-permissions]

<ApiEndpoint name="getGroupedTokenPermissions" title="Fetch Grouped Token Permissions" />

User Role Assignments [#user-role-assignments]

Update User Roles [#update-user-roles]

<ApiEndpoint name="updateUserRoles" title="Update User Roles" />

<ApiSchema name="UserRolesUpdateRequest" />

User Tenant Assignments [#user-tenant-assignments]

Update a User's Tenant Assignments [#update-a-users-tenant-assignments]

<ApiEndpoint name="updateUserTenantAssignments" title="Update a User's Tenant Assignments" />

<ApiSchema name="UserTenantsAssignmentsUpdateRequest" />


## API Reference

POST /auth/users — createUser
Permissions: add
Parameters:
  enableUser (boolean, query) — When true, user will be active (enabled) even if password is not set. Useful for SSO since user cannot use any other credentials to log in
Request body (UserCreateRequest):
Responses:
  200 UserResponse — OK

GET /auth/users/whoami — fetchMyUserDetails
Permissions: custom
Responses:
  200 UserResponse — OK

GET /auth/users/username/{username} — fetchUserByName
Permissions: read
Parameters:
  username (string, path, required)
Responses:
  200 UserResponse[] — OK

GET /auth/users/{locator} — fetchUserByLocator
Permissions: custom, read
Parameters:
  locator (uuid, path, required)
Responses:
  200 UserResponse — OK

GET /auth/users/list — fetchMultipleUsers
Permissions: read, list
Parameters:
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 UserListResponse — OK

GET /auth/users/basic/list — fetchMultipleBasicUsers
This endpoint returns a simplified response and therefore has a higher count limit compared to 'fetchMultipleUsers'.
Permissions: read, list
Parameters:
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 BasicUserResponse — OK

PATCH /auth/users/{locator} — updateUser
Permissions: update, custom
Parameters:
  locator (uuid, path, required)
Request body (UserUpdateRequest):
Responses:
  200 UserResponse — OK

PATCH /auth/users/{locator}/passwordreset — resetUserPassword
Permissions: password-reset
Parameters:
  locator (uuid, path, required)
Request body (string):
Responses:
  200 — OK

DELETE /auth/users/{locator} — deleteUser
Permissions: delete
Parameters:
  locator (uuid, path, required)
Responses:
  200 — OK

POST /auth/roles — createRole
Permissions: add
Request body (RoleCreateRequest):
Responses:
  200 RoleResponse — OK

GET /auth/roles/{locator} — getRole
Permissions: read
Parameters:
  locator (ulid, path, required)
Responses:
  200 RoleResponse — OK

PATCH /auth/roles/{locator} — updateRole
Permissions: update
Parameters:
  locator (ulid, path, required)
Request body (RoleUpdateRequest):
Responses:
  200 RoleResponse — OK

GET /auth/roles/list — fetchMultipleRoles
Permissions: read, list
Parameters:
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 RoleListResponse — OK

DELETE /auth/roles/{locator} — deleteRole
Permissions: delete
Parameters:
  locator (ulid, path, required)
Responses:
  200 — OK

GET /auth/roles/tenant/{tenantLocator}/list — listTenantRoles
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseRoleDetails — OK

GET /auth/roles/tenant/{tenantLocator}/{roleLocator} — getTenantRole
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  roleLocator (ulid, path, required)
Responses:
  200 RoleResponse — OK

POST /auth/roles/tenant/{tenantLocator}/{roleLocator} — createTenantRole
Permissions: add
Parameters:
  tenantLocator (uuid, path, required)
  roleLocator (ulid, path, required)
Request body (CreateTenantRoleReq):
Responses:
  200 RoleResponse — OK

PATCH /auth/roles/tenant/{tenantLocator}/{roleLocator} — updateTenantRole
Permissions: update
Parameters:
  tenantLocator (uuid, path, required)
  roleLocator (ulid, path, required)
Request body (PatchTenantRoleReq):
Responses:
  200 RoleResponse — OK

DELETE /auth/roles/tenant/{tenantLocator}/{roleLocator} — deleteTenantRole
Permissions: delete
Parameters:
  tenantLocator (uuid, path, required)
  roleLocator (ulid, path, required)
Responses:
  200 — OK

GET /auth/roles/permissions — fetchAvailablePermissions
Permissions: read
Responses:
  200 string[] — OK

GET /auth/users/{locator}/permissions — fetchUserPermissions
Permissions: read, custom
Parameters:
  locator (uuid, path, required)
Responses:
  200 string[] — OK

GET /auth/users/{userLocator}/tenant/{tenantLocator}/permissions — fetchUserTenantPermissions
Permissions: read, custom
Parameters:
  userLocator (uuid, path, required)
  tenantLocator (uuid, path, required)
Responses:
  200 string[] — OK

POST /auth/users/tokens/permissions — getGroupedTokenPermissions
Permissions: read, custom
Request body (string):
Responses:
  200 map<string, string[]> — OK

PATCH /auth/users/{locator}/roles — updateUserRoles
Permissions: update-roles
Parameters:
  locator (uuid, path, required)
Request body (UserRolesUpdateRequest):
Responses:
  200 UserResponse — OK

PATCH /auth/users/{locator}/tenants — updateUserTenantAssignments
Permissions: update-tenants
Parameters:
  locator (uuid, path, required)
Request body (UserTenantsAssignmentsUpdateRequest):
Responses:
  200 UserResponse — OK

UserCreateRequest
Properties:
  userName (string, required) — A user name in email format
  firstName (string, required)
  lastName (string, required)
  password (string)
  temporaryPassword (boolean)
  serviceAccount (boolean)
  email (string)
  tenants (string[])
  roles (string[])

UserResponse
Properties:
  locator (uuid, required)
  userName (string, required)
  firstName (string, required)
  lastName (string, required)
  email (string)
  serviceAccount (boolean, required)
  roles (string[])
  tenants (string[], required)
  permissions (string[])

UserListResponse
Properties:
  listCompleted (boolean, required)
  items (UserResponse[], required)

BasicUserListResponse
Properties:
  listCompleted (boolean, required)
  items (BasicUserResponse[], required)

BasicUserResponse
Properties:
  firstName (string)
  lastName (string)
  locator (ulid, required)
  userName (string, required)

UserUpdateRequest
Properties:
  firstName (string, required)
  lastName (string, required)
  email (string)
  roles (string[])
  tenants (string[], required)
  permissions (string[])

RoleCreateRequest
Properties:
  name (string, required)
  permissions (string[], required)
  description (string, required)

RoleResponse
Properties:
  name (string, required)
  locator (ulid, required)
  permissions (string[], required)
  version (integer, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  description (string, required)

RoleUpdateRequest
Properties:
  version (integer, required)
  name (string, required)
  addPermissions (string[], required)
  removePermissions (string[], required)
  description (string, required)

RoleListResponse
Properties:
  listCompleted (boolean, required)
  items (RoleResponse[], required)

ListPageResponseRoleDetails
Properties:
  listCompleted (boolean, required)
  items (RoleResponse[], required)

CreateTenantRoleReq
Properties:
  permissions (string[], required)
  description (string)

PatchTenantRoleReq
Properties:
  version (integer, required)
  addPermissions (string[], required)
  removePermissions (string[], required)
  description (string)

UserRolesUpdateRequest
Properties:
  addRoles (string[], required)
  removeRoles (string[], required)

UserTenantsAssignmentsUpdateRequest
Properties:
  addTenants (string[], required)
  removeTenants (string[], required)

# Account Balances API



<EndpointIndex names={['handleExcessFunds']} />

Handle Excess Funds [#handle-excess-funds]

<ApiEndpoint name="handleExcessFunds" />

<ApiSchema name="AccountExcessHandlingResult" />

<ApiSchema name="ExcludedDebitsAmountResult" />

<ApiSchema name="ExcludedDebit" />

<ApiSchema name="ExcessCreditCreateDisbursementResult" />


## API Reference

PATCH /billing/{tenantLocator}/accountBalances/{locator}/handleExcessFunds — handleExcessFunds
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  currency (string, query)
Responses:
  200 AccountExcessHandlingResult — OK

AccountExcessHandlingResult
Properties:
  accountLocator (ulid, required)
  currency (string, required)
  accountCreditBalance (number, required)
  excludedDebitsAmountResult (ExcludedDebitsAmountResult, required)
  thresholdUsed (number)
  createDisbursementResult (ExcessCreditCreateDisbursementResult)
  errors (string[], required)

ExcludedDebitsAmountResult
Properties:
  calculationType (Enum none | pastDueInvoices | allInvoices | invoicesAndUnbilledInstallments, required)
  entitiesUsedInCalculation (ExcludedDebit[], required)
  currency (string, required)
  amountToExclude (number, required)

ExcludedDebit
Properties:
  entityLocator (ulid, required)
  type (Enum invoice | installment, required)

ExcessCreditCreateDisbursementResult
Properties:
  disbursementLocator (ulid, required)
  disbursementState (Enum draft | validated | approved | executed | reversed | rejected | discarded, required)
  disbursedAmount (number, required)
  validationResult (ValidationResult)

# Credit Distribution API



Credit Distributions are used to apply customer credits from a Credit Balance to invoices or for disbursements.

<EndpointIndex
  names={[
  	'fetchCreditDistribution',
  	'fetchCreditDistributionsForAnInvoice',
  	'fetchMultipleCreditDistributions',
  	'createCreditDistribution',
  	'updateCreditDistribution',
  	'createOrReplaceCreditDistribution',
  	'validateCreditDistribution',
  	'executeCreditDistribution',
  	'reverseCreditDistribution',
  	'resetCreditDistribution',
  	'discardCreditDistribution',
  	'fetchInvoicesTargetedByACreditDistribution',
  ]}
/>

Fetch [#fetch]

Fetch Credit Distribution [#fetch-credit-distribution]

<ApiEndpoint name="fetchCreditDistribution" />

Fetch Credit Distributions For An Invoice [#fetch-credit-distributions-for-an-invoice]

<ApiEndpoint name="fetchCreditDistributionsForAnInvoice" />

Fetch Multiple Credit Distributions [#fetch-multiple-credit-distributions]

<ApiEndpoint name="fetchMultipleCreditDistributions" />

<ApiSchema name="CreditDistributionListResponse" />

<ApiSchema name="CreditDistributionResponse" />

Creation and Update [#creation-and-update]

Create Credit Distribution [#create-credit-distribution]

<ApiEndpoint name="createCreditDistribution" />

<ApiSchema name="CreditDistributionCreateRequest" />

Update Credit Distribution [#update-credit-distribution]

<ApiEndpoint name="updateCreditDistribution" />

<ApiSchema name="CreditDistributionUpdateRequest" />

Create Or Replace Credit Distribution [#create-or-replace-credit-distribution]

<ApiEndpoint name="createOrReplaceCreditDistribution" />

<ApiSchema name="CreditDistributionPutRequest" />

Execution [#execution]

Validate Credit Distribution [#validate-credit-distribution]

<ApiEndpoint name="validateCreditDistribution" />

Execute Credit Distribution [#execute-credit-distribution]

<ApiEndpoint name="executeCreditDistribution" />

Reversal [#reversal]

Reverse Credit Distribution [#reverse-credit-distribution]

<ApiEndpoint name="reverseCreditDistribution" />

<ApiSchema name="CreditDistributionReverseRequest" />

Reset and Discard [#reset-and-discard]

Reset Credit Distribution [#reset-credit-distribution]

<ApiEndpoint name="resetCreditDistribution" />

Discard Credit Distribution [#discard-credit-distribution]

<ApiEndpoint name="discardCreditDistribution" />

Invoices [#invoices]

Fetch Invoices Targeted By ACredit Distribution [#fetch-invoices-targeted-by-acredit-distribution]

<ApiEndpoint name="fetchInvoicesTargetedByACreditDistribution" />


## API Reference

GET /billing/{tenantLocator}/creditDistributions/{locator} — fetchCreditDistribution
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 CreditDistributionResponse — OK

GET /billing/{tenantLocator}/invoices/{locator}/creditDistributions/list — fetchCreditDistributionsForAnInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 CreditDistributionListResponse — OK

GET /billing/{tenantLocator}/creditDistributions/list — fetchMultipleCreditDistributions
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  accountLocator (ulid, query)
  extended (boolean, query)
Responses:
  200 CreditDistributionListResponse — OK

POST /billing/{tenantLocator}/creditDistributions — createCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (CreditDistributionCreateRequest):
Responses:
  200 CreditDistributionResponse — OK

PATCH /billing/{tenantLocator}/creditDistributions/{locator} — updateCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (CreditDistributionUpdateRequest):
Responses:
  200 CreditDistributionResponse — OK

PUT /billing/{tenantLocator}/creditDistributions/{locator} — createOrReplaceCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (CreditDistributionPutRequest):
Responses:
  200 CreditDistributionResponse — OK

PATCH /billing/{tenantLocator}/creditDistributions/{locator}/validate — validateCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 CreditDistributionResponse — OK

PATCH /billing/{tenantLocator}/creditDistributions/{locator}/execute — executeCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 CreditDistributionResponse — OK

PATCH /billing/{tenantLocator}/creditDistributions/{locator}/reverse — reverseCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (CreditDistributionReverseRequest):
Responses:
  200 CreditDistributionResponse — OK

PATCH /billing/{tenantLocator}/creditDistributions/{locator}/reset — resetCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 CreditDistributionResponse — OK

PATCH /billing/{tenantLocator}/creditDistributions/{locator}/discard — discardCreditDistribution
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 CreditDistributionResponse — OK

GET /billing/{tenantLocator}/creditDistributions/{locator}/invoices/list — fetchInvoicesTargetedByACreditDistribution
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceListResponse — OK

CreditDistributionListResponse
Properties:
  listCompleted (boolean, required)
  items (CreditDistributionResponse[], required)

CreditDistributionResponse
Properties:
  locator (ulid, required)
  creditDistributionState (Enum draft | validated | executed | reversed | discarded, required)
  currency (string, required)
  amount (number, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid)
  sources (CreditItem[], required)
  targets (CreditItem[], required)
  validationResult (ValidationResult)
  executedAt (datetime)
  reversalReason (string)
  reversedAt (datetime)
  shortfallCreditLocators (ulid[], required)

CreditDistributionCreateRequest
Properties:
  accountLocator (ulid)
  amount (number, required)
  currency (string)
  sources (CreditItem[], required)
  targets (CreditItem[], required)

CreditDistributionUpdateRequest
Properties:
  accountLocator (ulid)
  amount (number)
  addSources (CreditItem[], required)
  removeSources (ulid[], required)
  addTargets (CreditItem[], required)
  removeTargets (ulid[], required)
  currency (string)

CreditDistributionPutRequest
Properties:
  accountLocator (ulid)
  amount (number, required)
  currency (string)
  sources (CreditItem[], required)
  targets (CreditItem[], required)

CreditDistributionReverseRequest
Properties:
  reversalType (string, required)

# Credits API



Credits are added to the system to as desired to credit customer accounts.

<Callout>
  Currently the only credits supported (other than payments and credit distributions) are write-offs to resolve invoice payment shortfalls within the tolerance threshold.
</Callout>

<EndpointIndex
  names={[
  	'fetchCredits',
  	'fetchShortfallCredit',
  	'fetchMultipleShortfallCredits',
  ]}
/>

Fetch Credits [#fetch-credits]

<ApiEndpoint name="fetchCredits" />

<ApiSchema name="CreditListResponse" />

<ApiSchema name="CreditResponse" />

Fetch Shortfall Credit [#fetch-shortfall-credit]

<ApiEndpoint name="fetchShortfallCredit" />

<ApiSchema name="ShortfallCreditListResponse" />

<ApiSchema name="ShortfallCreditResponse" />

Fetch Multiple Shortfall Credits [#fetch-multiple-shortfall-credits]

<ApiEndpoint name="fetchMultipleShortfallCredits" />

Fetch Credits For An Invoice [#fetch-credits-for-an-invoice]

<ApiEndpoint name="fetchCreditsForAnInvoice" />


## API Reference

GET /billing/{tenantLocator}/credits/list — fetchCredits
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 CreditListResponse — OK

GET /billing/{tenantLocator}/shortfallCredits/{locator} — fetchShortfallCredit
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 ShortfallCreditResponse — OK

GET /billing/{tenantLocator}/shortfallCredits/list — fetchMultipleShortfallCredits
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  accountLocator (ulid, query)
  extended (boolean, query)
Responses:
  200 ShortfallCreditListResponse — OK

GET /billing/{tenantLocator}/invoices/{locator}/credits/list — fetchCreditsForAnInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 CreditListResponse — OK

CreditListResponse
Properties:
  listCompleted (boolean, required)
  items (CreditResponse[], required)

CreditResponse
Properties:
  locator (ulid, required)
  creditState (Enum discarded | draft | posted | reversed | validated | executed | distributed | approved | rejected | requested | executing | failed | cancelled, required)
  creditType (Enum creditDistribution | disbursement | payment | subpayment | shortfallWriteOff | writeOff, required)
  currency (string, required)
  amount (number, required)
  createdAt (datetime, required)
  accountLocator (ulid)
  realizedAt (datetime)
  reversedAt (datetime)
  reversalReason (string)

ShortfallCreditListResponse
Properties:
  listCompleted (boolean, required)
  items (ShortfallCreditResponse[], required)

ShortfallCreditResponse
Properties:
  locator (ulid, required)
  creditType (Enum creditDistribution | disbursement | payment | subpayment | shortfallWriteOff | writeOff, required)
  shortfallCreditState (Enum draft | distributed | reversed, required)
  currency (string, required)
  amount (number, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid, required)
  targets (CreditItem[], required)
  parentCreditLocator (ulid, required)
  reversalReason (string)

# Delinquency API



<EndpointIndex
  names={[
  	'updateQuoteDelinquencyPlan',
  	'updatePolicyDelinquencyPlan',
  	'getDelinquency',
  	'getDelinquenciesForAccount',
  	'getDelinquenciesForInvoice',
  	'getDelinquenciesForPolicy',
  	'updateDelinquency',
  	'fetchDelinquencyEvent',
  	'fetchDelinquencyEvents',
  	'updateDelinquencyEvent',
  ]}
  titles={{
  	updateQuoteDelinquencyPlan:
  		'Update the Delinquency Plan Assigned to a Quote',
  	updatePolicyDelinquencyPlan:
  		'Update the Delinquency Plan Assigned to a Policy',
  	getDelinquency: 'Fetch a Delinquency',
  	getDelinquenciesForAccount: 'Fetch Delinquencies for an Account',
  	getDelinquenciesForInvoice: 'Fetch Delinquencies for an Invoice',
  	getDelinquenciesForPolicy: 'Fetch Delinquencies for a Policy',
  }}
/>

Delinquency Plan Assignment [#delinquency-plan-assignment]

Update the Delinquency Plan Assigned to a Quote [#update-the-delinquency-plan-assigned-to-a-quote]

<ApiEndpoint name="updateQuoteDelinquencyPlan" title="Update the Delinquency Plan Assigned to a Quote" />

Update the Delinquency Plan Assigned to a Policy [#update-the-delinquency-plan-assigned-to-a-policy]

<ApiEndpoint name="updatePolicyDelinquencyPlan" title="Update the Delinquency Plan Assigned to a Policy" />

<ApiSchema name="DelinquencyPlanUpdateRequest" />

Fetch [#fetch]

Fetch a Delinquency [#fetch-a-delinquency]

<ApiEndpoint name="getDelinquency" title="Fetch a Delinquency" />

Fetch Delinquencies for an Account [#fetch-delinquencies-for-an-account]

<ApiEndpoint name="getDelinquenciesForAccount" title="Fetch Delinquencies for an Account" />

Fetch Delinquencies for an Invoice [#fetch-delinquencies-for-an-invoice]

<ApiEndpoint name="getDelinquenciesForInvoice" title="Fetch Delinquencies for an Invoice" />

Fetch Delinquencies for a Policy [#fetch-delinquencies-for-a-policy]

<ApiEndpoint name="getDelinquenciesForPolicy" title="Fetch Delinquencies for a Policy" />

<ApiSchema name="DelinquencyListResponse" />

<ApiSchema name="DelinquencyResponse" />

<Callout>
  The `references` property will only be populated when fetching an individual delinquency. It will be null when fetching all the delinquencies for an account, policy, etc.
</Callout>

<ApiSchema name="DelinquencyReference" />

<ApiSchema name="DelinquencySettings" />

<ApiSchema name="ConfiguredDelinquencyEvent" />

Delinquency Updates [#delinquency-updates]

This endpoint allows changing the trigger dates for an already-active delinquency.

Update Delinquency [#update-delinquency]

<ApiEndpoint name="updateDelinquency" />

<ApiSchema name="DelinquencyUpdateRequest" />

Delinquency Events [#delinquency-events]

Fetch Delinquency Event [#fetch-delinquency-event]

<ApiEndpoint name="fetchDelinquencyEvent" />

<ApiSchema name="DelinquencyEventResponse" />

Fetch Delinquency Events [#fetch-delinquency-events]

<ApiEndpoint name="fetchDelinquencyEvents" />

<ApiSchema name="DelinquencyEventsResponse" />

Update Delinquency Event [#update-delinquency-event]

<ApiEndpoint name="updateDelinquencyEvent" />

<ApiSchema name="DelinquencyEventUpdateRequest" />

See Also [#see-also]

* [Delinquency Feature Guide](/features/billing/delinquency)


## API Reference

PATCH /policy/{tenantLocator}/quotes/{locator}/delinquencyPlan — updateQuoteDelinquencyPlan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DelinquencyPlanUpdateRequest):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/delinquencyPlan — updatePolicyDelinquencyPlan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DelinquencyPlanUpdateRequest):
Responses:
  200 PolicyResponse — OK

GET /billing/{tenantLocator}/delinquencies/{locator} — getDelinquency
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DelinquencyResponse — OK

GET /billing/{tenantLocator}/delinquencies/accounts/{accountLocator}/list — getDelinquenciesForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 DelinquencyListResponse — OK

GET /billing/{tenantLocator}/delinquencies/invoices/{invoiceLocator}/list — getDelinquenciesForInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  invoiceLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 DelinquencyListResponse — OK

GET /billing/{tenantLocator}/delinquencies/policies/{policyLocator}/list — getDelinquenciesForPolicy
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 DelinquencyListResponse — OK

PATCH /billing/{tenantLocator}/delinquencies/{locator} — updateDelinquency
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DelinquencyUpdateRequest):
Responses:
  200 DelinquencyResponse — OK

GET /billing/{tenantLocator}/delinquencies/events/{delinquencyEventLocator} — fetchDelinquencyEvent
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  delinquencyEventLocator (ulid, path, required)
Responses:
  200 DelinquencyEventResponse — OK

GET /billing/{tenantLocator}/delinquencies/{delinquencyLocator}/events/list — fetchDelinquencyEvents
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  delinquencyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 DelinquencyEventsResponse — OK

PATCH /billing/{tenantLocator}/delinquencies/events/{delinquencyEventLocator} — updateDelinquencyEvent
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  delinquencyEventLocator (ulid, path, required)
Request body (DelinquencyEventUpdateRequest):
Responses:
  200 DelinquencyEventResponse — OK

DelinquencyPlanUpdateRequest
Properties:
  delinquencyPlanName (string, required)

DelinquencyListResponse
Properties:
  listCompleted (boolean, required)
  items (DelinquencyResponse[], required)

DelinquencyResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  delinquencyState (Enum preGrace | inGrace | lapseTriggered | settled | lapseTransactionCreated, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  settings (DelinquencySettings, required)
  timezone (string, required)
  references (DelinquencyReference[])
  graceStartedAt (datetime)
  graceEndAt (datetime)
  lapseTransactionEffectiveDate (datetime)
  configuredDelinquencyEvents (ConfiguredDelinquencyEvent[], required)

DelinquencyReference
Properties:
  locator (ulid, required)
  delinquencyLocator (ulid, required)
  referenceLocator (ulid, required)
  referenceType (Enum policy | invoice, required)
  transactionLocator (ulid)
  preemptingLapseTransactionLocator (ulid)

DelinquencySettings
Properties:
  lapseTransactionType (string, required)
  gracePeriodDays (integer, required)
  advanceLapseTo (Enum draft | validated | priced | underwritten | accepted | issued, required)
  delinquencyLevel (Enum policy | invoice)

ConfiguredDelinquencyEvent
Properties:
  name (string, required)
  offsetDays (number, required)
  offsetBasis (Enum gracePeriodStart | gracePeriodEnd, required)

DelinquencyUpdateRequest
Properties:
  graceEndAt (datetime)

DelinquencyEventResponse
Properties:
  locator (ulid, required)
  delinquencyLocator (ulid, required)
  delinquencyEventState (Enum active | triggered | cancelled, required)
  triggerTime (datetime, required)
  triggeredAt (datetime)
  createdAt (datetime, required)
  createdBy (uuid, required)
  updatedAt (datetime, required)
  updatedBy (uuid, required)
  name (string, required)

DelinquencyEventsResponse
Properties:
  accountLocator (ulid, required)
  delinquencyLocator (ulid, required)
  listCompleted (boolean, required)
  items (DelinquencyEventResponse[], required)

DelinquencyEventUpdateRequest
Properties:
  triggerTime (datetime)
  delinquencyEventState (Enum active | triggered | cancelled)

# Disbursements API



<EndpointIndex
  names={[
  	'fetchDisbursement',
  	'fetchMultipleDisbursements',
  	'createDisbursement',
  	'updateDisbursement',
  	'updateDisbursementReplaceData',
  	'validateDisbursement',
  	'approveDisbursement',
  	'executeDisbursement',
  	'rejectDisbursement',
  	'resetDisbursement',
  	'reverseDisbursement',
  	'discardDisbursement',
  	'fetchDisbursementsWithNumber',
  	'setDisbursementNumber',
  	'generateDisbursementNumber',
  ]}
  titles={{
  	createDisbursement: 'Create a Disbursement',
  	updateDisbursement: 'Update a Disbursement',
  	updateDisbursementReplaceData:
  		'Update a Disbursement and Replace Extension Data',
  	validateDisbursement: 'Validate a Disbursement',
  	approveDisbursement: 'Approve a Disbursement',
  	executeDisbursement: 'Execute a Disbursement',
  	rejectDisbursement: 'Reject a Disbursement',
  	resetDisbursement: 'Reset a Disbursement',
  	reverseDisbursement: 'Reverse a Disbursement',
  	discardDisbursement: 'Discard a Disbursement',
  }}
/>

Fetch [#fetch]

Fetch Disbursement [#fetch-disbursement]

<ApiEndpoint name="fetchDisbursement" />

Fetch Multiple Disbursements [#fetch-multiple-disbursements]

<ApiEndpoint name="fetchMultipleDisbursements" />

<ApiSchema name="DisbursementListResponse" />

<ApiSchema name="DisbursementResponse" />

Lifecycle [#lifecycle]

Create a Disbursement [#create-a-disbursement]

<ApiEndpoint name="createDisbursement" title="Create a Disbursement" />

<ApiSchema name="DisbursementCreateRequest" />

Update a Disbursement [#update-a-disbursement]

<ApiEndpoint name="updateDisbursement" title="Update a Disbursement" />

<ApiSchema name="DisbursementUpdateRequest" />

Update a Disbursement and Replace Extension Data [#update-a-disbursement-and-replace-extension-data]

<ApiEndpoint name="updateDisbursementReplaceData" title="Update a Disbursement and Replace Extension Data" />

<ApiSchema name="DisbursementUpdateReplaceDataRequest" />

Validate a Disbursement [#validate-a-disbursement]

<ApiEndpoint name="validateDisbursement" title="Validate a Disbursement" />

Approve a Disbursement [#approve-a-disbursement]

<ApiEndpoint name="approveDisbursement" title="Approve a Disbursement" />

Execute a Disbursement [#execute-a-disbursement]

<ApiEndpoint name="executeDisbursement" title="Execute a Disbursement" />

Reject a Disbursement [#reject-a-disbursement]

<ApiEndpoint name="rejectDisbursement" title="Reject a Disbursement" />

Reset a Disbursement [#reset-a-disbursement]

<ApiEndpoint name="resetDisbursement" title="Reset a Disbursement" />

Reverse a Disbursement [#reverse-a-disbursement]

<ApiEndpoint name="reverseDisbursement" title="Reverse a Disbursement" />

Discard a Disbursement [#discard-a-disbursement]

<ApiEndpoint name="discardDisbursement" title="Discard a Disbursement" />

Numbering [#numbering]

Fetch Disbursements With Number [#fetch-disbursements-with-number]

<ApiEndpoint name="fetchDisbursementsWithNumber" />

Set Disbursement Number [#set-disbursement-number]

<ApiEndpoint name="setDisbursementNumber" />

Generate Disbursement Number [#generate-disbursement-number]

<ApiEndpoint name="generateDisbursementNumber" />

See Also [#see-also]

* [Disbursements Feature Guide](/features/billing/disbursements)


## API Reference

GET /billing/{tenantLocator}/disbursements/{locator} — fetchDisbursement
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

GET /billing/{tenantLocator}/disbursements/list — fetchMultipleDisbursements
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  accountLocator (ulid, query)
  extended (boolean, query)
Responses:
  200 DisbursementListResponse — OK

POST /billing/{tenantLocator}/disbursements — createDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (DisbursementCreateRequest):
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator} — updateDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DisbursementUpdateRequest):
Responses:
  200 DisbursementResponse — OK

PUT /billing/{tenantLocator}/disbursements/{locator} — updateDisbursementReplaceData
Updates the disbursement and replaces all existing data extensions with the data.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DisbursementUpdateReplaceDataRequest):
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/validate — validateDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/approve — approveDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/execute — executeDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/reject — rejectDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/reset — resetDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/reverse — reverseDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

PATCH /billing/{tenantLocator}/disbursements/{locator}/discard — discardDisbursement
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

GET /billing/{tenantLocator}/disbursements/numbers/{disbursementNumber} — fetchDisbursementsWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  disbursementNumber (string, path, required)
Responses:
  200 DisbursementResponse[] — OK

POST /billing/{tenantLocator}/disbursements/{locator}/number/set — setDisbursementNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  disbursementNumber (string, query, required)
Responses:
  200 DisbursementResponse — OK

POST /billing/{tenantLocator}/disbursements/{locator}/number/generate — generateDisbursementNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DisbursementResponse — OK

DisbursementListResponse
Properties:
  listCompleted (boolean, required)
  items (DisbursementResponse[], required)

DisbursementResponse
Properties:
  locator (ulid, required)
  disbursementState (Enum draft | validated | approved | executed | reversed | rejected | discarded, required)
  type (string, required)
  currency (string, required)
  amount (number, required)
  data (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid)
  sources (CreditItem[], required)
  externalCashTransactionLocator (ulid)
  validationResult (ValidationResult)
  disbursementNumber (string)
  anonymizedAt (datetime)

DisbursementCreateRequest
Properties:
  accountLocator (ulid)
  type (string, required)
  amount (number, required)
  data (map<string, object>, required)
  sources (CreditItem[], required)
  useDefaultFinancialInstrument (boolean, required)
  financialInstrumentLocator (ulid)
  transactionMethod (Enum ach | cash | eft | standard | wire)
  transactionNumber (string)
  currency (string)

DisbursementUpdateRequest
Properties:
  accountLocator (ulid)
  type (string)
  amount (number)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  addSources (CreditItem[], required)
  removeSources (ulid[], required)
  useDefaultFinancialInstrument (boolean)
  financialInstrumentLocator (ulid)
  transactionMethod (Enum ach | cash | eft | standard | wire)
  transactionNumber (string)
  currency (string)

DisbursementUpdateReplaceDataRequest
Properties:
  accountLocator (ulid)
  type (string, required)
  amount (number, required)
  data (map<string, object>, required)
  sources (CreditItem[], required)
  useDefaultFinancialInstrument (boolean, required)
  financialInstrumentLocator (ulid)
  transactionMethod (Enum ach | cash | eft | standard | wire)
  transactionNumber (string)
  currency (string)

# Financial Instruments and External Cash Transactions API



<EndpointIndex
  names={[
  	'fetchFinancialInstrument',
  	'listFinancialInstruments',
  	'createFinancialInstrument',
  	'setFinancialInstrumentAsDefault',
  	'updateFinancialInstrument',
  	'fetchExternalCashTransaction',
  ]}
  titles={{
  	fetchFinancialInstrument: 'Fetch a Financial Instrument',
  	listFinancialInstruments: 'Fetch Financial Instruments for a Tenant',
  	createFinancialInstrument: 'Create a Financial Instrument',
  	setFinancialInstrumentAsDefault:
  		'Set the Default Financial Instrument for a Tenant',
  	updateFinancialInstrument: 'Update a Financial Instrument',
  	fetchExternalCashTransaction: 'Fetch an External Cash Transaction',
  }}
/>

Financial Instruments [#financial-instruments]

Fetch a Financial Instrument [#fetch-a-financial-instrument]

<ApiEndpoint name="fetchFinancialInstrument" title="Fetch a Financial Instrument" />

<ApiSchema name="FinancialInstrumentResponse" />

Fetch Financial Instruments for a Tenant [#fetch-financial-instruments-for-a-tenant]

<ApiEndpoint name="listFinancialInstruments" title="Fetch Financial Instruments for a Tenant" />

<ApiSchema name="FinancialInstrumentListResponse" />

Create a Financial Instrument [#create-a-financial-instrument]

<ApiEndpoint name="createFinancialInstrument" title="Create a Financial Instrument" />

<ApiSchema name="FinancialInstrumentCreateRequest" />

Set the Default Financial Instrument for a Tenant [#set-the-default-financial-instrument-for-a-tenant]

<ApiEndpoint name="setFinancialInstrumentAsDefault" title="Set the Default Financial Instrument for a Tenant" />

Update a Financial Instrument [#update-a-financial-instrument]

<ApiEndpoint name="updateFinancialInstrument" title="Update a Financial Instrument" />

External Cash Transactions [#external-cash-transactions]

Fetch an External Cash Transaction [#fetch-an-external-cash-transaction]

<ApiEndpoint name="fetchExternalCashTransaction" title="Fetch an External Cash Transaction" />

<ApiSchema name="ExternalCashTransactionResponse" />


## API Reference

GET /billing/{tenantLocator}/financialInstruments/{locator} — fetchFinancialInstrument
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 FinancialInstrumentResponse — OK

GET /billing/{tenantLocator}/financialInstruments/list — listFinancialInstruments
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
  account (ulid, query)
Responses:
  200 FinancialInstrumentListResponse — OK

POST /billing/{tenantLocator}/financialInstruments — createFinancialInstrument
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (FinancialInstrumentCreateRequest):
Responses:
  200 FinancialInstrumentResponse — OK

POST /billing/{tenantLocator}/financialInstruments/{locator}/setAsDefault — setFinancialInstrumentAsDefault
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  value (boolean, query)
Responses:
  200 FinancialInstrumentResponse — OK

PATCH /billing/{tenantLocator}/financialInstruments/{locator} — updateFinancialInstrument
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (FinancialInstrumentCreateRequest):
Responses:
  200 FinancialInstrumentResponse — OK

GET /billing/{tenantLocator}/externalCashTransactions/{locator} — fetchExternalCashTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 ExternalCashTransactionResponse — OK

FinancialInstrumentResponse
Properties:
  locator (ulid, required)
  externalIdentifier (string)
  institutionName (string)
  instrumentType (Enum checking | savings | creditCard | debitCard)
  defaultTransactionMethod (Enum ach | cash | eft | standard | wire)
  externalAccountNumber (string)
  accountLocator (ulid)
  nickname (string)
  expirationTime (datetime)
  isDefault (boolean, required)
  retryPlanName (string)

FinancialInstrumentListResponse
Properties:
  listCompleted (boolean, required)
  items (FinancialInstrumentResponse[], required)

FinancialInstrumentCreateRequest
Properties:
  externalIdentifier (string)
  institutionName (string)
  instrumentType (Enum checking | savings | creditCard | debitCard)
  defaultTransactionMethod (Enum ach | cash | eft | standard | wire)
  externalAccountNumber (string)
  accountLocator (ulid)
  nickname (string)
  expirationTime (datetime)
  retryPlanName (string)

ExternalCashTransactionResponse
Properties:
  locator (ulid, required)
  financialInstrumentLocator (ulid)
  transactionMethod (Enum ach | cash | eft | standard | wire, required)
  transactionNumber (string)

# Flat Charges API



<EndpointIndex
  names={[
  	'addCharges',
  	'reverseCharges',
  	'updateQuoteInvoiceFeeAmount',
  	'updatePolicyInvoiceFeeAmount',
  	'fetchChargesByAccount',
  	'fetchChargesByPolicy',
  	'fetchChargesByTransaction',
  ]}
  titles={{
  	addCharges: 'Add Charges',
  	reverseCharges: 'Reverse Charges',
  	updateQuoteInvoiceFeeAmount: 'Add or update invoice fee on a quote',
  	updatePolicyInvoiceFeeAmount: 'Add or update invoice fee on a policy',
  	fetchChargesByAccount: 'Fetch Charges by Account',
  	fetchChargesByPolicy: 'Fetch Charges by Policy',
  	fetchChargesByTransaction: 'Fetch Charges by Transaction',
  }}
/>

Create and Reverse [#create-and-reverse]

Add Charges [#add-charges]

<ApiEndpoint name="addCharges" title="Add Charges" />

<ApiSchema name="ChargesCreateRequest" />

<ApiSchema name="ChargeCreateRequest" />

Since charges are created with reference to an account, any `policyLocator` or
`transactionLocator` in the charge creation request must belong to the account.
If `transactionLocator` and `elementLocator` are provided, the `elementLocator`
must belong to the transaction specified by `transactionLocator`.

If the charge creation request references a specific `policyLocator`, the resulting <ApiLink name="InvoiceItemResponse">invoice item</ApiLink> or items will assume the policy's `timezone`. Otherwise, the `timezone` will be set to the tenant's `defaultTimezone`.

<ApiSchema name="ChargeResponse" />

Reverse Charges [#reverse-charges]

<ApiEndpoint name="reverseCharges" title="Reverse Charges" />

<ApiSchema name="ChargesReversalRequest" />

Add Invoice Fee to Policy or Quote [#add-invoice-fee-to-policy-or-quote]

Add or update invoice fee on a quote [#add-or-update-invoice-fee-on-a-quote]

<ApiEndpoint name="updateQuoteInvoiceFeeAmount" title="Add or update invoice fee on a quote" />

Add or update invoice fee on a policy [#add-or-update-invoice-fee-on-a-policy]

<ApiEndpoint name="updatePolicyInvoiceFeeAmount" title="Add or update invoice fee on a policy" />

<ApiSchema name="UpdateInvoiceFeeAmountRequest" />

Fetch [#fetch]

Fetch Charges by Account [#fetch-charges-by-account]

<ApiEndpoint name="fetchChargesByAccount" title="Fetch Charges by Account" />

<ApiSchema name="ListPageResponseChargeResponse" />

Fetch Charges by Policy [#fetch-charges-by-policy]

<ApiEndpoint name="fetchChargesByPolicy" title="Fetch Charges by Policy" />

Fetch Charges by Transaction [#fetch-charges-by-transaction]

<ApiEndpoint name="fetchChargesByTransaction" title="Fetch Charges by Transaction" />


## API Reference

POST /billing/{tenantLocator}/accounts/{accountLocator}/charges — addCharges
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
Request body (ChargesCreateRequest):
Responses:
  200 ChargeResponse[] — OK

POST /billing/{tenantLocator}/accounts/{accountLocator}/charges/reverse — reverseCharges
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
Request body (ChargesReversalRequest):
Responses:
  200 ChargeResponse[] — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/invoiceFeeAmount — updateQuoteInvoiceFeeAmount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateInvoiceFeeAmountRequest):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/invoiceFeeAmount — updatePolicyInvoiceFeeAmount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateInvoiceFeeAmountRequest):
Responses:
  200 PolicyResponse — OK

GET /billing/{tenantLocator}/accounts/{accountLocator}/charges/list — fetchChargesByAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseChargeResponse — OK

GET /billing/{tenantLocator}/policies/{policyLocator}/charges/list — fetchChargesByPolicy
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseChargeResponse — OK

GET /billing/{tenantLocator}/transactions/{transactionLocator}/charges/list — fetchChargesByTransaction
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  transactionLocator (ulid, path, required)
  includeAll (boolean, query)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseChargeResponse — OK

ChargesCreateRequest
Properties:
  policyLocator (ulid)
  invoicing (Enum scheduled | next | immediate)
  currency (string)
  charges (ChargeCreateRequest[], required)

ChargeCreateRequest
Properties:
  amount (number, required)
  chargeType (string, required)
  transactionLocator (ulid)
  elementLocator (ulid)
  elementStaticLocator (ulid)
  tag (string)

ChargeResponse
Properties:
  locator (ulid, required)
  amount (number, required)
  currency (string, required)
  chargeCategory (Enum none | premium | tax | fee | credit | invoiceFee | cededPremium | nonFinancial | surcharge, required)
  chargeType (string, required)
  chargeInvoicing (Enum scheduled | next | immediate, required)
  accountLocator (ulid, required)
  tag (string)
  policyLocator (ulid)
  transactionLocator (ulid)
  elementLocator (ulid)
  elementStaticLocator (ulid)
  reversalOfLocator (ulid)
  bundleTransactionLocator (ulid)

ChargesReversalRequest
Properties:
  charges (ulid[], required)
  invoicing (Enum scheduled | next | immediate, required)

UpdateInvoiceFeeAmountRequest
Properties:
  invoiceFeeAmount (number, required)

ListPageResponseChargeResponse
Properties:
  listCompleted (boolean, required)
  items (ChargeResponse[], required)

# Billing Holds API



Billing Holds are used to temporarily suspend invoicing and delinquency processes including lapse.

<EndpointIndex
  names={[
  	'fetchHold',
  	'fetchAllHoldsForAnAccount',
  	'createHold',
  	'updateHold',
  	'validateHold',
  	'activateHold',
  	'releaseHold',
  	'resetHold',
  	'discardHold',
  ]}
/>

Fetch [#fetch]

Fetch Hold [#fetch-hold]

<ApiEndpoint name="fetchHold" />

<ApiSchema name="HoldResponse" />

Fetch All Holds For An Account [#fetch-all-holds-for-an-account]

<ApiEndpoint name="fetchAllHoldsForAnAccount" />

<ApiSchema name="HoldListResponse" />

Creation and Update [#creation-and-update]

Create Hold [#create-hold]

<ApiEndpoint name="createHold" />

<ApiSchema name="HoldCreateRequest" />

Update Hold [#update-hold]

<ApiEndpoint name="updateHold" />

<ApiSchema name="HoldUpdateRequest" />

Execution [#execution]

Validate Hold [#validate-hold]

<ApiEndpoint name="validateHold" />

Activate Hold [#activate-hold]

<ApiEndpoint name="activateHold" />

Release, Reset, and Discard [#release-reset-and-discard]

Release Hold [#release-hold]

<ApiEndpoint name="releaseHold" />

Reset Hold [#reset-hold]

<ApiEndpoint name="resetHold" />

Discard Hold [#discard-hold]

<ApiEndpoint name="discardHold" />

See Also [#see-also]

* [Billing Holds Feature Guide](/features/billing/billing-holds)


## API Reference

GET /billing/{tenantLocator}/holds/{locator} — fetchHold
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 HoldResponse — OK

GET /billing/{tenantLocator}/holds/accounts/{accountLocator}/list — fetchAllHoldsForAnAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  state (Enum draft | validated | active | discarded | released, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 HoldListResponse — OK

POST /billing/{tenantLocator}/holds — createHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (HoldCreateRequest):
Responses:
  200 HoldResponse — OK

PATCH /billing/{tenantLocator}/holds/{locator} — updateHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (HoldUpdateRequest):
Responses:
  200 HoldResponse — OK

PATCH /billing/{tenantLocator}/holds/{locator}/validate — validateHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 HoldResponse — OK

PATCH /billing/{tenantLocator}/holds/{locator}/activate — activateHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 HoldResponse — OK

PATCH /billing/{tenantLocator}/holds/{locator}/release — releaseHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 HoldResponse — OK

PATCH /billing/{tenantLocator}/holds/{locator}/reset — resetHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 HoldResponse — OK

PATCH /billing/{tenantLocator}/holds/{locator}/discard — discardHold
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 HoldResponse — OK

HoldResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  targetType (Enum invoicing | delinquency, required)
  holdState (Enum draft | validated | active | discarded | released, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  validationResult (ValidationResult)

HoldListResponse
Properties:
  listCompleted (boolean, required)
  items (HoldResponse[], required)

HoldCreateRequest
Properties:
  accountLocator (ulid, required)
  targetType (Enum invoicing | delinquency, required)

HoldUpdateRequest
Properties:
  accountLocator (ulid)
  targetType (Enum invoicing | delinquency)

# Billing API Index



Main Index [#main-index]

Policy Service Endpoints [#policy-service-endpoints]

The following endpoints are used to update billing parameters but are hosted on their respective services:

Update Billing Level For An Account [#update-billing-level-for-an-account]

<ApiEndpoint name="updateBillingLevelForAnAccount" />

Update Billing Level For APolicy [#update-billing-level-for-apolicy]

<ApiEndpoint name="updateBillingLevelForAPolicy" />

Update Billing Level For AQuote [#update-billing-level-for-aquote]

<ApiEndpoint name="updateBillingLevelForAQuote" />


## API Reference

PATCH /policy/{tenantLocator}/accounts/{locator}/billingLevel — updateBillingLevelForAnAccount
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateBillingLevelRequest):
Responses:
  200 AccountResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/billingLevel — updateBillingLevelForAPolicy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateBillingLevelRequest):
Responses:
  200 PolicyResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/billingLevel — updateBillingLevelForAQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateBillingLevelRequest):
Responses:
  200 QuoteResponse — OK

# Installment Lattices API



<EndpointIndex
  names={[
  	'fetchLatestInstallmentLatticeByQuoteLocator',
  	'fetchInstallmentLatticesByPolicyLocator',
  	'fetchInstallmentLatticeSettings',
  ]}
  titles={{
  	fetchLatestInstallmentLatticeByQuoteLocator:
  		'Fetch an Installment Lattice for a Quote',
  	fetchInstallmentLatticesByPolicyLocator:
  		'Fetch Installment Lattices for a Policy',
  	fetchInstallmentLatticeSettings:
  		'Fetch Settings for an Installment Lattice',
  }}
/>

Fetch an Installment Lattice for a Quote [#fetch-an-installment-lattice-for-a-quote]

<ApiEndpoint name="fetchLatestInstallmentLatticeByQuoteLocator" title="Fetch an Installment Lattice for a Quote" />

Fetch Installment Lattices for a Policy [#fetch-installment-lattices-for-a-policy]

<ApiEndpoint name="fetchInstallmentLatticesByPolicyLocator" title="Fetch Installment Lattices for a Policy" />

<ApiSchema name="InstallmentLatticeListResponse" />

<ApiSchema name="InstallmentLatticeResponse" />

<ApiSchema name="InstallmentLatticeFrame" />

Fetch Settings for an Installment Lattice [#fetch-settings-for-an-installment-lattice]

<ApiEndpoint name="fetchInstallmentLatticeSettings" title="Fetch Settings for an Installment Lattice" />

<ApiSchema name="SettingsResponse" />

<ApiSchema name="InstallmentSettings" />

See Also [#see-also]

* [Installments and Installment Lattices Feature Guide](/features/billing/installments-and-installment-lattices)


## API Reference

GET /billing/{tenantLocator}/installmentLattices/quotes/{quoteLocator} — fetchLatestInstallmentLatticeByQuoteLocator
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
Responses:
  200 InstallmentLatticeResponse — OK

GET /billing/{tenantLocator}/installmentLattices/policies/{policyLocator}/list — fetchInstallmentLatticesByPolicyLocator
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InstallmentLatticeListResponse — OK

GET /billing/{tenantLocator}/settings/{locator} — fetchInstallmentLatticeSettings
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 SettingsResponse — OK

InstallmentLatticeListResponse
Properties:
  listCompleted (boolean, required)
  items (InstallmentLatticeResponse[], required)

InstallmentLatticeResponse
Properties:
  locator (ulid, required)
  settingsLocator (ulid)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid, required)
  termStartTime (datetime, required)
  termEndTime (datetime, required)
  termLocator (ulid)
  quoteLocator (ulid)
  policyLocator (ulid)
  currency (string, required)
  timezone (string, required)
  basedOnLocator (ulid)
  effectiveTime (datetime, required)
  frames (InstallmentLatticeFrame[], required)
  reversalLattice (boolean, required)

InstallmentLatticeFrame
Properties:
  installmentStartTime (datetime, required)
  installmentEndTime (datetime, required)
  coverageStartTime (datetime, required)
  coverageEndTime (datetime, required)
  installmentDuration (number, required)
  normalizedWeight (number, required)
  coverageDuration (number, required)
  generateTime (datetime, required)
  dueTime (datetime, required)
  autopayTime (datetime, required)

SettingsResponse
Properties:
  locator (ulid, required)
  installmentSettings (InstallmentSettings, required)

InstallmentSettings
Properties:
  cadence (Enum none | fullPay | weekly | everyOtherWeek | monthly | quarterly | semiannually | annually | thirtyDays | everyNDays, required)
  anchorMode (Enum generateDay | termStartDay | dueDay, required)
  generateLeadDays (integer, required)
  dueLeadDays (integer, required)
  installmentWeights (number[], required)
  maxInstallmentsPerTerm (integer)
  anchorType (Enum none | dayOfMonth | anchorTime | dayOfWeek | weekOfMonth)
  dayOfMonth (integer)
  dayOfWeek (Enum monday | tuesday | wednesday | thursday | friday | saturday | sunday)
  weekOfMonth (Enum none | first | second | third | fourth | fifth)
  anchorTime (datetime)
  autopayLeadDays (number)

# Installments API



<EndpointIndex
  names={[
  	'fetchInstallmentsForQuote',
  	'fetchInstallmentsForPolicy',
  	'fetchInstallmentsForPolicyTransaction',
  	'previewInstallmentsForStatelessQuote',
  	'updateInstallments',
  ]}
  titles={{
  	fetchInstallmentsForQuote: 'Fetch Installments for a Quote',
  	fetchInstallmentsForPolicy: 'Fetch Installments for a Policy',
  	fetchInstallmentsForPolicyTransaction:
  		'Fetch Installments for a Policy Transaction',
  	previewInstallmentsForStatelessQuote:
  		'Preview Installments for a Stateless Quote',
  }}
/>

Fetch Installments for a Quote [#fetch-installments-for-a-quote]

<ApiEndpoint name="fetchInstallmentsForQuote" title="Fetch Installments for a Quote" />

Fetch Installments for a Policy [#fetch-installments-for-a-policy]

<ApiEndpoint name="fetchInstallmentsForPolicy" title="Fetch Installments for a Policy" />

Fetch Installments for a Policy Transaction [#fetch-installments-for-a-policy-transaction]

<ApiEndpoint name="fetchInstallmentsForPolicyTransaction" title="Fetch Installments for a Policy Transaction" />

<ApiSchema name="InstallmentListResponse" />

<ApiSchema name="Installment" />

<ApiSchema name="InstallmentItem" />

Preview Installments for a Stateless Quote [#preview-installments-for-a-stateless-quote]

<ApiEndpoint name="previewInstallmentsForStatelessQuote" title="Preview Installments for a Stateless Quote" />

<ApiSchema name="QuoteBillingPreviewRequest" />

<ApiSchema name="PreviewChargeRequest" />

<ApiSchema name="InstallmentsPreview" />

<ApiSchema name="ChargeQueueItem" />

<ApiSchema name="ChargeMetadata" />

<ApiSchema name="Settings" />

Update Installments [#update-installments]

<ApiEndpoint name="updateInstallments" />

<ApiSchema name="PatchInstallmentsRequest" />


## API Reference

GET /billing/{tenantLocator}/installments/quotes/{quoteLocator}/list — fetchInstallmentsForQuote
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InstallmentListResponse — OK

GET /billing/{tenantLocator}/installments/policies/{policyLocator}/list — fetchInstallmentsForPolicy
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InstallmentListResponse — OK

GET /billing/{tenantLocator}/installments/transactions/{transactionLocator}/list — fetchInstallmentsForPolicyTransaction
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  transactionLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InstallmentListResponse — OK

GET /billing/{tenantLocator}/installments/quotes/statelessPreview — previewInstallmentsForStatelessQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  quotePreviewRequest (QuoteBillingPreviewRequest, query, required)
Responses:
  200 InstallmentsPreview — OK

PATCH /billing/{tenantLocator}/installments — updateInstallments
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (PatchInstallmentsRequest):
Responses:
  200 Installment[] — OK

InstallmentListResponse
Properties:
  listCompleted (boolean, required)
  items (Installment[], required)

Installment
Properties:
  locator (ulid, required)
  installmentLatticeLocator (ulid, required)
  accountLocator (ulid, required)
  currency (string, required)
  timezone (string, required)
  installmentFrameIndex (integer, required)
  quoteLocator (ulid)
  policyLocator (ulid)
  transactionLocator (ulid)
  installmentStartTime (datetime, required)
  installmentEndTime (datetime, required)
  coverageStartTime (datetime, required)
  coverageEndTime (datetime, required)
  installmentDuration (number, required)
  coverageDuration (number, required)
  generateTime (datetime, required)
  dueTime (datetime, required)
  invoiceLocator (ulid)
  createdAt (datetime, required)
  createdBy (uuid, required)
  updatedAt (datetime, required)
  updatedBy (uuid, required)
  installmentItems (InstallmentItem[], required)
  reversalOfInstallmentLocator (ulid)
  termLocator (ulid)
  migratedFromInstallmentLocator (ulid)
  autopayTime (datetime)
  enhancedByPlugin (boolean)

InstallmentItem
Properties:
  locator (ulid, required)
  installmentLocator (ulid, required)
  chargeLocator (ulid, required)
  elementLocator (ulid, required)
  elementStaticLocator (ulid, required)
  chargeType (string, required)
  chargeCategory (string, required)
  amount (number, required)
  invoiceItemLocator (ulid)
  createdAt (datetime, required)
  createdBy (uuid, required)
  reversalOfInstallmentItemLocator (ulid)

QuoteBillingPreviewRequest
Properties:
  accountLocator (ulid, required)
  productName (string, required)
  termStartTime (datetime, required)
  termEndTime (datetime, required)
  timezone (string)
  durationBasis (Enum years | months | weeks | days | hours)
  currency (string)
  invoiceFeeAmount (number)
  installmentPreferences (InstallmentPreferences)
  charges (PreviewChargeRequest[], required)

PreviewChargeRequest
Properties:
  amount (number, required)
  chargeType (string, required)
  elementLocator (ulid)
  elementStaticLocator (ulid)

InstallmentsPreview
Properties:
  installments (Installment[], required)
  accountLocator (ulid, required)
  quoteLocator (ulid)
  policyLocator (ulid)
  transactionLocator (ulid)
  queuedPolicyCharges (ChargeQueueItem[], required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  settings (Settings, required)
  persistedInstallmentLocators (ulid[], required)

ChargeQueueItem
Properties:
  chargeLocator (ulid, required)
  accountLocator (ulid, required)
  invoiceItemLocator (ulid)
  chargeSource (Enum billing | policy, required)
  currency (string, required)
  amount (number, required)
  chargeType (string, required)
  chargeMetadata (ChargeMetadata, required)

ChargeMetadata
Properties:
  policyLocator (ulid)
  transactionLocator (ulid)
  elementStaticLocator (ulid)
  timezone (string)
  invoicing (Enum scheduled | next | immediate)

Settings
Properties:
  locator (ulid, required)
  installmentSettings (InstallmentSettings, required)
  createdAt (datetime, required)
  createdBy (uuid, required)

PatchInstallmentsRequest
Properties:
  installmentLocators (ulid[], required)
  generateTime (datetime)
  dueTime (datetime)
  autopayTime (datetime)

# Invoices API



<EndpointIndex
  names={[
  	'fetchInvoicesForQuote',
  	'fetchInvoicesForPolicy',
  	'fetchInvoicesForAccount',
  	'getInvoiceWithItems',
  	'fetchInvoiceDetails',
  	'fetchPaymentsForAnInvoice',
  	'fetchCreditsForAnInvoice',
  	'fetchInvoicesTargetedByAPayment',
  	'updateInvoice',
  	'settleNegativeOrZeroInvoice',
  	'fetchDebitsForAnInvoice',
  	'previewInvoicesForQuote',
  	'previewInvoicesForTransaction',
  	'previewInvoicesForStatelessQuote',
  	'fetchInvoiceWithNumber',
  	'setInvoiceNumber',
  	'generateInvoiceNumber',
  	'initiateEarlyInvoicing',
  ]}
  titles={{
  	fetchInvoicesForQuote: 'Fetch Invoices for a Quote',
  	fetchInvoicesForPolicy: 'Fetch Invoices for a Policy',
  	fetchInvoicesForAccount: 'Fetch Invoices for an Account',
  	getInvoiceWithItems: 'Fetch an Invoice with Its Items',
  }}
/>

Fetch [#fetch]

Fetch Invoices for a Quote [#fetch-invoices-for-a-quote]

<ApiEndpoint name="fetchInvoicesForQuote" title="Fetch Invoices for a Quote" />

Fetch Invoices for a Policy [#fetch-invoices-for-a-policy]

<ApiEndpoint name="fetchInvoicesForPolicy" title="Fetch Invoices for a Policy" />

Fetch Invoices for an Account [#fetch-invoices-for-an-account]

<ApiEndpoint name="fetchInvoicesForAccount" title="Fetch Invoices for an Account" />

Fetch an Invoice with Its Items [#fetch-an-invoice-with-its-items]

<ApiEndpoint name="getInvoiceWithItems" title="Fetch an Invoice with Its Items" />

<ApiSchema name="InvoiceResponse" />

<ApiSchema name="InvoiceItemResponse" />

Fetch Invoice Details [#fetch-invoice-details]

<ApiEndpoint name="fetchInvoiceDetails" />

<ApiSchema name="InvoiceDetailsResponse" />

Fetch Payments For An Invoice [#fetch-payments-for-an-invoice]

<ApiEndpoint name="fetchPaymentsForAnInvoice" />

<ApiSchema name="PaymentListResponse" />

Fetch Credits For An Invoice [#fetch-credits-for-an-invoice]

<ApiEndpoint name="fetchCreditsForAnInvoice" />

Fetch Invoices Targeted By APayment [#fetch-invoices-targeted-by-apayment]

<ApiEndpoint name="fetchInvoicesTargetedByAPayment" />

<ApiSchema name="InvoiceListResponse" />

<ApiSchema name="InvoiceSummary" />

<ApiSchema name="InvoiceSummaryView" />

<ApiSchema name="FlatChargeSummary" />

<ApiSchema name="InstallmentItemSummary" />

<ApiSchema name="InvoiceItemSummary" />

Update [#update]

Update Invoice [#update-invoice]

<ApiEndpoint name="updateInvoice" />

<ApiSchema name="InvoiceUpdateRequest" />

Negative Invoice Handling [#negative-invoice-handling]

Settle Negative Or Zero Invoice [#settle-negative-or-zero-invoice]

<ApiEndpoint name="settleNegativeOrZeroInvoice" />

Fetch Debits For An Invoice [#fetch-debits-for-an-invoice]

<ApiEndpoint name="fetchDebitsForAnInvoice" />

<ApiSchema name="ListPageResponseDebitResponse" />

<ApiSchema name="DebitResponse" />

<ApiSchema name="ListPageResponseCreditDistributionResponse" />

Invoice Documents [#invoice-documents]

If you have configured invoicing to generate an invoice document, you can fetch it with the <ApiLink name="fetchInvoiceDocument" /> endpoint.

Invoice Preview [#invoice-preview]

Preview Invoices For Quote [#preview-invoices-for-quote]

<ApiEndpoint name="previewInvoicesForQuote" />

Preview Invoices For Transaction [#preview-invoices-for-transaction]

<ApiEndpoint name="previewInvoicesForTransaction" />

<ApiSchema name="InvoicePreviewResponse" />

<ApiSchema name="InvoiceItemPreview" />

Preview Invoices For Stateless Quote [#preview-invoices-for-stateless-quote]

<ApiEndpoint name="previewInvoicesForStatelessQuote" />

Numbering [#numbering]

Fetch Invoice With Number [#fetch-invoice-with-number]

<ApiEndpoint name="fetchInvoiceWithNumber" />

Set Invoice Number [#set-invoice-number]

<ApiEndpoint name="setInvoiceNumber" />

Generate Invoice Number [#generate-invoice-number]

<ApiEndpoint name="generateInvoiceNumber" />

Early Invoicing [#early-invoicing]

Initiate Early Invoicing [#initiate-early-invoicing]

<ApiEndpoint name="initiateEarlyInvoicing" />

<ApiSchema name="EarlyInvoicingRequest" />

<ApiSchema name="EarlyInvoicingResponse" />


## API Reference

GET /billing/{tenantLocator}/invoices/quotes/{quoteLocator}/list — fetchInvoicesForQuote
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  includeZeroAmountInvoices (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceListResponse — OK

GET /billing/{tenantLocator}/invoices/policies/{policyLocator}/list — fetchInvoicesForPolicy
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  includeZeroAmountInvoices (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceListResponse — OK

GET /billing/{tenantLocator}/invoices/accounts/{accountLocator}/list — fetchInvoicesForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  accountLocator (ulid, path, required)
  includeZeroAmountInvoices (boolean, query)
  includeContainedInvoices (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceListResponse — OK

GET /billing/{tenantLocator}/invoices/{locator} — getInvoiceWithItems
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 InvoiceResponse — OK

GET /billing/{tenantLocator}/invoices/{locator}/details — fetchInvoiceDetails
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 InvoiceDetailsResponse — OK

GET /billing/{tenantLocator}/invoices/{locator}/payments/list — fetchPaymentsForAnInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 PaymentListResponse — OK

GET /billing/{tenantLocator}/invoices/{locator}/credits/list — fetchCreditsForAnInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 CreditListResponse — OK

GET /billing/{tenantLocator}/payments/{locator}/invoices/list — fetchInvoicesTargetedByAPayment
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceListResponse — OK

PATCH /billing/{tenantLocator}/invoices/{locator} — updateInvoice
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (InvoiceUpdateRequest):
Responses:
  200 InvoiceResponse — OK

POST /billing/{tenantLocator}/invoices/{locator}/settle — settleNegativeOrZeroInvoice
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  forced (boolean, query)
Responses:
  200 ListPageResponseCreditDistributionResponse — OK

GET /billing/{tenantLocator}/invoices/{invoiceLocator}/debits/list — fetchDebitsForAnInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  invoiceLocator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseDebitResponse — OK

GET /billing/{tenantLocator}/invoices/quotes/{locator}/previewInvoices — previewInvoicesForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeZeroAmountInvoices (boolean, query)
  count (integer, query)
Responses:
  200 InvoicePreviewResponse[] — OK

GET /billing/{tenantLocator}/invoices/transactions/{locator}/previewInvoices — previewInvoicesForTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeZeroAmountInvoices (boolean, query)
  count (integer, query)
Responses:
  200 InvoicePreviewResponse[] — OK

GET /billing/{tenantLocator}/invoices/quotes/statelessPreview — previewInvoicesForStatelessQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  quotePreviewRequest (QuoteBillingPreviewRequest, query, required)
  includeZeroAmountInvoices (boolean, query)
  count (integer, query)
Responses:
  200 InvoicePreviewResponse[] — OK

GET /billing/{tenantLocator}/invoices/numbers/{invoiceNumber} — fetchInvoiceWithNumber
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  invoiceNumber (string, path, required)
Responses:
  200 InvoiceResponse[] — OK

POST /billing/{tenantLocator}/invoices/{locator}/number/set — setInvoiceNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  invoiceNumber (string, query, required)
Responses:
  200 InvoiceResponse — OK

POST /billing/{tenantLocator}/invoices/{locator}/number/generate — generateInvoiceNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 InvoiceResponse — OK

POST /billing/{tenantLocator}/invoices/earlyInvoicing — initiateEarlyInvoicing
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (EarlyInvoicingRequest):
Responses:
  200 EarlyInvoicingResponse — OK

InvoiceResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  invoiceState (Enum building | open | settled | discarded, required)
  invoiceItems (InvoiceItemResponse[]) — Not included when part of a list response
  generatedTime (datetime, required)
  dueTime (datetime, required)
  currency (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  unsettledTime (datetime)
  timezone (string, required)
  invoiceNumber (string)
  autopayTime (datetime)
  settledTime (datetime)
  aggregatedInvoiceLocator (ulid)
  invoiceType (Enum normal | aggregate, required)
  totalAmount (number)
  totalRemainingAmount (number)

InvoiceItemResponse
Properties:
  locator (ulid, required)
  chargeType (string, required)
  chargeCategory (string, required)
  amount (number, required)
  remainingAmount (number)
  settlementTime (datetime)
  invoiceLocator (ulid, required)
  installmentItemLocators (ulid[], required)
  timezone (string, required)
  quoteLocator (ulid)
  policyLocator (ulid)
  elementStaticLocator (ulid)
  elementType (string)
  transactionLocators (ulid[], required)
  unsettledTime (datetime)

InvoiceDetailsResponse
Properties:
  invoiceLocator (ulid, required)
  accountLocator (ulid, required)
  invoiceState (Enum building | open | settled | discarded, required)
  startTime (datetime, required)
  endTime (datetime, required)
  generatedTime (datetime, required)
  dueTime (datetime, required)
  currency (string, required)
  timezone (string, required)
  totalAmount (number, required)
  totalRemainingAmount (number, required)
  invoiceNumber (string)
  invoiceSummaries (InvoiceSummary[], required)
  autopayTime (datetime)
  unsettledTime (datetime)
  settledTime (datetime)
  aggregatedInvoiceLocator (ulid)
  invoiceType (Enum normal | aggregate, required)

PaymentListResponse
Properties:
  listCompleted (boolean, required)
  items (PaymentResponse[], required)

InvoiceListResponse
Properties:
  listCompleted (boolean, required)
  items (InvoiceSummaryView[], required)

InvoiceSummary
Properties:
  policyLocator (ulid)
  quoteLocator (ulid)
  productName (string)
  invoiceItemSummaries (InvoiceItemSummary[], required)

InvoiceSummaryView
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  invoiceState (Enum building | open | settled | discarded, required)
  generatedTime (datetime, required)
  autopayTime (datetime)
  dueTime (datetime, required)
  currency (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  settledTime (datetime)
  unsettledTime (datetime)
  timezone (string, required)
  invoiceNumber (string)
  totalAmount (number)
  totalRemainingAmount (number)
  invoiceType (Enum normal | aggregate, required)
  aggregatedInvoiceLocator (ulid)

FlatChargeSummary
Properties:
  transactionLocator (ulid)
  transactionType (string)
  transactionCategory (string)
  transactionEffectiveTime (datetime)
  amount (number, required)

InstallmentItemSummary
Properties:
  installmentItemLocator (ulid, required)
  installmentLocator (ulid, required)
  elementLocator (ulid, required)
  transactionLocator (ulid)
  transactionType (string)
  transactionCategory (string)
  transactionEffectiveTime (datetime)
  amount (number, required)

InvoiceItemSummary
Properties:
  invoiceItemLocator (ulid, required)
  elementType (string)
  elementStaticLocator (ulid)
  chargeType (string, required)
  chargeCategory (string, required)
  amount (number, required)
  remainingAmount (number, required)
  settlementTime (datetime)
  installmentItemSummaries (InstallmentItemSummary[], required)
  flatChargeSummary (FlatChargeSummary)
  unsettledTime (datetime)

InvoiceUpdateRequest
Properties:
  autopayTime (datetime)
  suppressAutopay (boolean)

ListPageResponseDebitResponse
Properties:
  listCompleted (boolean, required)
  items (DebitResponse[], required)

DebitResponse
Properties:
  invoiceLocator (ulid, required)
  targetType (Enum invoice | account | subpayment | invoiceItem, required)
  targetLocator (ulid, required)
  amount (number, required)
  reversed (boolean)
  reversedAt (datetime)

ListPageResponseCreditDistributionResponse
Properties:
  listCompleted (boolean, required)
  items (CreditDistributionResponse[], required)

InvoicePreviewResponse
Properties:
  generateTime (datetime, required)
  dueTime (datetime, required)
  startTime (datetime, required)
  endTime (datetime, required)
  invoiceItems (InvoiceItemPreview[], required)
  totalAmount (number, required)
  autopayTime (datetime, required)
  installmentLocators (ulid[], required)

InvoiceItemPreview
Properties:
  chargeType (string, required)
  chargeCategory (string, required)
  amount (number, required)
  quoteLocator (ulid)
  policyLocator (ulid)
  elementType (string, required)
  elementStaticLocator (ulid, required)
  transactionLocators (ulid[], required)

EarlyInvoicingRequest
Properties:
  accountLocator (ulid)
  invoiceThroughTime (datetime)
  installmentLocators (ulid[], required)
  invoiceDueTime (datetime)
  timezone (string)
  ignoreHolds (boolean, required)
  policyLocator (ulid)
  aggregateInvoices (boolean, required)
  includeExistingInvoices (boolean, required)

EarlyInvoicingResponse
Properties:
  jobLocator (ulid, required)
  candidateInstallmentsCount (integer, required)

# Payment Execution API



<Callout>
  The following endpoints are managed by the dedicated Payment Execution service in order to facilitate [PCI-Compliance ](https://listings.pcisecuritystandards.org/assessors_and_solutions/vpa_agreement). Please review Socotra's [PCI Compliance Statement](/features/security/pci-compliance-statement) for more information.
</Callout>

<EndpointIndex
  names={[
  	'fetchPaymentProviderConfigurations',
  	'fetchPaymentProviderConfiguration',
  	'addPaymentProviderConfiguration',
  	'updatePaymentProviderConfiguration',
  	'inactivatePaymentProviderConfiguration',
  	'fetchPaymentExecutionConfigurationForFinancialInstrument',
  	'addPaymentExecutionConfigurationForFinancialInstrument',
  	'updatePaymentExecutionConfigurationForFinancialInstrument',
  ]}
/>

Providers [#providers]

Fetch Payment Provider Configurations [#fetch-payment-provider-configurations]

<ApiEndpoint name="fetchPaymentProviderConfigurations" />

<ApiSchema name="ListPageResponsePaymentProvider" />

Fetch Payment Provider Configuration [#fetch-payment-provider-configuration]

<ApiEndpoint name="fetchPaymentProviderConfiguration" />

Add Payment Provider Configuration [#add-payment-provider-configuration]

<ApiEndpoint name="addPaymentProviderConfiguration" />

Update Payment Provider Configuration [#update-payment-provider-configuration]

<ApiEndpoint name="updatePaymentProviderConfiguration" />

<ApiSchema name="BraintreeConfigurationRequest" />

<ApiSchema name="StripeConfigurationRequest" />

Inactivate Payment Provider Configuration [#inactivate-payment-provider-configuration]

<ApiEndpoint name="inactivatePaymentProviderConfiguration" />

<ApiSchema name="PaymentProvider" />

Financial Instruments [#financial-instruments]

Fetch Payment Execution Configuration For Financial Instrument [#fetch-payment-execution-configuration-for-financial-instrument]

<ApiEndpoint name="fetchPaymentExecutionConfigurationForFinancialInstrument" />

Add Payment Execution Configuration For Financial Instrument [#add-payment-execution-configuration-for-financial-instrument]

<ApiEndpoint name="addPaymentExecutionConfigurationForFinancialInstrument" />

Update Payment Execution Configuration For Financial Instrument [#update-payment-execution-configuration-for-financial-instrument]

<ApiEndpoint name="updatePaymentExecutionConfigurationForFinancialInstrument" />

<ApiSchema name="FinancialInstrumentConfigurationRequest" />

<ApiSchema name="FinancialInstrumentConfigurationResponse" />

See Also [#see-also]

* [Payments API](./payments)
* [Payment Execution Service](/features/billing/payment-execution-service)
* [Autopay](/features/billing/autopay)


## API Reference

GET /payment-execution/{tenantLocator}/paymentProviders/list — fetchPaymentProviderConfigurations
Permissions: list
Parameters:
  tenantLocator (uuid, path, required)
  paymentServiceProvider (Enum braintree | braintreeSandbox | stripe | stripeTest, query)
  offset (integer, query)
  count (integer, query)
Responses:
  200 — OK

GET /payment-execution/{tenantLocator}/paymentProviders/{locator} — fetchPaymentProviderConfiguration
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /payment-execution/{tenantLocator}/paymentProviders — addPaymentProviderConfiguration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (oneOf<BraintreeConfigurationRequest,StripeConfigurationRequest>):
Responses:
  200 — OK

PATCH /payment-execution/{tenantLocator}/paymentProviders/{locator} — updatePaymentProviderConfiguration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (oneOf<BraintreeConfigurationRequest,StripeConfigurationRequest>):
Responses:
  200 — OK

PATCH /payment-execution/{tenantLocator}/paymentProviders/{locator}/inactivate — inactivatePaymentProviderConfiguration
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /payment-execution/{tenantLocator}/financialInstruments/{financialInstrumentLocator} — fetchPaymentExecutionConfigurationForFinancialInstrument
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  financialInstrumentLocator (ulid, path, required)
Responses:
  200 — OK

POST /payment-execution/{tenantLocator}/financialInstruments/{financialInstrumentLocator} — addPaymentExecutionConfigurationForFinancialInstrument
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  financialInstrumentLocator (ulid, path, required)
Request body (FinancialInstrumentConfigurationRequest):
Responses:
  200 — OK

PATCH /payment-execution/{tenantLocator}/financialInstruments/{financialInstrumentLocator} — updatePaymentExecutionConfigurationForFinancialInstrument
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  financialInstrumentLocator (ulid, path, required)
Request body (FinancialInstrumentConfigurationRequest):
Responses:
  200 — OK

ListPageResponsePaymentProvider
Properties:
  listCompleted (boolean, required)
  items (PaymentProvider[], required)

BraintreeConfigurationRequest
Properties:
  paymentServiceProvider (Enum braintree | braintreeSandbox | stripe | stripeTest, required)
  paymentProviderState (Enum active | inactive, required)
  merchantId (string, required)
  publicKey (string, required)
  privateKey (string, required)

StripeConfigurationRequest
Properties:
  paymentServiceProvider (Enum braintree | braintreeSandbox | stripe | stripeTest, required)
  paymentProviderState (Enum active | inactive, required)
  secretKey (string, required)

PaymentProvider
Properties:
  locator (ulid, required)
  paymentServiceProvider (Enum braintree | braintreeSandbox | stripe | stripeTest, required)
  paymentProviderState (Enum active | inactive, required)

FinancialInstrumentConfigurationRequest
Properties:
  paymentProviderLocator (ulid, required)
  offlinePaymentToken (string, required)
  externalAccountNumber (string)

FinancialInstrumentConfigurationResponse
Properties:
  paymentInstrumentLocator (ulid, required)
  paymentProviderLocator (ulid, required)
  externalAccountNumber (string)

# Payments API



<EndpointIndex
  names={[
  	'fetchPayment',
  	'fetchMultiplePayments',
  	'fetchSubpayments',
  	'fetchPaymentsWithNumber',
  	'createPayment',
  	'updatePayment',
  	'updatePaymentOverwriteData',
  	'validatePayment',
  	'postPayment',
  	'reversePayment',
  	'resetPayment',
  	'discardPayment',
  	'setPaymentNumber',
  	'generatePaymentNumber',
  	'executePayment',
  	'cancelPayment',
  	'failPayment',
  	'listShortfallCredits',
  	'previewPaymentValidate',
  	'previewPaymentPost',
  ]}
  titles={{
  	fetchPayment: 'Fetch a Payment',
  	fetchMultiplePayments: 'Fetch Multiple Payments',
  	fetchSubpayments: 'Fetch Subpayments',
  	createPayment: 'Create a Payment',
  	updatePayment: 'Update a Payment',
  	updatePaymentOverwriteData: 'Update a Payment (overwrite extension data)',
  	validatePayment: 'Validate a Payment',
  	postPayment: 'Post a Payment',
  	reversePayment: 'Reverse a Posted Payment',
  	resetPayment: 'Reset a Validated Payment Back to Draft State',
  	discardPayment: 'Discard a Payment',
  	listShortfallCredits: 'Fetch shortfall credits',
  	previewPaymentValidate: 'Preview Payment Validation',
  }}
/>

Fetch [#fetch]

Fetch a Payment [#fetch-a-payment]

<ApiEndpoint name="fetchPayment" title="Fetch a Payment" />

Fetch Multiple Payments [#fetch-multiple-payments]

<ApiEndpoint name="fetchMultiplePayments" title="Fetch Multiple Payments" />

Fetch Subpayments [#fetch-subpayments]

<ApiEndpoint name="fetchSubpayments" title="Fetch Subpayments" />

Fetch Payments With Number [#fetch-payments-with-number]

<ApiEndpoint name="fetchPaymentsWithNumber" />

<ApiSchema name="ListPageResponsePaymentResponse" />

<ApiSchema name="PaymentResponse" />

<ApiSchema name="SubpaymentResponse" />

<ApiSchema name="CreditItem" />

<ApiSchema name="PaymentRequestExecutionLogItem" />

Create and Update [#create-and-update]

Create a Payment [#create-a-payment]

<ApiEndpoint name="createPayment" title="Create a Payment" />

<ApiSchema name="PaymentCreateRequest" />

Update a Payment [#update-a-payment]

<ApiEndpoint name="updatePayment" title="Update a Payment" />

<ApiSchema name="PaymentUpdateRequest" />

Update a Payment (overwrite extension data) [#update-a-payment-overwrite-extension-data]

<ApiEndpoint name="updatePaymentOverwriteData" title="Update a Payment (overwrite extension data)" />

Validate a Payment [#validate-a-payment]

<ApiEndpoint name="validatePayment" title="Validate a Payment" />

Post a Payment [#post-a-payment]

<ApiEndpoint name="postPayment" title="Post a Payment" />

Reverse a Posted Payment [#reverse-a-posted-payment]

<ApiEndpoint name="reversePayment" title="Reverse a Posted Payment" />

Reset a Validated Payment Back to Draft State [#reset-a-validated-payment-back-to-draft-state]

<ApiEndpoint name="resetPayment" title="Reset a Validated Payment Back to Draft State" />

Discard a Payment [#discard-a-payment]

<ApiEndpoint name="discardPayment" title="Discard a Payment" />

Set Payment Number [#set-payment-number]

<ApiEndpoint name="setPaymentNumber" />

Generate Payment Number [#generate-payment-number]

<ApiEndpoint name="generatePaymentNumber" />

Payment Requests [#payment-requests]

Execute Payment [#execute-payment]

<ApiEndpoint name="executePayment" />

Cancel Payment [#cancel-payment]

<ApiEndpoint name="cancelPayment" />

Fail Payment [#fail-payment]

<ApiEndpoint name="failPayment" />

Shortfall Credits [#shortfall-credits]

Fetch shortfall credits [#fetch-shortfall-credits]

<ApiEndpoint name="listShortfallCredits" title="Fetch shortfall credits" />

<ApiSchema name="ListPageResponseShortfallCreditResponse" />

<ApiSchema name="ShortfallCreditResponse" />

Payments by invoice [#payments-by-invoice]

Fetch Payments For An Invoice [#fetch-payments-for-an-invoice]

<ApiEndpoint name="fetchPaymentsForAnInvoice" />

<ApiSchema name="PaymentListResponse" />

Fetch Invoices Targeted By APayment [#fetch-invoices-targeted-by-apayment]

<ApiEndpoint name="fetchInvoicesTargetedByAPayment" />

Payment Previews [#payment-previews]

Preview Payment Validation [#preview-payment-validation]

<ApiEndpoint name="previewPaymentValidate" title="Preview Payment Validation" />

Preview Payment Post [#preview-payment-post]

<ApiEndpoint name="previewPaymentPost" />

<ApiSchema name="PreviewPaymentResponse" />

<ApiSchema name="CreditWithBalance" />

<ApiSchema name="ShortfallCreditPreviewResponse" />

<ApiSchema name="ListPageResponseInvoicePaymentPreview" />

<ApiSchema name="InvoicePaymentPreview" />

See Also [#see-also]

* [Payments](/features/billing/payments)


## API Reference

GET /billing/{tenantLocator}/payments/{locator} — fetchPayment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

GET /billing/{tenantLocator}/payments/list — fetchMultiplePayments
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  accountLocator (ulid, query)
  targetContainerLocator (ulid, query)
  extended (boolean, query)
Responses:
  200 ListPageResponsePaymentResponse — OK

GET /billing/{tenantLocator}/payments/{locator}/subpayments/list — fetchSubpayments
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponsePaymentResponse — OK

GET /billing/{tenantLocator}/payments/numbers/{paymentNumber} — fetchPaymentsWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  paymentNumber (string, path, required)
Responses:
  200 PaymentResponse[] — OK

POST /billing/{tenantLocator}/payments — createPayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (PaymentCreateRequest):
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator} — updatePayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (PaymentUpdateRequest):
Responses:
  200 PaymentResponse — OK

PUT /billing/{tenantLocator}/payments/{locator} — updatePaymentOverwriteData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (PaymentCreateRequest):
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/validate — validatePayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/post — postPayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/reverse — reversePayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (CreditDistributionReverseRequest):
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/reset — resetPayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/discard — discardPayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

POST /billing/{tenantLocator}/payments/{locator}/number/set — setPaymentNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  paymentNumber (string, query, required)
Responses:
  200 PaymentResponse — OK

POST /billing/{tenantLocator}/payments/{locator}/number/generate — generatePaymentNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/request — executePayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/cancel — cancelPayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

PATCH /billing/{tenantLocator}/payments/{locator}/fail — failPayment
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PaymentResponse — OK

GET /billing/{tenantLocator}/payments/{locator}/shortfallCredits/list — listShortfallCredits
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseShortfallCreditResponse — OK

GET /billing/{tenantLocator}/invoices/{locator}/payments/list — fetchPaymentsForAnInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 PaymentListResponse — OK

GET /billing/{tenantLocator}/payments/{locator}/invoices/list — fetchInvoicesTargetedByAPayment
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  includeReversed (boolean, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceListResponse — OK

GET /billing/{tenantLocator}/payments/{locator}/previewValidate — previewPaymentValidate
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PreviewPaymentResponse — OK

GET /billing/{tenantLocator}/payments/{locator}/previewPost — previewPaymentPost
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PreviewPaymentResponse — OK

ListPageResponsePaymentResponse
Properties:
  listCompleted (boolean, required)
  items (PaymentResponse[], required)

PaymentResponse
Properties:
  locator (ulid, required)
  paymentState (Enum draft | validated | requested | executing | posting | posted | failed | cancelled | reversing | reversed | discarded, required)
  type (string, required)
  currency (string, required)
  amount (number, required)
  remainingAmount (number)
  data (map<string, object>)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid)
  targets (CreditItem[], required)
  externalCashTransactionLocator (ulid)
  validationResult (ValidationResult)
  postedAt (datetime)
  reversalReason (string)
  reversedAt (datetime)
  reversedBy (uuid)
  shortfallCreditLocators (ulid[], required)
  subpayments (SubpaymentResponse[], required)
  paymentMode (Enum normal | aggregate)
  aggregatePaymentLocator (ulid)
  paymentNumber (string)
  anonymizedAt (datetime)
  executionLog (PaymentRequestExecutionLogItem[], required)
  nextRequestTime (datetime)
  retryPlanName (string)

SubpaymentResponse
Properties:
  subpaymentLocator (ulid, required)
  amount (number, required)

CreditItem
Properties:
  containerLocator (ulid, required)
  containerType (Enum invoice | account | subpayment | invoiceItem, required)
  amount (number)

PaymentRequestExecutionLogItem
Properties:
  paymentRequestLocator (ulid, required)
  paymentRequestState (Enum pending | completed | failed | error, required)
  requestTime (datetime)
  transactionId (string)
  note (string)
  data (map<string, object>, required)

PaymentCreateRequest
Properties:
  accountLocator (ulid)
  type (string, required)
  amount (number, required)
  currency (string)
  data (map<string, object>, required)
  targets (CreditItem[], required)
  useDefaultFinancialInstrument (boolean)
  financialInstrumentLocator (ulid)
  transactionMethod (Enum ach | cash | eft | standard | wire)
  transactionNumber (string)
  paymentMode (Enum normal | aggregate)
  retryPlanName (string)

PaymentUpdateRequest
Properties:
  accountLocator (ulid)
  type (string)
  amount (number)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  addTargets (CreditItem[], required)
  removeTargets (ulid[], required)
  useDefaultFinancialInstrument (boolean)
  financialInstrumentLocator (ulid)
  transactionMethod (Enum ach | cash | eft | standard | wire)
  transactionNumber (string)
  currency (string)
  paymentMode (Enum normal | aggregate)
  retryPlanName (string)
  nextRequestTime (datetime)

ListPageResponseShortfallCreditResponse
Properties:
  listCompleted (boolean, required)
  items (ShortfallCreditResponse[], required)

ShortfallCreditResponse
Properties:
  locator (ulid, required)
  creditType (Enum creditDistribution | disbursement | payment | subpayment | shortfallWriteOff | writeOff, required)
  shortfallCreditState (Enum draft | distributed | reversed, required)
  currency (string, required)
  amount (number, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid, required)
  targets (CreditItem[], required)
  parentCreditLocator (ulid, required)
  reversalReason (string)

PaymentListResponse
Properties:
  listCompleted (boolean, required)
  items (PaymentResponse[], required)

PreviewPaymentResponse
Properties:
  locator (ulid, required)
  paymentState (Enum draft | validated | requested | executing | posting | posted | failed | cancelled | reversing | reversed | discarded, required)
  type (string, required)
  currency (string, required)
  amount (number, required)
  data (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid)
  remainingAmount (number)
  externalCashTransactionLocator (ulid)
  validationResult (ValidationResult)
  postedAt (datetime)
  paymentMode (Enum normal | aggregate)
  aggregatePaymentLocator (ulid)
  targets (CreditItem[], required)
  credits (CreditWithBalance[], required)
  shortfallCredits (ShortfallCreditPreviewResponse[], required)
  subpayments (PreviewPaymentResponse[])
  invoices (ListPageResponseInvoicePaymentPreview)

CreditWithBalance
Properties:
  type (Enum accountCreditBalance | invoiceCreditBalance | cash | creditCash | charge | credit | installmentItem | invoiceItem | account | policy | accountExpenseBalance, required)
  locator (ulid, required)
  amount (number, required)

ShortfallCreditPreviewResponse
Properties:
  locator (ulid, required)
  creditType (Enum creditDistribution | disbursement | payment | subpayment | shortfallWriteOff | writeOff, required)
  shortfallCreditState (Enum draft | distributed | reversed, required)
  currency (string, required)
  amount (number, required)
  accountLocator (ulid, required)
  targets (CreditItem[], required)

ListPageResponseInvoicePaymentPreview
Properties:
  listCompleted (boolean, required)
  items (InvoicePaymentPreview[], required)

InvoicePaymentPreview
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  invoiceState (Enum building | open | settled | discarded, required)
  amount (number)
  remainingAmount (number)

# Write-Offs API



<EndpointIndex
  names={[
  	'fetchWriteOff',
  	'fetchMultipleWriteOffs',
  	'writeOffInvoice',
  	'writeOff',
  	'reverseWriteOff',
  ]}
  titles={{
  	fetchWriteOff: 'Fetch a Write-Off',
  	fetchMultipleWriteOffs: 'Fetch Multiple Write-Offs',
  	writeOffInvoice: 'Write-Off an Invoice',
  	writeOff: 'Create Write-Off',
  	reverseWriteOff: 'Reverse a Write-Off',
  }}
/>

Fetch a Write-Off [#fetch-a-write-off]

<ApiEndpoint name="fetchWriteOff" title="Fetch a Write-Off" />

Fetch Multiple Write-Offs [#fetch-multiple-write-offs]

<ApiEndpoint name="fetchMultipleWriteOffs" title="Fetch Multiple Write-Offs" />

<ApiSchema name="WriteOffListResponse" />

<ApiSchema name="WriteOffResponse" />

Write-Off an Invoice [#write-off-an-invoice]

<ApiEndpoint name="writeOffInvoice" title="Write-Off an Invoice" />

Create Write-Off [#create-write-off]

<ApiEndpoint name="writeOff" title="Create Write-Off" />

<ApiSchema name="WriteOffRequest" />

<ApiSchema name="WriteOffTarget" />

Reverse a Write-Off [#reverse-a-write-off]

<ApiEndpoint name="reverseWriteOff" title="Reverse a Write-Off" />

See Also [#see-also]

* [Write-Offs Feature Guide](/features/billing/write-offs)


## API Reference

GET /billing/{tenantLocator}/writeOffs/{locator} — fetchWriteOff
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

GET /billing/{tenantLocator}/writeOffs/list — fetchMultipleWriteOffs
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  accountLocator (ulid, query)
  extended (boolean, query)
Responses:
  200 WriteOffListResponse — OK

PATCH /billing/{tenantLocator}/invoices/{locator}/writeOff — writeOffInvoice
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

POST /billing/{tenantLocator}/writeOffs — writeOff
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (WriteOffRequest):
Responses:
  200 WriteOffResponse — OK

PATCH /billing/{tenantLocator}/writeOffs/{locator}/reverse — reverseWriteOff
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

WriteOffListResponse
Properties:
  listCompleted (boolean, required)
  items (WriteOffResponse[], required)

WriteOffResponse
Properties:
  locator (ulid, required)
  creditType (Enum writeOff | shortfallWriteOff, required)
  writeOffState (Enum draft | distributed | reversed, required)
  currency (string, required)
  amount (number, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  accountLocator (ulid, required)
  targets (CreditItem[], required)
  reversalReason (string)
  reversedAt (datetime)

WriteOffRequest
Properties:
  accountLocator (ulid, required)
  targets (WriteOffTarget[], required)

WriteOffTarget
Properties:
  containerLocator (ulid, required)
  containerType (Enum invoice | account | subpayment | invoiceItem, required)
  amount (number)

# Anonymization API



<EndpointIndex
  names={[
  	'anonymizeData',
  	'previewAnonymization',
  	'getAnonymizationReferences',
  ]}
/>

Anonymize Data [#anonymize-data]

<ApiEndpoint name="anonymizeData" />

Preview Anonymization [#preview-anonymization]

<ApiEndpoint name="previewAnonymization" />

Get Anonymization References [#get-anonymization-references]

<ApiEndpoint name="getAnonymizationReferences" />

<ApiSchema name="AnonymizationRequest" />

<ApiSchema name="AnonymizationJobData" />

<ApiSchema name="AnonymizationPreviewResponse" />

<ApiSchema name="AnonymizationReferencePreviewResponse" />

<ApiSchema name="TargetReferences" />

<ApiSchema name="FetchAnonymizationReferencesRequest" />

<ApiSchema name="AnonymizationReferenceResponse" />

<ApiSchema name="AnonymizationReferencesBatch" />

See Also [#see-also]

* [Data Anonymization](/features/security/data-anonymization)
* [Jobs API](/api/configuration-and-development/jobs)


## API Reference

POST /compliance/{tenantLocator}/anonymize — anonymizeData
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (AnonymizationRequest):
Responses:
  200 AnonymizationJobData[] — OK

GET /compliance/{tenantLocator}/preview — previewAnonymization
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  request (AnonymizationRequest, query, required)
Responses:
  200 AnonymizationPreviewResponse[] — OK

GET /compliance/{tenantLocator}/references — getAnonymizationReferences
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  request (FetchAnonymizationReferencesRequest, query, required)
Responses:
  200 AnonymizationReferenceResponse[] — OK

AnonymizationRequest
Properties:
  references (map<string, ulid[]>, required)
  includeAcceptedQuotes (boolean)
  policyStatuses (Enum[])

AnonymizationJobData
Properties:
  referenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  jobLocator (ulid, required)
  jobStatus (Enum initialized | running | suspended | completed, required)
  assignedReferenceLocators (ulid[], required)
  fromCurrentRequest (boolean, required)

AnonymizationPreviewResponse
Properties:
  referenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  references (AnonymizationReferencePreviewResponse[], required)

AnonymizationReferencePreviewResponse
Properties:
  referenceLocator (ulid, required)
  state (Enum allowed | restricted | anonymized, required)
  targets (TargetReferences[])

TargetReferences
Properties:
  referenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  willAnonymize (boolean, required)
  anonymizableReferenceLocators (ulid[])
  restrictedReferenceLocators (ulid[])

FetchAnonymizationReferencesRequest
Properties:
  references (map<string, ulid[]>, required)

AnonymizationReferenceResponse
Properties:
  referenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  referenceLocator (ulid, required)
  updatedAt (datetime, required)
  anonymizationState (Enum identifiable | pending | anonymized, required)
  parentReferenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  parentReferenceLocator (ulid)
  anonymizationJobLocator (ulid)
  scheduledAt (datetime)
  anonymizedAt (datetime)
  preAnonymizationChildren (AnonymizationReferencesBatch[])
  postAnonymizationChildren (AnonymizationReferencesBatch[])

AnonymizationReferencesBatch
Properties:
  referenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  referenceLocators (ulid[], required)
  parentJobLocator (ulid)

# Automation Plugin API



<EndpointIndex names={['executeAutomationPlugin', 'fetchFromAutomationPlugin']} />

Execute Automation Plugin [#execute-automation-plugin]

<ApiEndpoint name="executeAutomationPlugin" />

Fetch From Automation Plugin [#fetch-from-automation-plugin]

<ApiEndpoint name="fetchFromAutomationPlugin" />


## API Reference

POST /plugin/{tenantLocator}/automation/{pluginName}/{action} — executeAutomationPlugin
Permissions: write, execute
Parameters:
  tenantLocator (uuid, path, required)
  Authorization (string, header, required)
  pluginName (string, path, required)
  action (string, path, required)
Request body (map<string, object>):
Responses:
  200 map<string, object> — OK

GET /plugin/{tenantLocator}/automation/{pluginName}/{action} — fetchFromAutomationPlugin
Permissions: write, execute
Parameters:
  tenantLocator (uuid, path, required)
  Authorization (string, header, required)
  pluginName (string, path, required)
  action (string, path, required)
Request body (map<string, object>):
Responses:
  200 map<string, object> — OK

# Data Access Controls API



<Callout type="warn">
  The API endpoints below have been deprecated and will be removed in a future release.
</Callout>

<EndpointIndex
  names={[
  	'addDataSecurityMask',
  	'fetchUserMask',
  	'fetchUserMasks',
  	'fetchUserMasksForTenant',
  	'deleteUserMasks',
  ]}
/>

Add Data Security Mask [#add-data-security-mask]

<ApiEndpoint name="addDataSecurityMask" />

Fetch User Mask [#fetch-user-mask]

<ApiEndpoint name="fetchUserMask" />

Fetch User Masks [#fetch-user-masks]

<ApiEndpoint name="fetchUserMasks" />

Fetch User Masks For Tenant [#fetch-user-masks-for-tenant]

<ApiEndpoint name="fetchUserMasksForTenant" />

Delete User Masks [#delete-user-masks]

<ApiEndpoint name="deleteUserMasks" />

<ApiSchema name="UserDataSecurityMaskRequest" />

<ApiSchema name="UserDataAccessControlMaskResponse" />

See Also [#see-also]

* [Data Access Controls](/configuration/general-topics/data-access-controls)


## API Reference

PATCH /auth/users/{locator}/accessmask — addDataSecurityMask
Permissions: write
Parameters:
  locator (uuid, path, required)
Request body (UserDataSecurityMaskRequest):
Responses:
  200 UserDataAccessControlMaskResponse — OK

GET /auth/users/{locator}/accessmask/{tenantLocator}/{type} — fetchUserMask
Permissions: read
Parameters:
  locator (uuid, path, required)
  tenantLocator (uuid, path, required)
  type (Enum account | policy, path, required)
Responses:
  200 UserDataAccessControlMaskResponse — OK

GET /auth/users/{locator}/accessmask — fetchUserMasks
Permissions: read
Parameters:
  locator (uuid, path, required)
Responses:
  200 UserDataAccessControlMaskResponse[] — OK

GET /auth/users/{locator}/accessmask/{tenantLocator} — fetchUserMasksForTenant
Permissions: read
Parameters:
  locator (uuid, path, required)
  tenantLocator (uuid, path, required)
Responses:
  200 UserDataAccessControlMaskResponse[] — OK

DELETE /auth/users/{locator}/accessmask/{tenantLocator} — deleteUserMasks
Permissions: write
Parameters:
  locator (uuid, path, required)
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

UserDataSecurityMaskRequest
Properties:
  tenantLocator (uuid, required)
  type (Enum account | policy, required)
  fields (map<string, string[]>, required)

UserDataAccessControlMaskResponse
Properties:
  userLocator (uuid, required)
  tenantLocator (uuid, required)
  maskType (Enum account | policy, required)
  fields (map<string, string[]>, required)

# Data Access API



<Callout>
  Use of this API is dependent on enabling data security. See the associated [Data Access Controls](/features/security/data-access-controls) and [Data Masking](/features/security/data-masking) guides for details.
</Callout>

<EndpointIndex
  names={[
  	'addUserDataAccess',
  	'fetchUserDataAccess',
  	'fetchUserDataAccessForTenant',
  	'deleteUserDataAccess',
  ]}
/>

Add User Data Access [#add-user-data-access]

<ApiEndpoint name="addUserDataAccess" />

Fetch User Data Access [#fetch-user-data-access]

<ApiEndpoint name="fetchUserDataAccess" />

Fetch User Data Access For Tenant [#fetch-user-data-access-for-tenant]

<ApiEndpoint name="fetchUserDataAccessForTenant" />

Delete User Data Access [#delete-user-data-access]

<ApiEndpoint name="deleteUserDataAccess" />

<ApiSchema name="UserDataAccessRequest" />

<ApiSchema name="UserDataAccessResponse" />

See Also [#see-also]

* [Data Access Controls](/features/security/data-access-controls)
* [Data Masking](/features/security/data-masking)


## API Reference

PATCH /auth/users/{locator}/dataaccess/{tenantLocator} — addUserDataAccess
Permissions: write
Parameters:
  locator (uuid, path, required)
  tenantLocator (uuid, path, required)
Request body (UserDataAccessRequest):
Responses:
  200 UserDataAccessResponse — OK

GET /auth/users/{locator}/dataaccess — fetchUserDataAccess
Permissions: read
Parameters:
  locator (uuid, path, required)
Responses:
  200 UserDataAccessResponse[] — OK

GET /auth/users/{locator}/dataaccess/{tenantLocator} — fetchUserDataAccessForTenant
Permissions: read
Parameters:
  locator (uuid, path, required)
  tenantLocator (uuid, path, required)
Responses:
  200 UserDataAccessResponse — OK

DELETE /auth/users/{locator}/dataaccess/{tenantLocator} — deleteUserDataAccess
Permissions: write
Parameters:
  locator (uuid, path, required)
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

UserDataAccessRequest
Properties:
  maskingLevel (Enum none | level1 | level2, required)
  accessControlFields (map<string, map<string, string[]>>, required)

UserDataAccessResponse
Properties:
  userLocator (uuid, required)
  tenantLocator (uuid, required)
  maskingLevel (Enum none | level1 | level2, required)
  accessControlFields (map<string, map<string, string[]>>, required)

# Configuration Deployments API



<EndpointIndex
  names={[
  	'downloadCurrentConfiguration',
  	'downloadConfigurationVersion',
  	'fetchConfigDefinition',
  	'fetchConfigDefinitionForAVersion',
  	'getDeployedConfigMetadata',
  	'deployConfigZip',
  	'getPartialDeployDifference',
  	'validateConfig',
  	'validateConfigZip',
  	'formatConfig',
  ]}
  titles={{
  	downloadCurrentConfiguration: 'Download the Current Configuration',
  	downloadConfigurationVersion: 'Download the Configuration for a Version',
  	fetchConfigDefinition: 'Fetch the Latest Configuration Definition',
  	fetchConfigDefinitionForAVersion:
  		'Fetch the Configuration Definition for a Version',
  	getDeployedConfigMetadata: 'Get Configuration Metadata',
  	deployConfigZip: 'Redeploy a Configuration',
  	getPartialDeployDifference: 'Get a Configuration Payload Difference',
  	validateConfig: 'Validate a Configuration Payload',
  	validateConfigZip: 'Validate a Configuration ZIP Payload',
  }}
/>

Tenant Creation [#tenant-creation]

Create a Tenant [#create-a-tenant]

<ApiEndpoint name="createTenant" title="Create a Tenant" />

<ApiSchema name="TenantDeploymentResult" />

Fetch [#fetch]

Download the Current Configuration [#download-the-current-configuration]

<ApiEndpoint name="downloadCurrentConfiguration" title="Download the Current Configuration" />

Download the Configuration for a Version [#download-the-configuration-for-a-version]

<ApiEndpoint name="downloadConfigurationVersion" title="Download the Configuration for a Version" />

Fetch the Latest Configuration Definition [#fetch-the-latest-configuration-definition]

<ApiEndpoint name="fetchConfigDefinition" title="Fetch the Latest Configuration Definition" />

Fetch the Configuration Definition for a Version [#fetch-the-configuration-definition-for-a-version]

<ApiEndpoint name="fetchConfigDefinitionForAVersion" title="Fetch the Configuration Definition for a Version" />

Get Configuration Metadata [#get-configuration-metadata]

<ApiEndpoint name="getDeployedConfigMetadata" title="Get Configuration Metadata" />

<ApiSchema name="DeployedConfigMetadata" />

Redeployment [#redeployment]

Redeploy a Configuration [#redeploy-a-configuration]

<ApiEndpoint name="deployConfigZip" title="Redeploy a Configuration" />

Get a Configuration Payload Difference [#get-a-configuration-payload-difference]

<ApiEndpoint name="getPartialDeployDifference" title="Get a Configuration Payload Difference" />

<ApiSchema name="MapDifference" />

Validation [#validation]

Validate a Configuration Payload [#validate-a-configuration-payload]

<ApiEndpoint name="validateConfig" title="Validate a Configuration Payload" />

Validate a Configuration ZIP Payload [#validate-a-configuration-zip-payload]

<ApiEndpoint name="validateConfigZip" title="Validate a Configuration ZIP Payload" />

Utility [#utility]

Format Config [#format-config]

<ApiEndpoint name="formatConfig" />

Configuration Entities [#configuration-entities]

<ApiSchema name="ConfigurationRef" />

<ApiSchema name="BootstrapRef" />

<ApiSchema name="ResourcesRef" />

<ApiSchema name="ResourceInstanceRef" />

<ApiSchema name="ResourceGroupRef" />

<ApiSchema name="JurisdictionRef" />

<ApiSchema name="ConfigBuilderResult" />

<ApiSchema name="BootstrapResult" />

<ApiSchema name="DeploymentMetadata" />

<ApiSchema name="TransactionTypeRef" />

<ApiSchema name="AccountRef" />

<ApiSchema name="ProductRef" />

<ApiSchema name="ElementRef" />

<ApiSchema name="CoverageTermRef" />

<ApiSchema name="CoverageTermOptionRef" />

<ApiSchema name="DisplayHintsRef" />

<ApiSchema name="FnolRef" />

<ApiSchema name="WorkManagementRef" />

<ApiSchema name="LabelRef" />

<ApiSchema name="TaskTypeRef" />

<ApiSchema name="UserAssociationRoleRef" />

<ApiSchema name="DataTypeRef" />

<ApiSchema name="AvailabilityRef" />

<ApiSchema name="PropertyRef" />

<ApiSchema name="PropertyConstraint" />

<ApiSchema name="ConditionValueRef" />

<ApiSchema name="RestrictedDataRef" />

<ApiSchema name="Values" />

<ApiSchema name="ChargeRef" />

<ApiSchema name="BillingPlanRef" />

<ApiSchema name="DelinquencyPlanRef" />

<ApiSchema name="DelinquencyEventConfiguration" />

<ApiSchema name="InstallmentPlanRef" />

<ApiSchema name="InvoicingPlanRef" />

<ApiSchema name="InstallmentGroupingDetails" />

<ApiSchema name="AutoRenewalPlanRef" />

<ApiSchema name="RetryPlanRef" />

<ApiSchema name="PaymentRef" />

<ApiSchema name="DisbursementRef" />

<ApiSchema name="ReversalTypeRef" />

<ApiSchema name="ShortfallTolerancePlanRef" />

<ApiSchema name="ExcessCreditPlanRef" />

<ApiSchema name="NegativeInvoiceHandlingRef" />

<ApiSchema name="NumberingPlanRef" />

<ApiSchema name="ExternalNumberingPlanRef" />

<ApiSchema name="RegionRef" />

<ApiSchema name="TemplateSnippetConfigRef" />

<ApiSchema name="ScheduleRef" />

<ApiSchema name="LossRef" />

<ApiSchema name="ClaimRef" />

<ApiSchema name="TableRef" />

<ApiSchema name="RangeTableRef" />

<ApiSchema name="ColumnRef" />

<ApiSchema name="ConstraintTableRef" />

<ApiSchema name="ConstraintColumnRef" />

<ApiSchema name="DocumentConfigRef" />

<ApiSchema name="AssistantRef" />

<ApiSchema name="IntentPlan" />

<ApiSchema name="SecretKeyRef" />

The `rendering` property is set to `dynamic` for documents that are generated
with a template and `prerendered` for documents that are uploaded and used as
they are, such as for pre-rendered PDF documents.

<ApiSchema name="DocumentMarginRef" />

The `bottom`, `left`, `right` and `top` properties represent the size of the
margin in millimeters.

<ApiSchema name="ConsolidatedDocumentConfigRef" />

<ApiSchema name="ConsolidatedPageNumberingRef" />

<ApiSchema name="CustomEventRef" />

<ApiSchema name="EventScheduleRef" />

<ApiSchema name="EventCadenceRef" />

<ApiSchema name="TenantCustomEventRef" />

<ApiSchema name="TenantEventScheduleRef" />

<ApiSchema name="SecretRef" />

<ApiSchema name="PrimitivePropertyRef" />

<ApiSchema name="AuxDataSettingsRef" />

<ApiSchema name="DataAccessControlRef" />

<ApiSchema name="DataAccessControlFieldRef" />

<ApiSchema name="ContactRef" />

<ApiSchema name="AutomationPluginRef" />

<ApiSchema name="AutomationPluginActionRef" />

<ApiSchema name="ProducerManagementRef" />

<ApiSchema name="UnderwritingFlagRef" />

<ApiSchema name="ProducerCodeRef" />

<ApiSchema name="ProducerRef" />

<ApiSchema name="ProducerLicenseRef" />

<ApiSchema name="ProducerAppointmentRef" />

<ApiSchema name="ClaimsManagementRef" />

<ApiSchema name="ClaimExposureRef" />


## API Reference

POST /config/createTenant — createTenant
Permissions: create-tenant
Parameters:
  name (string, query)
  description (string, query)
Responses:
  200 TenantDeploymentResult — OK

GET /config/{tenantLocator}/deployments/download — downloadCurrentConfiguration
Permissions: deploy
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

GET /config/{tenantLocator}/deployments/download/{version} — downloadConfigurationVersion
Permissions: deploy
Parameters:
  tenantLocator (uuid, path, required)
  version (ulid, path, required)
  byStaticLocator (boolean, query)
Responses:
  200 — OK

GET /config/{tenantLocator}/deployments/datamodel — fetchConfigDefinition
Permissions: deploy, datamodel
Parameters:
  tenantLocator (uuid, path, required)
  resolve (boolean, query)
Responses:
  200 ConfigurationRef — OK

GET /config/{tenantLocator}/deployments/datamodel/{version} — fetchConfigDefinitionForAVersion
Permissions: deploy, datamodel
Parameters:
  tenantLocator (uuid, path, required)
  version (ulid, path, required)
  resolve (boolean, query)
  byStaticLocator (boolean, query)
Responses:
  200 ConfigurationRef — OK

GET /config/{tenantLocator}/deployments — getDeployedConfigMetadata
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 DeployedConfigMetadata — OK

POST /config/{tenantLocator}/deployments/deploy — deployConfigZip
Permissions: deploy
Parameters:
  tenantLocator (uuid, path, required)
  overwrite (boolean, query)
Responses:
  200 — OK

GET /config/{tenantLocator}/deployments/diff — getPartialDeployDifference
Permissions: deploy
Parameters:
  tenantLocator (uuid, path, required)
  config (ConfigurationRef, query, required)
Responses:
  200 — OK

POST /config/validateConfig — validateConfig
Permissions: create-tenant, validate-config
Responses:
  200 — OK

POST /config/{tenantLocator}/deployments/validate — validateConfigZip
Permissions: deploy
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

POST /config/formatConfig — formatConfig
Converts a configuration's property casing to match requirements
Permissions: create-tenant, validate-config
Responses:
  200 — OK

TenantDeploymentResult
Properties:
  locator (uuid, required)
  name (string, required)
  deploymentResult (ConfigBuilderResult, required)
  bootstrapResult (BootstrapResult, required)

DeployedConfigMetadata
Properties:
  metadata (DeploymentMetadata, required)
  pluginVersionStatus (map<string, map<string, string>>, required) [deprecated]
  pluginStatus (map<string, string>, required)
  expectedRetirementTime (datetime)

MapDifference
Properties:
  added (map<string, object>, required)
  modified (map<string, object>, required)
  removed (map<string, object>, required)

ConfigurationRef
Properties:
  defaultTimeZone (string)
  defaultCurrency (string)
  defaultTermDuration (number)
  defaultInstallmentPlan (string)
  defaultInvoicingPlan (string)
  defaultPaymentNumberingPlanName (string)
  defaultDisbursementNumberingPlanName (string)
  defaultBillingPlan (string) [deprecated]
  defaultDurationBasis (Enum years | months | weeks | days | hours)
  defaultBillingLevel (Enum account | inherit | policy) [deprecated]
  defaultBackdatedInstallmentsBilling (Enum immediate | deferDueDate)
  defaultDelinquencyPlan (string)
  defaultAutoRenewalPlan (string)
  defaultExcessCreditPlan (string)
  defaultRetryPlan (string)
  defaultLapseType (string) [deprecated]
  defaultAnchorMode (Enum generateDay | termStartDay | dueDay) [deprecated]
  defaultGenerateLeadDays (integer) [deprecated]
  defaultDueLeadDays (integer) [deprecated]
  defaultAuxDataSettings (string)
  defaultShortfallTolerancePlan (string)
  jurisdictions (map<string, JurisdictionRef>)
  regions (map<string, RegionRef>)
  defaultRegion (string) [deprecated]
  defaultSearchable (boolean) — Default is true
  enableSerialInvoiceNumbering (boolean)
  enableEntityAnonymization (boolean)
  defaultScheduleUploadErrorsLimit (integer)
  dataTypes (map<string, DataTypeRef>)
  accounts (map<string, AccountRef>, required)
  policyLines (map<string, ElementRef>)
  exposureGroups (map<string, ElementRef>)
  exposures (map<string, ElementRef>)
  coverages (map<string, ElementRef>)
  products (map<string, ProductRef>, required)
  coverageTerms (map<string, CoverageTermRef>)
  charges (map<string, ChargeRef>, required)
  transactionTypes (map<string, TransactionTypeRef>)
  installmentPlans (map<string, InstallmentPlanRef>)
  invoicingPlans (map<string, InvoicingPlanRef>)
  billingPlans (map<string, BillingPlanRef>) [deprecated]
  payments (map<string, PaymentRef>)
  disbursements (map<string, DisbursementRef>)
  tables (map<string, TableRef>)
  rangeTables (map<string, RangeTableRef>)
  constraintTables (map<string, ConstraintTableRef>)
  secrets (map<string, SecretRef>)
  documents (map<string, DocumentConfigRef>)
  consolidatedDocuments (map<string, ConsolidatedDocumentConfigRef>)
  templateSnippets (map<string, TemplateSnippetConfigRef>)
  customFonts (string[])
  auxDataSettings (map<string, AuxDataSettingsRef>)
  moratoriums (map<string, MoratoriumRef>)
  customEvents (map<string, CustomEventRef>)
  delinquencyPlans (map<string, DelinquencyPlanRef>)
  shortfallTolerancePlans (map<string, ShortfallTolerancePlanRef>)
  autoRenewalPlans (map<string, AutoRenewalPlanRef>)
  excessCreditPlans (map<string, ExcessCreditPlanRef>)
  reversalTypes (map<string, ReversalTypeRef>)
  numberingPlans (map<string, NumberingPlanRef>)
  fnol (map<string, FnolRef>)
  claims (map<string, ClaimRef>) [deprecated]
  claimsManagement (ClaimsManagementRef)
  losses (map<string, LossRef>)
  lossCategories (string[])
  contacts (map<string, ContactRef>)
  contactRoles (string[])
  schedules (map<string, ScheduleRef>)
  workManagement (WorkManagementRef)
  dataAccessControl (DataAccessControlRef)
  assistant (AssistantRef)
  bootstrap (BootstrapRef)
  defaultInvoiceDocument (string)
  retryPlans (map<string, RetryPlanRef>)
  automations (map<string, AutomationPluginRef>)
  producerManagement (ProducerManagementRef)
  tenantCustomEvents (map<string, TenantCustomEventRef>)
  externalNumberingPlans (map<string, ExternalNumberingPlanRef>)

BootstrapRef
Properties:
  resources (ResourcesRef, required)

ResourcesRef
Properties:
  resourceInstances (map<string, ResourceInstanceRef>, required)
  resourceGroups (map<string, ResourceGroupRef>, required)

ResourceInstanceRef
Properties:
  staticName (string, required)
  jurisdictions (string[], required)

ResourceGroupRef
Properties:
  selectionStartTime (datetime, required)
  resourceNames (string[], required)

JurisdictionRef
Properties:
  displayHints (DisplayHintsRef)

ConfigBuilderResult
Properties:
  isSuccess (boolean, required)
  errors (string[], required)
  metadata (DeploymentMetadata, required)

BootstrapResult
Properties:
  status (Enum queued | failed, required)
  error (string, required)

DeploymentMetadata
Properties:
  version1 (ulid, required)
  version2 (ulid, required) [deprecated]
  staticVersionLocator (ulid)
  implementedPlugins (map<string, string>, required)
  implementedAutomationPlugins (map<string, string>, required)
  latestVersion (ulid, required)

TransactionTypeRef
Properties:
  category (Enum issuance | change | renewal | cancellation | reinstatement | reversal | aggregate, required)
  costBearing (boolean, required)
  displayHints (DisplayHintsRef)
  data (map<string, PropertyRef>)

AccountRef
Properties:
  displayName (string)
  abstract (boolean)
  extend (string)
  defaultSearchable (boolean)
  data (map<string, PropertyRef>, required)
  defaultInvoiceDocument (string)
  numberingPlan (string)
  invoiceNumberingPlan (string)
  paymentExecutionRetryPlan (string)
  contacts (map<string, string[]>)
  numberingTrigger (Enum creation | validation)
  accountKind (Enum standard | proxyPayer)

ProductRef
Properties:
  extend (string)
  abstract (boolean)
  defaultInstallmentPlan (string)
  defaultBillingPlan (string) [deprecated]
  defaultTermDuration (number)
  defaultDelinquencyPlan (string)
  defaultAutoRenewalPlan (string)
  defaultShortfallTolerancePlan (string)
  displayName (string)
  defaultDurationBasis (Enum years | months | weeks | days | hours)
  coverageTerms (string[])
  eligibleAccountTypes (string[])
  eligibleTransactionTypes (string[])
  contents (string[])
  documents (string[])
  charges (string[])
  scheduledEvents (string[])
  data (map<string, PropertyRef>)
  staticData (map<string, PropertyRef>)
  defaultSearchable (boolean)
  pluralType (string) [deprecated]
  numberingPlan (string)
  numberingString (string)
  availability (AvailabilityRef)
  withPrecommitReapplication (boolean)
  requiresJurisdiction (boolean)
  contacts (map<string, string[]>)
  numberingTrigger (Enum creation | validation)
  workplanTriggers (map<string, string[]>)
  riskAssessmentCriteria (string)
  producerQualification (Enum none | license | appointment)
  externalNumberingPlan (string)
  reservedPolicyNumberRequired (boolean)

ElementRef
Properties:
  extend (string)
  abstract (boolean)
  pluralType (string) [deprecated]
  displayName (string)
  coverageTerms (string[])
  contents (string[])
  charges (string[])
  defaultSearchable (boolean)
  data (map<string, PropertyRef>)
  availability (AvailabilityRef)
  schedule (string)

CoverageTermRef
Properties:
  type (Enum splitLimit | deductible | limit, required)
  displayName (string)
  options (map<string, CoverageTermOptionRef>)
  value (PropertyRef)
  availability (AvailabilityRef)

CoverageTermOptionRef
Properties:
  displayName (string)
  value (number, required)
  tag (string)
  displayHints (DisplayHintsRef)

DisplayHintsRef
Properties:
  displayName (string)
  displayOrder (integer)

FnolRef
Properties:
  extend (string)
  abstract (boolean)
  lossTypes (string[])
  defaultClaimType (string)
  defaultSearchable (boolean)
  data (map<string, PropertyRef>, required)
  numberingPlan (string)
  contacts (map<string, string[]>)

WorkManagementRef
Properties:
  tasks (map<string, map<string, TaskTypeRef>>)
  userAssociationRoles (map<string, UserAssociationRoleRef>)
  qualifications (map<string, string[]>)
  labels (map<string, LabelRef>)

LabelRef

TaskTypeRef
Properties:
  defaultDeadlineDays (number, required)
  blocksUnderwriting (boolean, required)
  numberingPlan (string)
  numberingString (string)

UserAssociationRoleRef
Properties:
  appliesTo (Enum[])
  exclusive (boolean)
  qualification (map<string, string>)

DataTypeRef
Properties:
  displayName (string)
  abstract (boolean)
  extend (string)
  data (map<string, PropertyRef>, required)
  defaultSearchable (boolean)

AvailabilityRef
Specifies availability. At least one of availableAfter, retireAfter, retire, removeOnRenewalAfter, or removeOnRenewal must be set.
Properties:
  availableAfter (datetime)
  availabilityTimeBasis (Enum policyStartTime | termStartTime, required) — default: TermStartTime
  retireAfter (datetime)
  retire (boolean) — default: false
  retirementTimeBasis (Enum policyStartTime | termStartTime, required) — default: TermStartTime
  removeOnRenewalAfter (datetime)
  removeOnRenewal (boolean) — default: false

PropertyRef
Properties:
  displayName (string)
  type (string)
  scope (string)
  defaultValue (string)
  min (string)
  max (string)
  minLength (integer)
  maxLength (integer)
  precision (integer)
  options (string[])
  regex (string)
  roundingMode (Enum ceiling | down | floor | halfDown | halfEven | halfUp | up)
  tag (string[])
  constraint (PropertyConstraint)
  searchable (boolean)
  availability (AvailabilityRef)
  restrictedData (RestrictedDataRef)

PropertyConstraint
Properties:
  table (string, required)
  column (string, required)
  where (map<string, ConditionValueRef>, required)

ConditionValueRef
Properties:
  key (string, required)
  values (string[], required)

RestrictedDataRef
Properties:
  anonymizable (boolean, required)
  maskingLevel (Enum none | level1 | level2, required)
  value (Values, required)

Values
Properties:
  string (string, required)
  int (integer, required)
  long (integer, required)
  guid (string, required)
  date (date, required)
  datetime (datetime, required)
  decimal (number, required)

ChargeRef
Properties:
  displayName (string) [deprecated]
  category (Enum none | premium | tax | fee | credit | invoiceFee | cededPremium | nonFinancial | surcharge, required)
  handling (Enum flat | normal | retention, required)
  invoicing (Enum scheduled | next | immediate, required)
  transactionBundlingEnabled (boolean, required)

BillingPlanRef
Properties:
  displayName (string)
  billingLevel (Enum account | inherit | policy, required)

DelinquencyPlanRef
Properties:
  displayName (string)
  gracePeriodDays (integer, required)
  delinquencyLevel (Enum policy | invoice)
  lapseTransactionType (string)
  advanceLapseTo (Enum draft | validated | priced | underwritten | accepted | issued)
  events (map<string, DelinquencyEventConfiguration>)

DelinquencyEventConfiguration
Properties:
  offsetDays (number, required)
  offsetBasis (Enum gracePeriodStart | gracePeriodEnd, required)

InstallmentPlanRef
Properties:
  displayName (string)
  cadence (Enum none | fullPay | weekly | everyOtherWeek | monthly | quarterly | semiannually | annually | thirtyDays | everyNDays, required)
  anchorMode (Enum generateDay | termStartDay | dueDay, required)
  generateLeadDays (integer, required)
  dueLeadDays (integer, required)
  installmentWeights (number[], required)
  maxInstallmentsPerTerm (integer, required)
  autopayLeadDays (number)

InvoicingPlanRef
Properties:
  displayName (string)
  invoiceFeeHandling (Enum max | min | sum | waive, required)
  invoiceFeeAmounts (map<string, number>, required)
  consolidateInvoicesOnCancellation (Enum none | future | all, required)
  installmentGrouping (InstallmentGroupingDetails, required)

InstallmentGroupingDetails
Properties:
  matching (Enum generateTime | startTime | all, required) — Default is generateTime
  window (Enum start | startAndEnd | catchUp, required) — Default is startAndEnd

AutoRenewalPlanRef
Properties:
  generateAutoRenewals (boolean, required)
  renewalTransactionType (string)
  renewalCreateLeadDays (integer)
  renewalAcceptLeadDays (integer)
  renewalIssueLeadDays (integer)
  newTermDuration (integer)

RetryPlanRef
Properties:
  attempts (integer, required)
  hoursBetweenAttempts (number[], required)

PaymentRef
Properties:
  displayName (string)
  abstract (boolean, required)
  extend (string, required)
  defaultSearchable (boolean, required)
  data (map<string, PropertyRef>)
  numberingPlan (string, required)
  numberingTrigger (Enum creation | validation, required)

DisbursementRef
Properties:
  displayName (string)
  abstract (boolean)
  extend (string)
  data (map<string, PropertyRef>, required)
  numberingPlan (string)
  numberingTrigger (Enum creation | validation)

ReversalTypeRef
Properties:
  creditType (Enum any | creditDistribution | payment, required)

ShortfallTolerancePlanRef
Properties:
  currencyTolerances (map<string, number>, required)

ExcessCreditPlanRef
Properties:
  disburseExcess (boolean, required) — Set to true to enable excess funds handling for the plan.
  disbursementType (string, required) — The type of the disbursement to be automatically created.
  excludeDebits (Enum allInvoices | invoicesAndUnbilledInstallments | none | pastDueInvoices, required) — Which pending debits should be considered for determining how much of the credit to retain
  disbursementThresholds (map<string, number>, required)
  advanceDisbursementTo (Enum draft | validated | approved | executed | reversed | rejected | discarded, required)
  autoApplyExcessToInvoicesEnabled (boolean, required)
  negativeInvoiceHandling (NegativeInvoiceHandlingRef, required)

NegativeInvoiceHandlingRef
Properties:
  automaticallySettleNegativeInvoices (Enum toOpenInvoices | toCreditBalance | never, required)
  prioritizeOverlappingCoveragePeriods (boolean, required)
  targetInvoices (Enum overlappingCoveragePeriodsOnly | overlappingCoverageAndEarlier | allOpenInvoices, required)
  targetInvoicePriority (Enum byAmount | smallestFirst | earliestFirst, required)
  processingMode (Enum accountLevel | policyLevel, required)
  yieldExcessToCreditBalance (boolean, required)

NumberingPlanRef
Properties:
  displayName (string)
  initialCoreNumber (string, required)
  format (string, required)
  copyFromQuote (boolean, required)
  termNumberFormat (string, required)
  quoteNumberFormat (string, required)
  initialQuoteCoreNumber (string, required)
  productScope (string)

ExternalNumberingPlanRef
Properties:
  displayName (string)
  triggerQuoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)

RegionRef
Properties:
  displayName (string)
  numberingString (string)

TemplateSnippetConfigRef
Properties:
  displayName (string)
  selectionTimeBasis (Enum policyStartTime | termStartTime | transactionEffectiveTime | currentTime, required)

ScheduleRef
Properties:
  extend (string)
  abstract (boolean)
  displayName (string)
  data (map<string, PropertyRef>, required)
  resetOnRenewal (boolean, required)

LossRef
Properties:
  extend (string)
  abstract (boolean)
  data (map<string, PropertyRef>, required)
  category (string, required)
  defaultClaimExposureType (string)
  coverageTypes (string[])

ClaimRef
Properties:
  extend (string)
  abstract (boolean)
  claimCategory (string, required)
  eligibleExposureTypes (string[])
  eligibleProducts (string[])
  data (map<string, PropertyRef>, required)
  numberingPlan (string)
  contacts (map<string, string[]>)

TableRef
Properties:
  columns (map<string, ColumnRef>, required)
  selectionTimeBasis (Enum policyStartTime | termStartTime | transactionEffectiveTime | currentTime, required)

RangeTableRef
Properties:
  columns (map<string, ColumnRef>, required)
  selectionTimeBasis (Enum policyStartTime | termStartTime | transactionEffectiveTime | currentTime, required)
  rangeStart (string, required)
  rangeEnd (string)

ColumnRef
Properties:
  dataType (string, required)
  isKey (boolean, required)

ConstraintTableRef
Properties:
  columns (map<string, ConstraintColumnRef>, required)
  selectionTimeBasis (Enum policyStartTime | termStartTime | transactionEffectiveTime | currentTime, required)

ConstraintColumnRef
Properties:
  dataType (string, required)
  makeDistinct (boolean, required)

DocumentConfigRef
Properties:
  displayName (string)
  scope (Enum transaction | policy | term | segment | invoice, required)
  format (Enum text | html | pdf | jpg | jpeg | doc | docx | xls | xlsx | csv | txt | zip, required)
  rendering (Enum dynamic | prerendered, required)
  selectionTimeBasis (Enum policyStartTime | termStartTime | transactionEffectiveTime | currentTime, required)
  trigger (Enum validated | priced | accepted | underwritten | issued | generated | declined | rejected | refused, required)
  portrait (boolean)
  pageSize (Enum letter | legal | A3 | A4 | A5 | B4 | B5)
  margin (DocumentMarginRef)
  templateSnippets (string[], required)
  customFonts (string[], required)

AssistantRef
Properties:
  patTokenSecretRef (SecretKeyRef)
  inquiryIntents (map<string, IntentPlan>)

IntentPlan
Properties:
  intentType (string, required)
  taskType (string, required)
  workgroup (string)

SecretKeyRef
Properties:
  name (string, required)
  key (string, required)

DocumentMarginRef
Properties:
  top (number)
  bottom (number)
  left (number)
  right (number)

ConsolidatedDocumentConfigRef
Properties:
  displayName (string)
  consolidatedDocuments (string[], required)
  leadingDocumentTemplate (string)
  pageNumbering (ConsolidatedPageNumberingRef)

ConsolidatedPageNumberingRef
Properties:
  enableNumbering (boolean, required)
  leadingDocumentPages (boolean, required)
  xPosition (integer, required)
  yPosition (integer, required)

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)

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

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

SecretRef
Properties:
  items (map<string, PrimitivePropertyRef>, required)

PrimitivePropertyRef
Properties:
  dataType (string, required)

AuxDataSettingsRef
Properties:
  displayName (string)
  expirationPeriod (integer, required)

DataAccessControlRef
Properties:
  enabled (boolean, required)
  dataMasking (boolean, required)
  account (DataAccessControlFieldRef, required)
  policy (DataAccessControlFieldRef, required)

DataAccessControlFieldRef
Properties:
  fields (string[], required)

ContactRef
Properties:
  abstract (boolean)
  extend (string)
  defaultSearchable (boolean)
  data (map<string, PropertyRef>, required)

AutomationPluginRef
Properties:
  enableWebhooks (boolean)
  actions (map<string, AutomationPluginActionRef>)
  secret (string)
  webhookHandlerTimeout (integer)

AutomationPluginActionRef
Properties:
  timeout (integer)
  request (map<string, PropertyRef>)
  response (map<string, PropertyRef>)

ProducerManagementRef
Properties:
  producers (map<string, ProducerRef>, required)
  producerCodes (map<string, ProducerCodeRef>, required)
  producerLicenses (map<string, ProducerLicenseRef>, required)
  producerAppointments (map<string, ProducerAppointmentRef>, required)
  underwritingFlag (UnderwritingFlagRef, required)

UnderwritingFlagRef
Properties:
  level (Enum info | block | decline | reject | approve)
  tag (string)
  note (string)

ProducerCodeRef
Properties:
  displayName (string)
  abstract (boolean, required)
  extend (string, required)
  defaultSearchable (boolean, required)
  numberingPlan (string, required)
  numberingString (string, required)
  data (map<string, PropertyRef>)

ProducerRef
Properties:
  displayName (string)
  abstract (boolean, required)
  extend (string, required)
  defaultSearchable (boolean, required)
  data (map<string, PropertyRef>)

ProducerLicenseRef
Properties:
  abstract (boolean, required)
  extend (string, required)
  defaultSearchable (boolean, required)
  data (map<string, PropertyRef>)

ProducerAppointmentRef
Properties:
  abstract (boolean, required)
  extend (string, required)
  defaultSearchable (boolean, required)
  data (map<string, PropertyRef>)

ClaimsManagementRef
Properties:
  claims (map<string, ClaimRef>) [deprecated]
  claimExposures (map<string, ClaimExposureRef>)

ClaimExposureRef
Properties:
  extend (string)
  abstract (boolean)
  data (map<string, PropertyRef>, required)
  eligibleLossTypes (string[])
  numberingPlan (string)
  contacts (map<string, string[]>)

# Developer API



<EndpointIndex
  names={['buildBundle', 'downloadBundle']}
  titles={{
  	buildBundle: 'Build a Development Bundle',
  	downloadBundle: 'Download a Development Bundle',
  }}
/>

Build a Development Bundle [#build-a-development-bundle]

<ApiEndpoint name="buildBundle" title="Build a Development Bundle" />

Download a Development Bundle [#download-a-development-bundle]

<ApiEndpoint name="downloadBundle" title="Download a Development Bundle" />


## API Reference

POST /config/{tenantLocator}/developer/build — buildBundle
Permissions: build
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

GET /config/{tenantLocator}/developer/download — downloadBundle
Permissions: download
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

# Identity Providers API



<EndpointIndex
  names={[
  	'fetchIdentityProviderByName',
  	'fetchIdentityProviders',
  	'addSAMLIdentityProvider',
  	'addOIDCIdentityProvider',
  	'createIdentityProvider',
  	'deleteIdentityServerInstance',
  ]}
  titles={{
  	fetchIdentityProviderByName: 'Fetch an Identity Provider',
  	fetchIdentityProviders: 'Fetch All Identity Providers',
  	addSAMLIdentityProvider: 'Add a SAML Identity Provider',
  	addOIDCIdentityProvider: 'Add an OIDC Identity Provider',
  	createIdentityProvider: 'Create an Identity Provider',
  	deleteIdentityServerInstance: 'Delete an Identity Provider',
  }}
/>

Fetch an Identity Provider [#fetch-an-identity-provider]

<ApiEndpoint name="fetchIdentityProviderByName" title="Fetch an Identity Provider" />

Fetch All Identity Providers [#fetch-all-identity-providers]

<ApiEndpoint name="fetchIdentityProviders" title="Fetch All Identity Providers" />

Add a SAML Identity Provider [#add-a-saml-identity-provider]

<ApiEndpoint name="addSAMLIdentityProvider" title="Add a SAML Identity Provider" />

<ApiSchema name="SAMLIdentityProviderCreateRequest" />

Add an OIDC Identity Provider [#add-an-oidc-identity-provider]

<ApiEndpoint name="addOIDCIdentityProvider" title="Add an OIDC Identity Provider" />

<ApiSchema name="OIDCIdentityProviderCreateRequest" />

Create an Identity Provider [#create-an-identity-provider]

<ApiEndpoint name="createIdentityProvider" title="Create an Identity Provider" />

<ApiSchema name="IdentityProviderResponse" />

Delete an Identity Provider [#delete-an-identity-provider]

<ApiEndpoint name="deleteIdentityServerInstance" title="Delete an Identity Provider" />


## API Reference

GET /auth/identity/instances/{name} — fetchIdentityProviderByName
Permissions: read, custom
Parameters:
  name (string, path, required)
Responses:
  200 IdentityProviderResponse — OK

GET /auth/identity/instances — fetchIdentityProviders
Permissions: read, custom
Responses:
  200 IdentityProviderResponse[] — OK

POST /auth/identity/saml — addSAMLIdentityProvider
Permissions: add, custom
Request body (SAMLIdentityProviderCreateRequest):
Responses:
  200 IdentityProviderResponse — OK

POST /auth/identity/oidc — addOIDCIdentityProvider
Permissions: add, custom
Request body (OIDCIdentityProviderCreateRequest):
Responses:
  200 IdentityProviderResponse — OK

POST /auth/identity — createIdentityProvider
Permissions: add, custom
Request body (SAMLIdentityProviderCreateRequest):
Responses:
  200 IdentityProviderResponse — OK

DELETE /auth/identity/instances/{name} — deleteIdentityServerInstance
Permissions: delete, custom
Parameters:
  name (string, path, required)
Responses:
  200 — OK

SAMLIdentityProviderCreateRequest
Properties:
  id (string, required)
  displayName (string, required)
  singleSignOnServiceUrl (string, required)

OIDCIdentityProviderCreateRequest
Properties:
  id (string, required)
  displayName (string, required)
  importConfigUrl (string, required)
  clientId (string, required)
  clientSecret (string, required)

IdentityProviderResponse
Properties:
  id (string, required)
  displayName (string, required)
  type (string, required)
  acsUrl (string, required)
  callbackUrl (string, required)
  entityId (string, required)
  singleSignOnServiceUrl (string, required)

# Jobs API



<EndpointIndex
  names={[
  	'fetchDocumentsJobForTransaction',
  	'fetchMultipleDocumentsJobsForTransaction',
  	'fetchDocumentsJobForSegment',
  	'fetchMultipleDocumentsJobsForSegment',
  	'fetchDocumentsJobForQuote',
  	'fetchMultipleDocumentsJobsForQuote',
  	'triggerTimedOutDocumentsJobForTransaction',
  	'triggerTimedOutDocumentsJobForSegment',
  	'triggerTimedOutDocumentsJobForQuote',
  	'triggerFailedDocumentJobForTransaction',
  	'triggerFailedDocumentJobForSegment',
  	'triggerFailedDocumentJobForQuote',
  	'triggerFailedDocumentJobForInvoice',
  	'fetchInstallmentsJobDataForQuotes',
  	'fetchInstallmentsJobDataForTransactions',
  	'retryFailedTransactions',
  	'fetchInvoicingJobsForAccount',
  	'fetchInvoicingJob',
  	'fetchInvoiceJobDataForAccount',
  	'fetchInvoiceLifecycleJobData',
  	'fetchDelinquencyGraceJob',
  	'fetchCreateDelinquenciesJobDataForInvoice',
  	'fetchDelinquencyEventJobs',
  	'fetchAnonymizationJobs',
  	'listDeserializeScheduleItemsJobs',
  	'fetchDeserializeScheduleItemsJob',
  	'terminateDeserializationJob',
  	'restartDeserializationJob',
  ]}
  titles={{
  	fetchInstallmentsJobDataForQuotes: 'Fetch Installments Jobs for Quotes',
  	fetchInstallmentsJobDataForTransactions:
  		'Fetch Installments Jobs for Policy Transactions',
  	fetchInvoicingJobsForAccount: 'Fetch Invoice Jobs for Accounts',
  	fetchInvoicingJob: 'Fetch Invoice Job',
  	fetchInvoiceJobDataForAccount: 'Fetch Invoice Job Data For Account',
  	fetchInvoiceLifecycleJobData: 'Fetch Invoice Lifecycle Job Data',
  }}
/>

Documents Jobs [#documents-jobs]

Fetch Documents Job For Transaction [#fetch-documents-job-for-transaction]

<ApiEndpoint name="fetchDocumentsJobForTransaction" />

Fetch Multiple Documents Jobs For Transaction [#fetch-multiple-documents-jobs-for-transaction]

<ApiEndpoint name="fetchMultipleDocumentsJobsForTransaction" />

Fetch Documents Job For Segment [#fetch-documents-job-for-segment]

<ApiEndpoint name="fetchDocumentsJobForSegment" />

Fetch Multiple Documents Jobs For Segment [#fetch-multiple-documents-jobs-for-segment]

<ApiEndpoint name="fetchMultipleDocumentsJobsForSegment" />

Fetch Documents Job For Quote [#fetch-documents-job-for-quote]

<ApiEndpoint name="fetchDocumentsJobForQuote" />

Fetch Multiple Documents Jobs For Quote [#fetch-multiple-documents-jobs-for-quote]

<ApiEndpoint name="fetchMultipleDocumentsJobsForQuote" />

<ApiSchema name="DocumentJobListResponse" />

<ApiSchema name="DocumentsJob" />

<ApiSchema name="DocumentsJobSummary" />

<ApiSchema name="DocumentJobInfo" />

<ApiSchema name="DocumentContext" />

<ApiSchema name="DocumentInfo" />

<ApiSchema name="CreateDocumentsRequest" />

<ApiSchema name="DocumentCreationJobContext" />

<ApiSchema name="CreateInvoiceDocumentRequest" />

<ApiSchema name="CreatePolicyDocumentRequest" />

<ApiSchema name="CreateConsolidatedPolicyDocumentRequest" />

<Callout>
  The `/list` endpoints above will return an empty array if the entity does not exist for the given locator. An HTTP 404 error will *not* be generated.
</Callout>

Retrigger Jobs [#retrigger-jobs]

Trigger Timed Out Documents Job For Transaction [#trigger-timed-out-documents-job-for-transaction]

<ApiEndpoint name="triggerTimedOutDocumentsJobForTransaction" />

Trigger Timed Out Documents Job For Segment [#trigger-timed-out-documents-job-for-segment]

<ApiEndpoint name="triggerTimedOutDocumentsJobForSegment" />

Trigger Timed Out Documents Job For Quote [#trigger-timed-out-documents-job-for-quote]

<ApiEndpoint name="triggerTimedOutDocumentsJobForQuote" />

Trigger Failed Document Job For Transaction [#trigger-failed-document-job-for-transaction]

<ApiEndpoint name="triggerFailedDocumentJobForTransaction" />

Trigger Failed Document Job For Segment [#trigger-failed-document-job-for-segment]

<ApiEndpoint name="triggerFailedDocumentJobForSegment" />

Trigger Failed Document Job For Quote [#trigger-failed-document-job-for-quote]

<ApiEndpoint name="triggerFailedDocumentJobForQuote" />

Trigger Failed Document Job For Invoice [#trigger-failed-document-job-for-invoice]

<ApiEndpoint name="triggerFailedDocumentJobForInvoice" />

Installment Jobs [#installment-jobs]

Fetch Installments Jobs for Quotes [#fetch-installments-jobs-for-quotes]

<ApiEndpoint name="fetchInstallmentsJobDataForQuotes" title="Fetch Installments Jobs for Quotes" />

Fetch Installments Jobs for Policy Transactions [#fetch-installments-jobs-for-policy-transactions]

<ApiEndpoint name="fetchInstallmentsJobDataForTransactions" title="Fetch Installments Jobs for Policy Transactions" />

Retry Failed Transactions [#retry-failed-transactions]

<ApiEndpoint name="retryFailedTransactions" />

<ApiSchema name="InstallmentJobDataListResponse" />

<ApiSchema name="InstallmentJobData" />

<ApiSchema name="ListPageResponseInstallmentJobData" />

Invoice Jobs [#invoice-jobs]

Normal Invoicing [#normal-invoicing]

Fetch Invoice Jobs for Accounts [#fetch-invoice-jobs-for-accounts]

<ApiEndpoint name="fetchInvoicingJobsForAccount" title="Fetch Invoice Jobs for Accounts" />

<ApiSchema name="ListPageResponseInvoicingJobData" />

Fetch Invoice Job [#fetch-invoice-job]

<ApiEndpoint name="fetchInvoicingJob" title="Fetch Invoice Job" />

<ApiSchema name="InvoicingJobData" />

<ApiSchema name="ImmediateInvoicingData" />

Fetch Invoice Job Data For Account [#fetch-invoice-job-data-for-account]

<ApiEndpoint name="fetchInvoiceJobDataForAccount" title="Fetch Invoice Job Data For Account" />

<ApiSchema name="InvoiceGenerationJobListResponse" />

<ApiSchema name="InvoiceGenerationJob" />

<ApiSchema name="InvoiceGenerationInstance" />

Fetch Invoice Lifecycle Job Data [#fetch-invoice-lifecycle-job-data]

<ApiEndpoint name="fetchInvoiceLifecycleJobData" title="Fetch Invoice Lifecycle Job Data" />

<ApiSchema name="WorkflowContextInvoiceLifecycleJobData" />

<ApiSchema name="InvoiceLifecycleJobData" />

<ApiSchema name="InvoiceLifecycleTriggerUpdate" />

<ApiSchema name="InvoiceLifecycleTrigger" />

<ApiSchema name="InvoiceLifecycleResult" />

Early Invoicing [#early-invoicing]

<ApiSchema name="EarlyInvoicingGenerationData" />

Delinquency Jobs [#delinquency-jobs]

Fetch Delinquency Grace Job [#fetch-delinquency-grace-job]

<ApiEndpoint name="fetchDelinquencyGraceJob" />

<ApiSchema name="GraceJobDataListResponse" />

<ApiSchema name="GraceJobData" />

Fetch Create Delinquencies Job Data For Invoice [#fetch-create-delinquencies-job-data-for-invoice]

<ApiEndpoint name="fetchCreateDelinquenciesJobDataForInvoice" />

<ApiSchema name="DelinquencyCreateJobDataListResponse" />

<ApiSchema name="DelinquencyCreateJobData" />

Fetch Delinquency Event Jobs [#fetch-delinquency-event-jobs]

<ApiEndpoint name="fetchDelinquencyEventJobs" />

<ApiSchema name="DelinquencyEventJobDataListResponse" />

<ApiSchema name="DelinquencyEventJobData" />

Anonymization Jobs [#anonymization-jobs]

Fetch Anonymization Jobs [#fetch-anonymization-jobs]

<ApiEndpoint name="fetchAnonymizationJobs" />

<ApiSchema name="FetchAnonymizationJobsRequest" />

<ApiSchema name="AnonymizationJobResponse" />

<ApiSchema name="AnonymizationJobDetails" />

<ApiSchema name="ProblematicReferenceLocators" />

<span id="deserialization-jobs" />

Deserialization Jobs [#deserialization-jobs]

List Deserialize Schedule Items Jobs [#list-deserialize-schedule-items-jobs]

<ApiEndpoint name="listDeserializeScheduleItemsJobs" />

<ApiSchema name="ListPageResponseDeserializationJob" />

<ApiSchema name="DeserializationJob" />

<ApiSchema name="DeserializationRequestMetadata" />

Fetch Deserialize Schedule Items Job [#fetch-deserialize-schedule-items-job]

<ApiEndpoint name="fetchDeserializeScheduleItemsJob" />

Terminate Deserialization Job [#terminate-deserialization-job]

<ApiEndpoint name="terminateDeserializationJob" />

Restart Deserialization Job [#restart-deserialization-job]

<ApiEndpoint name="restartDeserializationJob" />


## API Reference

GET /document/{tenantLocator}/documents/transaction/{locator}/jobs/{jobLocator} — fetchDocumentsJobForTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

GET /document/{tenantLocator}/documents/transaction/{locator}/jobs/list — fetchMultipleDocumentsJobsForTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 DocumentJobListResponse — OK

GET /document/{tenantLocator}/documents/segment/{locator}/jobs/{jobLocator} — fetchDocumentsJobForSegment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

GET /document/{tenantLocator}/documents/segment/{locator}/jobs/list — fetchMultipleDocumentsJobsForSegment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 DocumentJobListResponse — OK

GET /document/{tenantLocator}/documents/quote/{locator}/jobs/{jobLocator} — fetchDocumentsJobForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

GET /document/{tenantLocator}/documents/quote/{locator}/jobs/list — fetchMultipleDocumentsJobsForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 DocumentJobListResponse — OK

POST /document/{tenantLocator}/documents/transaction/{locator}/trigger — triggerTimedOutDocumentsJobForTransaction
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/segment/{locator}/trigger — triggerTimedOutDocumentsJobForSegment
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/quote/{locator}/trigger — triggerTimedOutDocumentsJobForQuote
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/transaction/{locator}/jobs/{jobLocator}/trigger — triggerFailedDocumentJobForTransaction
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/segment/{locator}/jobs/{jobLocator}/trigger — triggerFailedDocumentJobForSegment
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/quote/{locator}/jobs/{jobLocator}/trigger — triggerFailedDocumentJobForQuote
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

POST /document/{tenantLocator}/documents/invoices/{locator}/jobs/{jobLocator}/trigger — triggerFailedDocumentJobForInvoice
Permissions: trigger
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 — OK

GET /billing/{tenantLocator}/jobs/installments/quotes/{locator}/list — fetchInstallmentsJobDataForQuotes
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InstallmentJobDataListResponse — OK

GET /billing/{tenantLocator}/jobs/installments/transactions/{locator}/list — fetchInstallmentsJobDataForTransactions
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InstallmentJobDataListResponse — OK

POST /billing/{tenantLocator}/retryJobs/{policyLocator}/retryFailedTransactions — retryFailedTransactions
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
Responses:
  200 ListPageResponseInstallmentJobData — OK

GET /billing/{tenantLocator}/jobs/invoicing/accounts/{locator}/list — fetchInvoicingJobsForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseInvoicingJobData — OK

GET /billing/{tenantLocator}/jobs/invoicing/{jobLocator} — fetchInvoicingJob
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  jobLocator (ulid, path, required)
Responses:
  200 InvoicingJobData — OK

GET /billing/{tenantLocator}/jobs/invoices/accounts/{locator}/list — fetchInvoiceJobDataForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 InvoiceGenerationJobListResponse — OK

GET /billing/{tenantLocator}/jobs/invoicesLifecycle/{locator} — fetchInvoiceLifecycleJobData
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WorkflowContextInvoiceLifecycleJobData — OK

GET /billing/{tenantLocator}/jobs/delinquencies/{delinquencyLocator}/list — fetchDelinquencyGraceJob
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  delinquencyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 GraceJobDataListResponse — OK

GET /billing/{tenantLocator}/jobs/delinquencies/invoices/{invoiceLocator}/list — fetchCreateDelinquenciesJobDataForInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  invoiceLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 DelinquencyCreateJobDataListResponse — OK

GET /billing/{tenantLocator}/jobs/delinquencies/{delinquencyLocator}/events/list — fetchDelinquencyEventJobs
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  delinquencyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 DelinquencyEventJobDataListResponse — OK

GET /compliance/{tenantLocator}/jobs — fetchAnonymizationJobs
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  request (FetchAnonymizationJobsRequest, query, required)
Responses:
  200 AnonymizationJobResponse[] — OK

GET /policy/{tenantLocator}/deserializeJobs/{jobType}/list — listDeserializeScheduleItemsJobs
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  jobType (string, path, required)
  offset (integer, query)
  count (integer, query)
  state (string[], query)
Responses:
  200 ListPageResponseDeserializationJob — OK

GET /policy/{tenantLocator}/deserializeJobs/{locator} — fetchDeserializeScheduleItemsJob
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 DeserializationJob — OK

PATCH /policy/{tenantLocator}/deserializeJobs/{locator}/terminate — terminateDeserializationJob
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /policy/{tenantLocator}/deserializeJobs/{locator}/restart — restartDeserializationJob
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

DocumentJobListResponse
Properties:
  listCompleted (boolean, required)
  items (DocumentsJobSummary[], required)

DocumentsJob
Properties:
  locator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  referenceLocator (ulid, required)
  documentTrigger (Enum validated | priced | accepted | underwritten | issued | generated | declined | rejected | refused, required)
  status (Enum running | finished | failed, required)
  stage (Enum started | referenceResolved | downstreamGenerationStarted | documentsSelected | documentsCreated | generationStarted, required)
  context (DocumentCreationJobContext, required)
  request (CreateDocumentsRequest, required)
  childrenJobs (ulid[], required)
  documents (DocumentJobInfo[], required)
  processingErrors (string, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  completedAt (datetime, required)
  transactionLocator (ulid, required)
  segmentLocator (ulid, required)
  isConsolidation (boolean, required)

DocumentsJobSummary
Properties:
  locator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  status (Enum running | finished | failed, required)
  createdAt (datetime, required)

DocumentJobInfo
Properties:
  locator (ulid, required)
  staticName (string, required)
  name (string, required)
  documentInstanceState (string, required)
  processingErrors (string, required)
  state (string, required) [deprecated]

DocumentContext
Properties:
  transactionLocator (ulid, required)
  segmentLocator (ulid, required)

DocumentInfo
Properties:
  jobLocator (ulid, required)
  action (Enum generate | noChange | generateIfAbsent | remove | defaultAction, required)
  productName (string)
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  transactionLocator (ulid)
  segmentLocator (ulid)
  name (string, required)
  staticName (string, required)
  jurisdiction (string)

CreateDocumentsRequest
Properties:
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  generationJobLocators (ulid[], required)
  policyDocumentRequest (CreatePolicyDocumentRequest)
  invoiceDocumentRequest (CreateInvoiceDocumentRequest)
  consolidatedPolicyDocumentRequest (CreateConsolidatedPolicyDocumentRequest)
  rerun (boolean)

DocumentCreationJobContext
Properties:
  referenceLocator (ulid, required)
  documentContext (DocumentContext, required)
  documentSelection (map<string, Enum generate | noChange | generateIfAbsent | remove | defaultAction>, required)
  documentLocatorMapping (map<string, ulid>, required)
  documentGenerationRequests (DocumentInfo[], required)
  documentGenerationMapping (map<string, DocumentInfo>, required)
  processedDocumentStaticNames (string[], required)
  scheduledDocumentLocators (ulid[], required)

CreateInvoiceDocumentRequest
Properties:
  invoiceDocumentName (string, required)

CreatePolicyDocumentRequest
Properties:
  productName (string, required)
  referenceState (string, required)
  transactionLocator (ulid)
  trigger (Enum validated | priced | accepted | underwritten | issued | generated | declined | rejected | refused, required)
  policyLocator (ulid)
  termLocator (ulid)
  segmentLocator (ulid)

CreateConsolidatedPolicyDocumentRequest
Properties:
  productName (string, required)
  referenceState (string, required)
  transactionLocator (ulid)
  trigger (Enum validated | priced | accepted | underwritten | issued | generated | declined | rejected | refused, required)

InstallmentJobDataListResponse
Properties:
  listCompleted (boolean, required)
  items (InstallmentJobData[], required)

InstallmentJobData
Properties:
  locator (ulid, required)
  referenceLocator (ulid, required)
  latticeLocator (ulid, required)
  installmentLocators (string, required)
  jobStatus (Enum queued | finished | failed | running, required)
  createdAt (datetime, required)
  completedAt (datetime, required)
  processingErrors (string, required)

ListPageResponseInstallmentJobData
Properties:
  listCompleted (boolean, required)
  items (InstallmentJobData[], required)

ListPageResponseInvoicingJobData
Properties:
  listCompleted (boolean, required)
  items (InvoicingJobData[], required)

InvoicingJobData
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  jobStatus (Enum queued | finished | failed | running, required)
  createdAt (datetime, required)
  completedAt (datetime)
  processingErrors (string)
  invoiceLocators (ulid[], required)
  invoicingData (oneOf<EarlyInvoicingGenerationData,ImmediateInvoicingData>, required)

ImmediateInvoicingData
Properties:
  invoicingType (string, required)
  accountLocator (ulid, required)
  currencies (string[], required)

InvoiceGenerationJobListResponse
Properties:
  listCompleted (boolean, required)
  items (InvoiceGenerationJob[], required)

InvoiceGenerationJob
Properties:
  locator (ulid, required)
  invoiceGenerationScheduleLocator (ulid, required)
  jobStatus (Enum queued | finished | failed | running, required)
  generateTime (datetime, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  completedAt (datetime, required)
  processingErrors (string, required)
  invoiceGenerationInstances (InvoiceGenerationInstance[], required)

InvoiceGenerationInstance
Properties:
  locator (ulid, required)
  invoiceGenerationJobLocator (ulid, required)
  generateTime (datetime, required)
  jobStatus (Enum queued | finished | failed | running, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  completedAt (datetime, required)
  invoiceLocator (ulid, required)
  processingErrors (string, required)

WorkflowContextInvoiceLifecycleJobData
Properties:
  workflowJobLocator (ulid, required)
  workflowType (Enum LATTICE_AND_INSTALLMENTS_GENERATION | INVOICE_GENERATION | INVOICE_LIFECYCLE | PAYMENT_EXECUTION | DELINQUENCY_MORATORIUM_EXECUTION, required)
  contextData (InvoiceLifecycleJobData, required)
  completedAt (datetime)
  createdAt (datetime, required)

InvoiceLifecycleJobData
Properties:
  invoiceLocator (ulid, required)
  triggers (InvoiceLifecycleTrigger[], required)
  triggersHistory (InvoiceLifecycleTriggerUpdate[], required)
  results (InvoiceLifecycleResult[], required)
  processingErrors (string)

InvoiceLifecycleTriggerUpdate
Properties:
  triggerType (Enum autopay | due, required)
  oldTriggerTime (datetime, required)
  newTriggerTime (datetime, required)
  comment (string, required)

InvoiceLifecycleTrigger
Properties:
  triggerType (Enum autopay | due, required)
  triggerTime (datetime, required)

InvoiceLifecycleResult
Properties:
  resultType (Enum autopay | due, required)
  resultLocator (ulid, required)

EarlyInvoicingGenerationData
Properties:
  invoicingType (string, required)
  accountLocator (ulid, required)
  installmentsToBeInvoiced (ulid[], required)
  invoiceDueTime (datetime)
  invoiceThroughTime (datetime)
  timezone (string)
  policyLocator (ulid)
  aggregateInvoices (boolean)
  includeExistingInvoices (boolean)

GraceJobDataListResponse
Properties:
  listCompleted (boolean, required)
  items (GraceJobData[], required)

GraceJobData
Properties:
  locator (ulid, required)
  jobStatus (Enum queued | finished | failed | running, required)
  outcome (string)
  delinquencyLocator (ulid, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  processingErrors (string)

DelinquencyCreateJobDataListResponse
Properties:
  listCompleted (boolean, required)
  items (DelinquencyCreateJobData[], required)

DelinquencyCreateJobData
Properties:
  locator (ulid, required)
  invoiceLocator (ulid, required)
  dueTime (datetime, required)
  jobStatus (Enum queued | finished | failed | running, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  delinquencyLocators (ulid[], required)
  processingErrors (string)

DelinquencyEventJobDataListResponse
Properties:
  listCompleted (boolean, required)
  items (DelinquencyEventJobData[], required)

DelinquencyEventJobData
Properties:
  locator (ulid, required)
  delinquencyLocator (ulid, required)
  delinquencyEventLocator (ulid, required)
  triggerTime (datetime, required)
  jobStatus (Enum queued | finished | failed | running, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  cancelled (boolean)
  cancellationType (Enum cancellationRequested | rescheduled | tenantRetired | delinquencySettled | delinquencyHeld | delinquencyUnderMoratorium)
  updatedDelinquencyEventLocators (ulid[], required)
  processingErrors (string)
  rescheduledByLocator (ulid)

FetchAnonymizationJobsRequest
Properties:
  jobLocators (ulid[], required)

AnonymizationJobResponse
Properties:
  referenceType (Enum none | account | quickQuote | quote | policy | contact | fnol | payment | disbursement, required)
  jobLocator (ulid, required)
  jobStatus (Enum initialized | running | suspended | completed, required)
  assignedReferenceLocators (ulid[], required)
  updatedAt (datetime, required)
  createdBy (uuid)
  parentJobLocator (ulid)
  processingErrors (string)
  jobDetails (AnonymizationJobDetails, required)
  anonymizedReferenceLocators (ulid[])

AnonymizationJobDetails
Properties:
  assignedReferenceLocators (ulid[], required)
  problematicReferenceLocators (ProblematicReferenceLocators)
  includeAcceptedQuotes (boolean)
  policyStatuses (Enum[])

ProblematicReferenceLocators
Properties:
  assigned (ulid[], required)
  children (ulid[], required)
  failed (ulid[], required)

ListPageResponseDeserializationJob
Properties:
  listCompleted (boolean, required)
  items (DeserializationJob[], required)

DeserializationJob
Properties:
  locator (ulid, required)
  jobType (Enum scheduleItems, required)
  jobState (Enum initialized | running | interrupted | failed | completed | terminated, required)
  metadata (DeserializationRequestMetadata, required)
  createdBy (uuid, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  retryCount (integer, required)
  processingErrors (string)

DeserializationRequestMetadata
Properties:
  fileName (string, required)
  fileSize (integer, required)
  referenceType (string, required)
  referenceLocator (ulid, required)
  staticElementLocator (ulid, required)
  params (map<string, string>, required)

# Logging API



<EndpointIndex
  names={['fetchLogsList', 'fetchLogs']}
  titles={{
  	fetchLogsList: 'Fetch a List of Logs',
  	fetchLogs: 'Fetch Logs for a Request',
  }}
/>

Fetch a List of Logs [#fetch-a-list-of-logs]

<ApiEndpoint name="fetchLogsList" title="Fetch a List of Logs" />

<ApiSchema name="PluginLogsListResponse" />

<ApiSchema name="PluginLogsMetadata" />

<ApiSchema name="ObjectReference" />

Fetch Logs for a Request [#fetch-logs-for-a-request]

<ApiEndpoint name="fetchLogs" title="Fetch Logs for a Request" />


## API Reference

GET /plugin/{tenantLocator}/logs/list — fetchLogsList
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  requestId (ulid, query)
  objectLocator (ulid, query)
  createdAtMin (datetime, query)
  createdAtMax (datetime, query)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 PluginLogsListResponse — OK

GET /plugin/{tenantLocator}/logs/{locator} — fetchLogs
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  Accept-Encoding (string, header)
  locator (ulid, path, required)
Responses:
  200 — OK

PluginLogsListResponse
Properties:
  listCompleted (boolean, required)
  items (PluginLogsMetadata[], required)

PluginLogsMetadata
Properties:
  locator (ulid, required)
  createdAt (datetime, required)
  pluginType (Enum delinquencyEvent | documentDataSnapshot | documentSelection | preCommit | rating | renewal | underwriting | validation, required)
  requestId (ulid, required)
  objectReferences (ObjectReference[], required)

ObjectReference
Properties:
  locator (ulid, required)
  type (string, required)

# Passwords API



<EndpointIndex names={['fetchPasswordPolicy', 'updatePasswordPolicy']} />

Fetch [#fetch]

Fetch Password Policy [#fetch-password-policy]

<ApiEndpoint name="fetchPasswordPolicy" />

<ApiSchema name="PasswordPolicyResponse" />

<ApiSchema name="PasswordPolicies" />

Update [#update]

Update Password Policy [#update-password-policy]

<ApiEndpoint name="updatePasswordPolicy" />

<ApiSchema name="PasswordPolicyUpdateRequest" />

<ApiSchema name="PasswordPoliciesUpdateRequest" />

<Callout type="warn">
  The <ApiLink name="updatePasswordPolicy" /> endpoint is a `PUT` endpoint, which means *all* the password policy settings will be replaced. If any properties are not included in the update request, the default values will be used.
</Callout>

See Also [#see-also]

* [Passwords Feature Guide](/features/security/password-policies)


## API Reference

GET /auth/identity/passwordPolicy — fetchPasswordPolicy
Permissions: read, custom
Responses:
  200 PasswordPolicyResponse — OK

PUT /auth/identity/passwordPolicy — updatePasswordPolicy
Permissions: add, custom
Request body (PasswordPolicyUpdateRequest):
Responses:
  200 — OK

PasswordPolicyResponse
Properties:
  passwordPolicies (PasswordPolicies, required)

PasswordPolicies
Properties:
  digits (integer, required) — The minimum number of numeric digits required in the password string.
  forceExpiredPasswordChange (integer, required) — The number of days the password is valid before a new password is required.
  length (integer, required) — The minimum number of characters allowed in the password.
  lowercase (integer, required) — The minimum number of uppercase characters required in the password string.
  maxLength (integer, required) — The maximum number of characters allowed in the password.
  passwordHistory (integer, required) — The count of previous passwords that are not allowed to be reused, starting with the most recent.
  specialChars (integer, required) — The minimum number of special characters required in the password string.
  uppercase (integer, required) — The minimum number of uppercase characters required in the password string.

PasswordPolicyUpdateRequest
Properties:
  passwordPolicies (PasswordPoliciesUpdateRequest, required)

PasswordPoliciesUpdateRequest
Properties:
  digits (integer) — The minimum number of numeric digits required in the password string.
  forceExpiredPasswordChange (integer) — The number of days the password is valid before a new password is required.
  length (integer) — The minimum number of characters allowed in the password.
  lowercase (integer) — The minimum number of uppercase characters required in the password string.
  maxLength (integer) — The maximum number of characters allowed in the password.
  passwordHistory (integer) — The minimum age of a password in days to allow its reuse.
  specialChars (integer) — The minimum number of special characters required in the password string.
  uppercase (integer) — The minimum number of uppercase characters required in the password string.

# Webhooks API



<EndpointIndex
  names={[
  	'fetchWebhook',
  	'fetchWebhooks',
  	'createWebhook',
  	'updateWebhook',
  	'unsuspendWebhook',
  	'deleteWebhook',
  ]}
  titles={{
  	fetchWebhook: 'Fetch a Webhook',
  	fetchWebhooks: 'Fetch All Webhooks',
  	createWebhook: 'Create a Webhook',
  	updateWebhook: 'Update a Webhook',
  	deleteWebhook: 'Delete a Webhook',
  }}
/>

Fetch a Webhook [#fetch-a-webhook]

<ApiEndpoint name="fetchWebhook" title="Fetch a Webhook" />

Fetch All Webhooks [#fetch-all-webhooks]

<ApiEndpoint name="fetchWebhooks" title="Fetch All Webhooks" />

<ApiSchema name="WebhookListResponse" />

<ApiSchema name="WebhookResponse" />

<ApiSchema name="EndpointResponse" />

Create a Webhook [#create-a-webhook]

<ApiEndpoint name="createWebhook" title="Create a Webhook" />

<ApiSchema name="CreateWebhookRequest" />

<ApiSchema name="CreateEndpointRequest" />

Update a Webhook [#update-a-webhook]

<ApiEndpoint name="updateWebhook" title="Update a Webhook" />

<Callout>
  This endpoint follows Socotra Insurance Suite's add-remove semantics for updates: removals happen first, followed by additions. This means that addition takes precedence over removal if a request includes some item in both "remove" and "add".
</Callout>

<ApiSchema name="UpdateWebhookRequest" />

<ApiSchema name="UpdateEndpointRequest" />

Unsuspend Webhook [#unsuspend-webhook]

<ApiEndpoint name="unsuspendWebhook" />

Delete a Webhook [#delete-a-webhook]

<ApiEndpoint name="deleteWebhook" title="Delete a Webhook" />

See Also [#see-also]

* [Webhooks Feature Guide](/configuration/general-topics/webhooks): Webhooks feature guide
* [Events API](/api/events/events): API details, including a list of supported events
* [Diverted Events API](/api/events/diverted-events): Functionality to handle failed webhook event messages.


## API Reference

GET /event/{tenantLocator}/webhooks/{webhookLocator} — fetchWebhook
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
Responses:
  200 WebhookResponse — OK

GET /event/{tenantLocator}/webhooks/list — fetchWebhooks
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  name (string, query)
  enabled (boolean, query)
  suspended (boolean, query)
  active (boolean, query)
  eventTypes (string[], query)
  extended (boolean, query)
Responses:
  200 WebhookListResponse — OK

POST /event/{tenantLocator}/webhooks — createWebhook
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (CreateWebhookRequest):
Responses:
  200 WebhookResponse — OK

PATCH /event/{tenantLocator}/webhooks/{webhookLocator} — updateWebhook
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
Request body (UpdateWebhookRequest):
Responses:
  200 WebhookResponse — OK

PATCH /event/{tenantLocator}/webhooks/{webhookLocator}/unsuspend — unsuspendWebhook
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
Responses:
  204 — No Content

DELETE /event/{tenantLocator}/webhooks/{webhookLocator} — deleteWebhook
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
Responses:
  204 — No Content

WebhookListResponse
Properties:
  listCompleted (boolean, required)
  items (WebhookResponse[], required)

WebhookResponse
Properties:
  locator (ulid, required)
  name (string, required)
  enabled (boolean, required)
  suspended (boolean, required)
  suspendedAt (datetime, required)
  eventTypes (string[], required)
  endpoint (EndpointResponse, required)
  failureHandling (FailureHandlingResponse, required)

EndpointResponse
Properties:
  url (string, required)
  headers (map<string, string[]>, required)
  secureSsl (boolean, required)
  hmacEnabled (boolean, required)
  secret (string, required)
  tag (string, required)

CreateWebhookRequest
Properties:
  name (string, required)
  enabled (boolean, required)
  eventTypes (string[], required)
  endpoint (CreateEndpointRequest, required)
  failureHandling (FailureHandlingCreateRequest, required)
  useAutomationPlugin (boolean)

CreateEndpointRequest
Properties:
  url (string, required)
  headers (map<string, string[]>)
  secureSsl (boolean)
  hmacEnabled (boolean)
  secret (string)
  tag (string)

UpdateWebhookRequest
Properties:
  name (string, required)
  enabled (boolean, required)
  removeEventTypes (string[], required)
  addEventTypes (string[], required)
  endpoint (UpdateEndpointRequest, required)
  removeFailureHandling (boolean, required)
  failureHandling (FailureHandlingUpdateRequest, required)

UpdateEndpointRequest
Properties:
  url (string, required)
  removeHeaders (string[], required)
  addHeaders (map<string, string[]>, required)
  secureSsl (boolean)
  hmacEnabled (boolean)
  secret (string)
  tag (string)

# Diverted Events API



This API Guide describes functionality for handling failed webhook event messages.

<EndpointIndex
  names={[
  	'fetchDivertedEvent',
  	'fetchMultipleDivertedEvents',
  	'resendDivertedEvent',
  	'deleteDivertedEvent',
  ]}
/>

Fetch Diverted Event [#fetch-diverted-event]

<ApiEndpoint name="fetchDivertedEvent" />

Fetch Multiple Diverted Events [#fetch-multiple-diverted-events]

<ApiEndpoint name="fetchMultipleDivertedEvents" />

<ApiSchema name="DivertedEventResponse" />

Resend Diverted Event [#resend-diverted-event]

<ApiEndpoint name="resendDivertedEvent" />

Delete Diverted Event [#delete-diverted-event]

<ApiEndpoint name="deleteDivertedEvent" />

<ApiSchema name="FailureHandlingCreateRequest" />

<ApiSchema name="FailureHandlingUpdateRequest" />

<ApiSchema name="FailureHandlingResponse" />

<ApiSchema name="RetryStrategyCreateRequest" />

<ApiSchema name="RetryStrategyResponse" />

<ApiSchema name="RetryStrategyUpdateRequest" />

See Also [#see-also]

* [Events Feature Guide](/configuration/general-topics/events)
* [Webhooks Feature Guide](/configuration/general-topics/webhooks)
* [Events API](/api/events/events): Events API details, including a list of supported events


## API Reference

GET /event/{tenantLocator}/webhooks/{webhookLocator}/diverted/{eventLocator} — fetchDivertedEvent
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
  eventLocator (ulid, path, required)
Responses:
  200 DivertedEventResponse — OK

GET /event/{tenantLocator}/webhooks/{webhookLocator}/diverted — fetchMultipleDivertedEvents
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 DivertedEventResponse[] — OK

POST /event/{tenantLocator}/webhooks/{webhookLocator}/diverted/{eventLocator}/resend — resendDivertedEvent
Permissions: resend
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
  eventLocator (ulid, path, required)
Responses:
  200 object — OK

DELETE /event/{tenantLocator}/webhooks/{webhookLocator}/diverted/{eventLocator} — deleteDivertedEvent
Permissions: delete
Parameters:
  tenantLocator (uuid, path, required)
  webhookLocator (ulid, path, required)
  eventLocator (ulid, path, required)
Responses:
  200 object — OK

DivertedEventResponse
Properties:
  requestLocator (ulid, required)
  eventLocator (ulid, required)
  failureTrigger (string, required)
  failureMessage (string, required)
  failureTimestamp (datetime, required)

FailureHandlingCreateRequest
Properties:
  alertEndpoint (CreateEndpointRequest, required)
  triggers (string[], required)
  retryStrategy (RetryStrategyCreateRequest, required)
  divert (boolean, required)
  suspend (boolean, required)

FailureHandlingUpdateRequest
Properties:
  removeAlertEndpoint (boolean, required)
  alertEndpoint (UpdateEndpointRequest, required)
  removeTriggers (string[], required)
  addTriggers (string[], required)
  removeRetryStrategy (boolean, required)
  retryStrategy (RetryStrategyUpdateRequest, required)
  divert (boolean, required)
  suspend (boolean, required)

FailureHandlingResponse
Properties:
  alertEndpoint (EndpointResponse, required)
  triggers (string[], required)
  retryStrategy (RetryStrategyResponse, required)
  divert (boolean, required)
  suspend (boolean, required)

RetryStrategyCreateRequest
Properties:
  type (Enum linear | exponential, required)
  interval (integer, required)
  attempts (integer, required)

RetryStrategyResponse
Properties:
  type (Enum linear | exponential, required)
  interval (integer, required)
  attempts (integer, required)

RetryStrategyUpdateRequest
Properties:
  type (Enum linear | exponential, required)
  interval (integer, required)
  attempts (integer, required)

# Events API



<EndpointIndex
  names={[
  	'fetchEvent',
  	'fetchEventsForARequest',
  	'fetchMultipleEvents',
  	'fetchScheduledPolicyEvents',
  	'fetchScheduledTenantEvents',
  	'scheduleTenantEvents',
  	'resumeFailedScheduledEvent',
  	'fetchFailedScheduledPolicyEvents',
  	'fetchFailedScheduledTenantEvents',
  	'fetchFailedScheduledEventsByFailedJobState',
  	'fetchFailedScheduledEvents',
  	'deleteFailedScheduledEvent',
  ]}
  titles={{
  	fetchEvent: 'Fetch an Event',
  	fetchEventsForARequest: 'Fetch Events for an API Request',
  	fetchMultipleEvents: 'Fetch Multiple Events',
  	fetchScheduledPolicyEvents: 'Fetch Scheduled Policy Events',
  	fetchScheduledTenantEvents: 'Fetch Scheduled Tenant Events',
  	scheduleTenantEvents: 'Schedule Custom Tenant Events',
  	resumeFailedScheduledEvent: 'Resume Failed Scheduled Event',
  	fetchFailedScheduledPolicyEvents: 'Fetch Failed Scheduled Policy Events',
  	fetchFailedScheduledTenantEvents: 'Fetch Failed Scheduled Tenant Events',
  	fetchFailedScheduledEventsByFailedJobState:
  		'Fetch Failed Scheduled Events By Failed Job State',
  	fetchFailedScheduledEvents: 'Fetch Failed Scheduled Events',
  	deleteFailedScheduledEvent: 'Delete Failed Scheduled Event',
  }}
/>

Fetch [#fetch]

Fetch an Event [#fetch-an-event]

<ApiEndpoint name="fetchEvent" title="Fetch an Event" />

Fetch Events for an API Request [#fetch-events-for-an-api-request]

<ApiEndpoint name="fetchEventsForARequest" title="Fetch Events for an API Request" />

Fetch Multiple Events [#fetch-multiple-events]

<ApiEndpoint name="fetchMultipleEvents" title="Fetch Multiple Events" />

<ApiSchema name="EventStreamResponse" />

<ApiSchema name="EventResponse" />

Fetch Scheduled Policy Events [#fetch-scheduled-policy-events]

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

<ApiSchema name="ScheduledPolicyEvent" />

Fetch Scheduled Tenant Events [#fetch-scheduled-tenant-events]

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

<ApiSchema name="ScheduledTenantEvent" />

Schedule Custom Tenant Events [#schedule-custom-tenant-events]

<ApiEndpoint name="scheduleTenantEvents" title="Schedule Custom Tenant Events" />

<ApiSchema name="ScheduleTenantEventsRequest" />

<ApiSchema name="ScheduleTenantEventRequest" />

Resume Failed Scheduled Event [#resume-failed-scheduled-event]

<ApiEndpoint name="resumeFailedScheduledEvent" title="Resume Failed Scheduled Event" />

Fetch Failed Scheduled Policy Events [#fetch-failed-scheduled-policy-events]

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

Fetch Failed Scheduled Tenant Events [#fetch-failed-scheduled-tenant-events]

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

Fetch Failed Scheduled Events By Failed Job State [#fetch-failed-scheduled-events-by-failed-job-state]

<ApiEndpoint name="fetchFailedScheduledEventsByFailedJobState" title="Fetch Failed Scheduled Events By Failed Job State" />

Fetch Failed Scheduled Events [#fetch-failed-scheduled-events]

<ApiEndpoint name="fetchFailedScheduledEvents" title="Fetch Failed Scheduled Events" />

Delete Failed Scheduled Event [#delete-failed-scheduled-event]

<ApiEndpoint name="deleteFailedScheduledEvent" title="Delete Failed Scheduled Event" />

<ApiSchema name="FailedJobRequest" />

<ApiSchema name="FailedJobDetails" />

<Callout>
  Custom events generated from plugin code will be added to the event stream even if the operation associated with that plugin call has failed.
</Callout>

<Callout>
  For events generated from API calls, The `timestamp` and ordering of events in the event stream are dependent on  the *completion time* of the call. It is possible for events from an API call made before another to come after those events from the subsequent API call, if the first call takes longer than the second call to complete.
</Callout>

See Also [#see-also]

* [Events Configuration Guide](/configuration/general-topics/events)
* [Event Definitions](/configuration/general-topics/event-definitions)


## API Reference

GET /event/{tenantLocator}/events/{locator} — fetchEvent
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EventResponse — OK

GET /event/{tenantLocator}/events/request/{locator} — fetchEventsForARequest
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EventResponse[] — OK

GET /event/{tenantLocator}/events/list — fetchMultipleEvents
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  startTimestamp (datetime, query)
  endTimestamp (datetime, query)
  type (string, query)
  pageSize (integer, query)
  pagingToken (string, query)
Responses:
  200 EventStreamResponse — OK

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

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

POST /config/{tenantLocator}/tenantEvents — scheduleTenantEvents
Permissions: tenant-events
Parameters:
  tenantLocator (uuid, path, required)
Request body (ScheduleTenantEventsRequest):
Responses:
  200 — OK

POST /event/{tenantLocator}/events/schedules/failed/resume — resumeFailedScheduledEvent
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (FailedJobRequest):
Responses:
  204 — No Content

GET /event/{tenantLocator}/events/schedules/policy/{policyLocator}/failed/list — fetchFailedScheduledPolicyEvents
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 FailedJobDetails[] — OK

GET /event/{tenantLocator}/events/schedules/tenant/failed/list — fetchFailedScheduledTenantEvents
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 FailedJobDetails[] — OK

GET /event/{tenantLocator}/events/schedules/failed/{failedJobState}/list — fetchFailedScheduledEventsByFailedJobState
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  failedJobState (Enum queued | quit, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 FailedJobDetails[] — OK

GET /event/{tenantLocator}/events/schedules/failed/list — fetchFailedScheduledEvents
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 FailedJobDetails[] — OK

DELETE /event/{tenantLocator}/events/schedules/failed — deleteFailedScheduledEvent
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (FailedJobRequest):
Responses:
  204 — No Content

EventStreamResponse
Properties:
  pagingToken (string, required)
  events (EventResponse[], required)

EventResponse
Properties:
  locator (ulid, required)
  requestId (ulid, required) — Identifier of the transaction request that triggered the event
  userLocator (uuid, required)
  timestamp (datetime, required)
  type (string, required)
  data (map<string, object>, required)

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

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

ScheduleTenantEventsRequest
Properties:
  requests (ScheduleTenantEventRequest[], required)

ScheduleTenantEventRequest
Properties:
  scheduleId (string, required)
  eventTypeId (string, required)
  eventTime (datetime, required)
  data (map<string, object>, required)

FailedJobRequest
Properties:
  triggerGroup (string, required)
  triggerName (string, required)

FailedJobDetails
Properties:
  failedJobState (Enum queued | quit, required)
  triggerGroup (string, required)
  triggerName (string, required)
  createdAt (datetime, required)
  updatedAt (datetime, required)
  failureCount (integer, required)
  stackTrace (string, required)

# Policies API



<EndpointIndex
  names={[
  	'fetchPolicy',
  	'addStaticDataForPolicy',
  	'updateStaticDataForPolicy',
  	'replaceAllStaticDataForPolicy',
  	'fetchStaticDataForPolicy',
  	'listStaticDataForPolicy',
  	'fetchPolicySnapshot',
  	'fetchMultipleSnapshots',
  	'updateBillingLevelForAPolicy',
  	'fetchPoliciesWithNumber',
  	'setPolicyNumber',
  	'setReservedPolicyNumber',
  	'generatePolicyNumber',
  	'addPolicyContact',
  	'deletePolicyContact',
  	'fetchPolicyContacts',
  	'updatePolicyContact',
  	'updatePolicyJurisdiction',
  	'createQuoteFromPolicy',
  ]}
  titles={{
  	fetchPolicy: 'Fetch a Policy',
  	addStaticDataForPolicy: 'Add Static Data to a Policy',
  	updateStaticDataForPolicy: 'Update Static Data on a Policy',
  	replaceAllStaticDataForPolicy: 'Replace All Static Data on a Policy',
  	fetchStaticDataForPolicy: 'Fetch Static Data for a Policy',
  	listStaticDataForPolicy: 'List Static Data for a Policy',
  	fetchPolicySnapshot: 'Fetch a Policy Snapshot',
  	addPolicyContact: 'Add policy contact',
  	deletePolicyContact: 'Delete policy contact',
  	fetchPolicyContacts: 'Fetch policy contacts',
  	updatePolicyContact: 'Update policy contact',
  }}
/>

Fetch [#fetch]

Fetch a Policy [#fetch-a-policy]

<ApiEndpoint name="fetchPolicy" title="Fetch a Policy" />

<ApiSchema name="PolicyResponse" />

Fetch all Policies for an Account [#fetch-all-policies-for-an-account]

<ApiEndpoint name="fetchPoliciesForAccount" title="Fetch all Policies for an Account" />

<ApiSchema name="PolicyListResponse" />

Static Data [#static-data]

Add Static Data to a Policy [#add-static-data-to-a-policy]

<ApiEndpoint name="addStaticDataForPolicy" title="Add Static Data to a Policy" />

Update Static Data on a Policy [#update-static-data-on-a-policy]

<ApiEndpoint name="updateStaticDataForPolicy" title="Update Static Data on a Policy" />

<ApiSchema name="StaticDataUpdateRequest" />

Replace All Static Data on a Policy [#replace-all-static-data-on-a-policy]

<ApiEndpoint name="replaceAllStaticDataForPolicy" title="Replace All Static Data on a Policy" />

Fetch Static Data for a Policy [#fetch-static-data-for-a-policy]

<ApiEndpoint name="fetchStaticDataForPolicy" title="Fetch Static Data for a Policy" />

List Static Data for a Policy [#list-static-data-for-a-policy]

<ApiEndpoint name="listStaticDataForPolicy" title="List Static Data for a Policy" />

<ApiSchema name="ListPageResponseStaticDataHistoryResponse" />

<ApiSchema name="StaticDataHistoryResponse" />

Snapshots [#snapshots]

Fetch a Policy Snapshot [#fetch-a-policy-snapshot]

<ApiEndpoint name="fetchPolicySnapshot" title="Fetch a Policy Snapshot" />

Fetch Multiple Snapshots [#fetch-multiple-snapshots]

<ApiEndpoint name="fetchMultipleSnapshots" />

<ApiSchema name="PolicySnapshotListResponse" />

<ApiSchema name="PolicySnapshotResponse" />

<ApiSchema name="TransactionSnapshotResponse" />

Billing [#billing]

Update Billing Level For APolicy [#update-billing-level-for-apolicy]

<ApiEndpoint name="updateBillingLevelForAPolicy" />

<ApiSchema name="UpdateBillingLevelRequest" />

Update the Delinquency Plan Assigned to a Policy [#update-the-delinquency-plan-assigned-to-a-policy]

<ApiEndpoint name="updatePolicyDelinquencyPlan" title="Update the Delinquency Plan Assigned to a Policy" />

Numbering [#numbering]

Fetch Policies With Number [#fetch-policies-with-number]

<ApiEndpoint name="fetchPoliciesWithNumber" />

Set Policy Number [#set-policy-number]

<ApiEndpoint name="setPolicyNumber" />

Set Reserved Policy Number [#set-reserved-policy-number]

<ApiEndpoint name="setReservedPolicyNumber" />

Generate Policy Number [#generate-policy-number]

<ApiEndpoint name="generatePolicyNumber" />

Contacts [#contacts]

Add policy contact [#add-policy-contact]

<ApiEndpoint name="addPolicyContact" title="Add policy contact" />

<ApiSchema name="ContactRoles" />

Delete policy contact [#delete-policy-contact]

<ApiEndpoint name="deletePolicyContact" title="Delete policy contact" />

Fetch policy contacts [#fetch-policy-contacts]

<ApiEndpoint name="fetchPolicyContacts" title="Fetch policy contacts" />

Update policy contact [#update-policy-contact]

<ApiEndpoint name="updatePolicyContact" title="Update policy contact" />

Holds [#holds]

Fetch Policy Holds [#fetch-policy-holds]

<ApiEndpoint name="fetchPolicyHolds" />

Jurisdictions [#jurisdictions]

Update Policy Jurisdiction [#update-policy-jurisdiction]

<ApiEndpoint name="updatePolicyJurisdiction" />

<ApiSchema name="UpdateJurisdictionRequest" />

Create Quote from Policy [#create-quote-from-policy]

Create Quote From Policy [#create-quote-from-policy-1]

<ApiEndpoint name="createQuoteFromPolicy" />

<Callout>
  The `date` parameter specifies the point in time used to identify which policy segment to copy. If a `date` is not provided, the generated quote will be based on the segment created by the policy's issuance transaction. The `byIssuedTime` parameter determines whether the provided `date` is evaluated against the segment's issued time or effective time, and `includeStaticData` controls whether policy-level static data is included in the generated quote.
</Callout>


## API Reference

GET /policy/{tenantLocator}/policies/{locator} — fetchPolicy
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyResponse — OK

GET /policy/{tenantLocator}/accounts/{locator}/policies/list — fetchPoliciesForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  includeStaticData (boolean, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 PolicyListResponse — OK

POST /policy/{tenantLocator}/policies/{locator}/static — addStaticDataForPolicy
Set the static extension data on a policy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, object>):
Responses:
  200 PolicyResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/static — updateStaticDataForPolicy
Updates some of the static data on a policy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (StaticDataUpdateRequest):
Responses:
  200 PolicyResponse — OK

PUT /policy/{tenantLocator}/policies/{locator}/static — replaceAllStaticDataForPolicy
Replaces all of the static data on a policy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, object>):
Responses:
  200 PolicyResponse — OK

GET /policy/{tenantLocator}/policies/{locator}/static — fetchStaticDataForPolicy
Gets the static data on a policy
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, object> — OK

GET /policy/{tenantLocator}/policies/{locator}/static/history/list — listStaticDataForPolicy
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseStaticDataHistoryResponse — OK

GET /policy/{tenantLocator}/policies/{locator}/snapshot — fetchPolicySnapshot
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  date (datetime, query, required)
  byIssuedTime (boolean, query)
Responses:
  200 PolicySnapshotResponse — OK

GET /policy/{tenantLocator}/policies/snapshot/list — fetchMultipleSnapshots
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 PolicySnapshotResponse[] — OK

PATCH /policy/{tenantLocator}/policies/{locator}/billingLevel — updateBillingLevelForAPolicy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateBillingLevelRequest):
Responses:
  200 PolicyResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/delinquencyPlan — updatePolicyDelinquencyPlan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DelinquencyPlanUpdateRequest):
Responses:
  200 PolicyResponse — OK

GET /policy/{tenantLocator}/policies/numbers/{policyNumber} — fetchPoliciesWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  policyNumber (string, path, required)
Responses:
  200 PolicyResponse[] — OK

POST /policy/{tenantLocator}/policies/{locator}/number/set — setPolicyNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  policyNumber (string, query, required)
Responses:
  200 PolicyResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/reservedPolicyNumber/set — setReservedPolicyNumber
Permissions: write, reserve-policy-number-set
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  reservedPolicyNumber (string, query, required)
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/policies/{locator}/number/generate — generatePolicyNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyResponse — OK

POST /policy/{tenantLocator}/policies/{policyLocator}/contacts — addPolicyContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
Request body (ContactRoles):
Responses:
  200 PolicyResponse — OK

DELETE /policy/{tenantLocator}/policies/{policyLocator}/contacts/{contactLocator} — deletePolicyContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Responses:
  200 PolicyResponse — OK

GET /policy/{tenantLocator}/policies/{policyLocator}/contacts — fetchPolicyContacts
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
Responses:
  200 ContactRoles[] — OK

PATCH /policy/{tenantLocator}/policies/{policyLocator}/contacts/{contactLocator} — updatePolicyContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Request body (ContactAssociationUpdateRequest):
Responses:
  200 PolicyResponse — OK

GET /policy/{tenantLocator}/policies/{locator}/holds — fetchPolicyHolds
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold[] — OK

PATCH /policy/{tenantLocator}/policies/{locator}/jurisdiction — updatePolicyJurisdiction
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateJurisdictionRequest):
Responses:
  200 PolicyResponse — OK

POST /policy/{tenantLocator}/policies/{locator}/quote — createQuoteFromPolicy
Permissions: write, create-quote
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  date (datetime, query)
  byIssuedTime (boolean, query)
  includeStaticData (boolean, query)
Responses:
  200 QuoteResponse — OK

PolicyResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  branchHeadTransactionLocators (ulid[]) — The locators of all the top-level transactions on the policy, one per branch
  issuedTransactionLocator (ulid, required) — The locator of the latest issued transaction for the policy.
  productName (string, required)
  timezone (string, required)
  currency (string, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  startTime (datetime, required) — The start time, based on issued transactions only
  endTime (datetime, required) — The end time based on issued transactions only.
  latestTermLocator (ulid, required)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  policyNumber (string)
  latestSegmentLocator (ulid, required) — The last segment on the policy, based on issued transactions only
  contacts (ContactRoles[], required)
  statuses (Enum[], required)
  invoiceFeeAmount (number)
  anonymizedAt (datetime)
  coverageEndTime (datetime)
  moratoriumElections (map<string, string>, required)
  jurisdiction (string)
  producerCode (string)
  producerCodeOfRecord (string)
  proxyPayerLocator (ulid)
  static (map<string, object>, required)
  validationResult (ValidationResult)

PolicyListResponse
Properties:
  listCompleted (boolean, required)
  items (PolicyResponse[], required)

StaticDataUpdateRequest
Properties:
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ListPageResponseStaticDataHistoryResponse
Properties:
  listCompleted (boolean, required)
  items (StaticDataHistoryResponse[], required)

StaticDataHistoryResponse
Properties:
  historyLocator (ulid, required)
  staticData (map<string, object>, required)
  updatedBy (uuid, required)
  updatedAt (datetime, required)

PolicySnapshotListResponse
Properties:
  listCompleted (boolean, required)
  items (PolicySnapshotResponse[], required)

PolicySnapshotResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  productName (string, required)
  timezone (string, required)
  currency (string, required)
  region (string, required)
  transaction (TransactionSnapshotResponse, required)
  delinquencyPlanName (string)
  static (map<string, object>, required)

TransactionSnapshotResponse
Properties:
  locator (ulid, required)
  transactionCategory (Enum issuance | change | renewal | cancellation | reinstatement | reversal | aggregate, required)
  transactionType (string, required)
  effectiveTime (datetime, required)
  issuedTime (datetime, required)
  preferences (Preferences, required)
  segment (SegmentResponse, required)

UpdateBillingLevelRequest
Properties:
  billingLevel (Enum account | inherit | policy, required)

ContactRoles
Properties:
  contactLocator (ulid, required)
  roles (string[], required)

UpdateJurisdictionRequest
Properties:
  jurisdiction (string)

# Policy Holds API



Policy Holds are used to temporarily block policy transactions and to suspend the auto-renewal process.

<EndpointIndex
  names={[
  	'fetchEntityHold',
  	'createEntityHold',
  	'updateEntityHold',
  	'validateEntityHold',
  	'activateEntityHold',
  	'releaseEntityHold',
  	'discardEntityHold',
  	'fetchPolicyHolds',
  	'fetchQuoteHolds',
  ]}
/>

Fetch [#fetch]

Fetch Entity Hold [#fetch-entity-hold]

<ApiEndpoint name="fetchEntityHold" />

<ApiSchema name="EntityHold" />

Creation and Update [#creation-and-update]

Create Entity Hold [#create-entity-hold]

<ApiEndpoint name="createEntityHold" />

Update Entity Hold [#update-entity-hold]

<ApiEndpoint name="updateEntityHold" />

Execution [#execution]

Validate Entity Hold [#validate-entity-hold]

<ApiEndpoint name="validateEntityHold" />

Activate Entity Hold [#activate-entity-hold]

<ApiEndpoint name="activateEntityHold" />

Release and Discard [#release-and-discard]

Release Entity Hold [#release-entity-hold]

<ApiEndpoint name="releaseEntityHold" />

Discard Entity Hold [#discard-entity-hold]

<ApiEndpoint name="discardEntityHold" />

Entities [#entities]

<ApiSchema name="CreateEntityHoldRequest" />

<ApiSchema name="PolicyHoldScope" />

<ApiSchema name="QuoteHoldScope" />

<ApiSchema name="EntityHold" />

<ApiSchema name="UpdateEntityHoldRequest" />

Fetch Holds for a Policy or Quote [#fetch-holds-for-a-policy-or-quote]

Fetch Policy Holds [#fetch-policy-holds]

<ApiEndpoint name="fetchPolicyHolds" />

Fetch Quote Holds [#fetch-quote-holds]

<ApiEndpoint name="fetchQuoteHolds" />

See Also [#see-also]

* [Policy Holds Feature Guide](/features/policy-management/policy-holds)


## API Reference

GET /policy/{tenantLocator}/holds/{locator} — fetchEntityHold
Fetches an entity hold by its locator
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold — OK

PUT /policy/{tenantLocator}/holds — createEntityHold
Fetches all entity holds for the current user
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Request body (CreateEntityHoldRequest):
Responses:
  200 EntityHold — OK

PATCH /policy/{tenantLocator}/holds/{locator} — updateEntityHold
Updates an entity hold by its locator
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateEntityHoldRequest):
Responses:
  200 EntityHold — OK

PATCH /policy/{tenantLocator}/holds/{locator}/validate — validateEntityHold
Validates an entity hold by its locator
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold — OK

PATCH /policy/{tenantLocator}/holds/{locator}/activate — activateEntityHold
Activates an entity hold by its locator
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold — OK

PATCH /policy/{tenantLocator}/holds/{locator}/release — releaseEntityHold
Releases an entity hold by its locator
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold — OK

PATCH /policy/{tenantLocator}/holds/{locator}/discard — discardEntityHold
Discards an entity hold by its locator
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold — OK

GET /policy/{tenantLocator}/policies/{locator}/holds — fetchPolicyHolds
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold[] — OK

GET /policy/{tenantLocator}/quotes/{locator}/holds — fetchQuoteHolds
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold[] — OK

EntityHold
Properties:
  locator (ulid, required)
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy, required)
  state (Enum draft | validated | active | discarded | released, required)
  holdStaticData (boolean, required)
  description (string, required)
  quoteHoldScope (QuoteHoldScope, required)
  policyHoldScope (PolicyHoldScope, required)
  validationResult (ValidationResult)
  createdAt (datetime, required)
  createdBy (uuid, required)

CreateEntityHoldRequest
Properties:
  referenceType (Enum quote | policy, required)
  referenceLocator (ulid, required)
  description (string)
  quoteHoldScope (QuoteHoldScope)
  policyHoldScope (PolicyHoldScope)
  holdStaticData (boolean)

PolicyHoldScope
Properties:
  transactionCategory (Enum[], required)
  transactionType (string[], required)
  allowStaticData (boolean, required)

QuoteHoldScope
Properties:
  quoteState (Enum validated | underwritten | accepted | priced, required)

UpdateEntityHoldRequest
Properties:
  referenceType (Enum quote | policy, required)
  referenceLocator (ulid, required)
  description (string, required)
  holdStaticData (boolean, required)
  quoteHoldScope (QuoteHoldScope, required)
  policyHoldScope (PolicyHoldScope, required)
  referenceUpdate (boolean, required)

# Policy Terms API



<EndpointIndex
  names={[
  	'fetchTerm',
  	'fetchMultipleTerms',
  	'fetchTermPayableAmounts',
  	'fetchTermCharges',
  	'fetchTermSummaryByTermLocator',
  	'fetchTermSummaryByTermNumber',
  	'fetchTermsWithNumber',
  	'setTermNumber',
  	'generateTermNumber',
  ]}
  titles={{
  	fetchTerm: 'Fetch a Term',
  	fetchTermPayableAmounts: 'Fetch Payable Amounts for a Policy Term',
  }}
/>

Fetch [#fetch]

Fetch a Term [#fetch-a-term]

<ApiEndpoint name="fetchTerm" title="Fetch a Term" />

<ApiSchema name="TermResponse" />

Fetch Multiple Terms [#fetch-multiple-terms]

<ApiEndpoint name="fetchMultipleTerms" />

<ApiSchema name="TermListResponse" />

Fetch Payable Amounts for a Policy Term [#fetch-payable-amounts-for-a-policy-term]

<ApiEndpoint name="fetchTermPayableAmounts" title="Fetch Payable Amounts for a Policy Term" />

<ApiSchema name="TermPayableResponse" />

Fetch Term Charges [#fetch-term-charges]

<ApiEndpoint name="fetchTermCharges" />

Term Summaries [#term-summaries]

Term Summaries are views of the term based on issued transactions, showing in-force coverage only. This essentially flattens the transactions that affect the term into a single series of segments, such that the segments cover the entire term without overlaps or time periods without segments. This is useful to understand the state of the term without constructing it from the transaction stack.

Fetch Term Summary By Term Locator [#fetch-term-summary-by-term-locator]

<ApiEndpoint name="fetchTermSummaryByTermLocator" />

Fetch Term Summary By Term Number [#fetch-term-summary-by-term-number]

<ApiEndpoint name="fetchTermSummaryByTermNumber" />

<Callout>
  If the term has been created by a renewal transaction that is not yet issued, the <ApiLink name="TermSummary" /> will not contain any <ApiLink name="SubsegmentSummary">segments</ApiLink>.
</Callout>

<ApiSchema name="TermSummary" />

<ApiSchema name="SubsegmentSummary" />

<ApiSchema name="ElementSummary" />

<ApiSchema name="DocumentSummary" />

Numbering [#numbering]

Fetch Terms With Number [#fetch-terms-with-number]

<ApiEndpoint name="fetchTermsWithNumber" />

Set Term Number [#set-term-number]

<ApiEndpoint name="setTermNumber" />

Generate Term Number [#generate-term-number]

<ApiEndpoint name="generateTermNumber" />


## API Reference

GET /policy/{tenantLocator}/terms/{locator} — fetchTerm
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 TermResponse — OK

GET /policy/{tenantLocator}/policies/{locator}/terms/list — fetchMultipleTerms
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 TermListResponse — OK

GET /policy/{tenantLocator}/terms/{locator}/payable — fetchTermPayableAmounts
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 TermPayableResponse — OK

GET /policy/{tenantLocator}/terms/{locator}/charges — fetchTermCharges
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, PolicyChargeResponse[]> — OK

GET /policy/{tenantLocator}/terms/{locator}/summary — fetchTermSummaryByTermLocator
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 TermSummary — OK

GET /policy/{tenantLocator}/policies/{locator}/summary — fetchTermSummaryByTermNumber
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  termNumber (integer, query)
Responses:
  200 TermSummary — OK

GET /policy/{tenantLocator}/terms/numbers/{termNumber} — fetchTermsWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  termNumber (string, path, required)
Responses:
  200 TermResponse[] — OK

POST /policy/{tenantLocator}/terms/{locator}/number/set — setTermNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  termNumber (string, query, required)
Responses:
  200 TermResponse — OK

POST /policy/{tenantLocator}/terms/{locator}/number/generate — generateTermNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 TermResponse — OK

TermResponse
Properties:
  locator (ulid, required)
  staticLocator (ulid, required)
  policyLocator (ulid, required)
  number (integer, required)
  previousTermLocator (ulid)
  supersedesTermLocator (ulid)
  startTime (datetime, required)
  endTime (datetime, required)
  autoRenewalLocator (ulid)
  termNumber (string)

TermListResponse
Properties:
  listCompleted (boolean, required)
  items (TermResponse[], required)

TermPayableResponse
Properties:
  locator (ulid, required)
  staticLocator (ulid, required)
  policyLocator (ulid, required)
  number (integer, required)
  startTime (datetime, required)
  endTime (datetime, required)
  amount (number, required)

TermSummary
Properties:
  policyLocator (ulid, required)
  locator (ulid, required)
  staticLocator (ulid, required)
  termNumber (integer, required)
  startTime (datetime, required)
  endTime (datetime, required)
  duration (number, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  subsegments (SubsegmentSummary[], required)

SubsegmentSummary
Properties:
  locator (ulid, required)
  type (Enum coverage | gap, required)
  basedOn (ulid, required)
  startTime (datetime, required)
  endTime (datetime, required)
  duration (number, required)
  producerInfo (ProducerInfo)
  elements (ElementSummary[], required)
  documentSummary (DocumentSummary[], required)

ElementSummary
Properties:
  locator (ulid, required)
  staticLocator (ulid, required)
  type (string, required)
  data (map<string, object>, required)
  chargeSummaries (map<string, number>, required)

DocumentSummary
Properties:
  locator (ulid, required)
  name (string)
  staticName (string)
  documentInstanceState (Enum draft | dataReady | ready | dataError | renderError | conversionError | rendered | removed, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  state (Enum draft | dataReady | ready | dataError | renderError | conversionError | rendered | removed, required) [deprecated]

# Policy Transactions Schedules API



<EndpointIndex
  names={[
  	'getTransactionSchedules',
  	'getTransactionSchedule',
  	'getTransactionScheduleItem',
  	'downloadScheduleItemsCsv',
  	'downloadTransactionScheduleItemsCsv',
  	'uploadDeserializedTransactionSchedule',
  	'uploadTransactionSchedule',
  	'addTransactionSchedule',
  	'updateTransactionSchedule',
  	'deleteTransactionSchedule',
  ]}
  titles={{
  	getTransactionSchedules: 'Get Transaction Schedules',
  	getTransactionSchedule: 'Get a Transaction Schedule and Items',
  	getTransactionScheduleItem: 'Get a Transaction Schedule Item',
  	downloadScheduleItemsCsv: 'Download Quote Schedule Items',
  	downloadTransactionScheduleItemsCsv: 'Download Transaction Schedule Items',
  	uploadDeserializedTransactionSchedule:
  		'Upload Transaction Schedule Items for Deserialization',
  	uploadTransactionSchedule: 'Upload a CSV of Transaction Schedule Items',
  	addTransactionSchedule: 'Add Items to Transaction Schedule',
  	updateTransactionSchedule: 'Update a Transaction Schedule Item',
  	deleteTransactionSchedule: 'Delete an Item from Transaction Schedule',
  }}
/>

Fetch [#fetch]

Get Transaction Schedules [#get-transaction-schedules]

<ApiEndpoint name="getTransactionSchedules" title="Get Transaction Schedules" />

<ApiSchema name="ElementScheduleResponse" />

Get a Transaction Schedule and Items [#get-a-transaction-schedule-and-items]

<ApiEndpoint name="getTransactionSchedule" title="Get a Transaction Schedule and Items" />

<ApiSchema name="ScheduleItemsResponse" />

<ApiSchema name="ScheduleItem" />

Get a Transaction Schedule Item [#get-a-transaction-schedule-item]

<ApiEndpoint name="getTransactionScheduleItem" title="Get a Transaction Schedule Item" />

<ApiSchema name="ScheduleItem" />

Download Quote Schedule Items [#download-quote-schedule-items]

<ApiEndpoint name="downloadScheduleItemsCsv" title="Download Quote Schedule Items" />

Download Transaction Schedule Items [#download-transaction-schedule-items]

<ApiEndpoint name="downloadTransactionScheduleItemsCsv" title="Download Transaction Schedule Items" />

Update [#update]

Upload Transaction Schedule Items for Deserialization [#upload-transaction-schedule-items-for-deserialization]

<ApiEndpoint name="uploadDeserializedTransactionSchedule" title="Upload Transaction Schedule Items for Deserialization" />

<ApiSchema name="DeserializationResponse" />

Upload a CSV of Transaction Schedule Items [#upload-a-csv-of-transaction-schedule-items]

<ApiEndpoint name="uploadTransactionSchedule" title="Upload a CSV of Transaction Schedule Items" />

CSV for bulk upload of schedule items only supports flat item data structures,
meaning no nested objects in the schedule definition.

Add Items to Transaction Schedule [#add-items-to-transaction-schedule]

<ApiEndpoint name="addTransactionSchedule" title="Add Items to Transaction Schedule" />

<ApiSchema name="AddScheduleItemRequest" />

API requests to add items to a schedule are limited to 500 items

Update a Transaction Schedule Item [#update-a-transaction-schedule-item]

<ApiEndpoint name="updateTransactionSchedule" title="Update a Transaction Schedule Item" />

<ApiSchema name="PatchScheduleItemRequest" />

Delete an Item from Transaction Schedule [#delete-an-item-from-transaction-schedule]

<ApiEndpoint name="deleteTransactionSchedule" title="Delete an Item from Transaction Schedule" />

Delete individual items from a schedule by specifying their locator within the
string array of the request.

See Also [#see-also]

* [Schedules Feature Guide](/features/schedules)


## API Reference

GET /policy/{tenantLocator}/transactions/{locator}/schedules — getTransactionSchedules
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, ElementScheduleResponse> — OK

GET /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — getTransactionSchedule
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  lastSeenLocator (ulid, query)
Responses:
  200 ScheduleItemsResponse — OK

GET /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator}/{scheduleItemLocator} — getTransactionScheduleItem
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  scheduleItemLocator (ulid, path, required)
Responses:
  200 ScheduleItem — OK

GET /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator}/csv — downloadScheduleItemsCsv
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Responses:
  200 — OK

GET /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator}/csv — downloadTransactionScheduleItemsCsv
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Responses:
  200 — OK

POST /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator}/deserialize — uploadDeserializedTransactionSchedule
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  params (map<string, string>, query, required)
Responses:
  200 DeserializationResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — uploadTransactionSchedule
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Responses:
  200 ValidationResult — OK

PUT /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — addTransactionSchedule
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (AddScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — updateTransactionSchedule
Permissions: write, schedule-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (PatchScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/schedules/{staticElementLocator} — deleteTransactionSchedule
Permissions: write, schedule-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 — OK

ElementScheduleResponse
Properties:
  staticElementLocator (ulid, required)
  elementType (string, required)
  scheduleItemType (string, required)
  complexData (boolean, required)
  maxValidationErrors (integer, required)

ScheduleItemsResponse
Properties:
  items (ScheduleItem[], required)
  lastSeenLocator (ulid, required)

ScheduleItem
Properties:
  locator (ulid, required)
  staticElementLocator (ulid, required)
  type (string, required)
  data (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid, required)

DeserializationResponse
Properties:
  jobLocator (ulid, required)

AddScheduleItemRequest
Properties:
  data (map<string, object>, required)

PatchScheduleItemRequest
Properties:
  locator (ulid, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

# Policy Transactions API



<EndpointIndex
  names={[
  	'fetchTransaction',
  	'fetchPolicyTransactionWithUpdatedChanges',
  	'getTransactionsBranchesByPolicy',
  	'fetchTransactionSegment',
  	'fetchPolicySegment',
  	'fetchIssuedTransactions',
  	'createPolicyTransaction',
  	'changePolicy',
  	'renewPolicy',
  	'cancelPolicy',
  	'reinstatePolicy',
  	'reversePolicyChange',
  	'initializeTransaction',
  	'addElementsToPolicyWithTransaction',
  	'updateElementsInPolicyWithTransaction',
  	'removeElementsFromPolicyWithTransaction',
  	'createPolicyChangeInstruction',
  	'updateChangeInstruction',
  	'deleteChangeInstructionFromTransaction',
  	'validateTransaction',
  	'transactionValidatePreview',
  	'priceTransaction',
  	'fetchTransactionPricing',
  	'transactionPricePreview',
  	'underwriteTransaction',
  	'underwritePreview',
  	'updateUnderwritingFlagsForPolicyTransaction',
  	'fetchUnderwritingFlagsForTransaction',
  	'addApproveUnderwritingFlagsForTransaction',
  	'addDeclineUnderwritingFlagsForTransaction',
  	'addBlockUnderwritingFlagsForTransaction',
  	'addRejectUnderwritingFlagsForTransaction',
  	'addInfoUnderwritingFlagsForTransaction',
  	'clearApproveUnderwritingFlagsForTransaction',
  	'clearDeclineUnderwritingFlagsForTransaction',
  	'clearBlockUnderwritingFlagsForTransaction',
  	'clearRejectUnderwritingFlagsForTransaction',
  	'clearInfoUnderwritingFlagsForTransaction',
  	'acceptTransaction',
  	'issueTransaction',
  	'fetchPreferencesForATransaction',
  	'fetchAffectedTransactions',
  	'resetTransaction',
  	'refuseTransaction',
  	'discardTransaction',
  	'precommitTransaction',
  	'fetchAffectedTransactionsForListEndpoint',
  	'fetchTransactionSegments',
  	'fetchPolicySegmentEx',
  	'patchTransactionData',
  ]}
  titles={{
  	fetchTransaction: 'Fetch a Transaction',
  	getTransactionsBranchesByPolicy: 'Fetch Transaction Branches by Policy',
  	fetchTransactionSegment: 'Fetch Policy Segment for a Transaction',
  	fetchPolicySegment: 'Fetch a Policy Segment',
  	createPolicyTransaction: 'Create a Transaction',
  	changePolicy: 'Create a Policy Change Transaction',
  	renewPolicy: 'Create a Renewal Transaction',
  	cancelPolicy: 'Create a Cancellation Transaction',
  	reinstatePolicy: 'Create a Reinstatement Transaction',
  	reversePolicyChange: 'Create a Reversal Transaction',
  	createPolicyChangeInstruction: 'Add a Change Instruction to a Transaction',
  	updateChangeInstruction:
  		"Update One of a Transaction's Change Instructions",
  	deleteChangeInstructionFromTransaction:
  		'Delete a Change Instruction from a Transaction',
  	validateTransaction: 'Validate a Transaction',
  	transactionValidatePreview:
  		'Get a stateless validation preview for a hypothetical transaction',
  	priceTransaction: 'Price a Transaction',
  	fetchTransactionPricing: 'Fetch Pricing for a Transaction',
  	transactionPricePreview:
  		'Get a stateless price preview for a hypothetical transaction',
  	underwriteTransaction: 'Underwrite a Transaction',
  	underwritePreview:
  		'Get a stateless underwriting preview for a hypothetical transaction',
  	updateUnderwritingFlagsForPolicyTransaction:
  		"Update a Transaction's Underwriting Flags",
  	fetchUnderwritingFlagsForTransaction: 'Fetch Underwriting Flags',
  	addApproveUnderwritingFlagsForTransaction:
  		'Add Approve Level Underwriting Flag for Transaction',
  	addDeclineUnderwritingFlagsForTransaction:
  		'Add Decline Level Underwriting Flag for Transaction',
  	addBlockUnderwritingFlagsForTransaction:
  		'Add Block Level Underwriting Flag for Transaction',
  	addRejectUnderwritingFlagsForTransaction:
  		'Add Reject Level Underwriting Flag for Transaction',
  	addInfoUnderwritingFlagsForTransaction:
  		'Add Info Level Underwriting Flag for Transaction',
  	clearApproveUnderwritingFlagsForTransaction:
  		'Clear Approve Level Underwriting Flag for Transaction',
  	clearDeclineUnderwritingFlagsForTransaction:
  		'Clear Decline Level Underwriting Flag for Transaction',
  	clearBlockUnderwritingFlagsForTransaction:
  		'Clear Block Level Underwriting Flag for Transaction',
  	clearRejectUnderwritingFlagsForTransaction:
  		'Clear Reject Level Underwriting Flag for Transaction',
  	clearInfoUnderwritingFlagsForTransaction:
  		'Clear Info Level Underwriting Flag for Transaction',
  	acceptTransaction: 'Accept a Transaction',
  	issueTransaction: 'Issue a Transaction',
  	resetTransaction: 'Reset a Transaction',
  	refuseTransaction: 'Refuse a Transaction',
  	discardTransaction: 'Discard a Transaction',
  	precommitTransaction:
  		'Invoke the precommit plugin for a draft or initialized transaction',
  	patchTransactionData: 'Patch Transaction Data',
  }}
/>

Main Flow [#main-flow]

<Callout>
  For unissued transactions that are elible for issuance, you can attempt to advance to any subsequent state. If the transaction fails to validate, the response will be `HTTP 200`, but the transaction itself will not be in the requested new state. The actual state of the transaction will be included in the payload.
</Callout>

Fetch [#fetch]

Fetch a Transaction [#fetch-a-transaction]

<ApiEndpoint name="fetchTransaction" title="Fetch a Transaction" />

<ApiSchema name="PolicyTransactionResponse" />

<Callout>
  The `staticLocator` of the transaction equals the `locator` for the original version of a transaction. When transactions are reapplied, as in [out-of-sequence transactions](/features/policy-management/out-of-sequence-transactions), the `staticLocator` will equal the `staticLocator` of the transaction this it is based on.
</Callout>

<ApiSchema name="Preferences" />

<ApiSchema name="InstallmentPreferences" />

Fetch Policy Transaction With Updated Changes [#fetch-policy-transaction-with-updated-changes]

<ApiEndpoint name="fetchPolicyTransactionWithUpdatedChanges" />

Fetch Transaction Branches by Policy [#fetch-transaction-branches-by-policy]

<ApiEndpoint name="getTransactionsBranchesByPolicy" title="Fetch Transaction Branches by Policy" />

Fetch Policy Segment for a Transaction [#fetch-policy-segment-for-a-transaction]

<ApiEndpoint name="fetchTransactionSegment" title="Fetch Policy Segment for a Transaction" />

Fetch a Policy Segment [#fetch-a-policy-segment]

<ApiEndpoint name="fetchPolicySegment" title="Fetch a Policy Segment" />

<ApiSchema name="SegmentResponse" />

<ApiSchema name="ProducerInfo" />

Fetch Issued Transactions [#fetch-issued-transactions]

<ApiEndpoint name="fetchIssuedTransactions" />

<ApiSchema name="PolicyTransactionListResponse" />

Transaction Creation [#transaction-creation]

Create a Transaction [#create-a-transaction]

<ApiEndpoint name="createPolicyTransaction" title="Create a Transaction" />

Create a Policy Change Transaction [#create-a-policy-change-transaction]

<ApiEndpoint name="changePolicy" title="Create a Policy Change Transaction" />

Create a Renewal Transaction [#create-a-renewal-transaction]

<ApiEndpoint name="renewPolicy" title="Create a Renewal Transaction" />

Create a Cancellation Transaction [#create-a-cancellation-transaction]

<ApiEndpoint name="cancelPolicy" title="Create a Cancellation Transaction" />

Create a Reinstatement Transaction [#create-a-reinstatement-transaction]

<ApiEndpoint name="reinstatePolicy" title="Create a Reinstatement Transaction" />

<ApiSchema name="AddChangeInstructionCreateRequest" />

<ApiSchema name="ParamsChangeInstructionCreateRequest" />

<ApiSchema name="ModifyChangeInstructionCreateRequest" />

<ApiSchema name="DeleteChangeInstructionCreateRequest" />

<ApiSchema name="ProducersChangeInstructionCreateRequest" />

<ApiSchema name="MigrateChangeInstructionCreateRequest" />

<ApiSchema name="TransactionDataChangeInstructionCreateRequest" />

<ApiSchema name="ProxyPayerChangeInstructionRequest" />

<ApiSchema name="AddChangeInstructionResponse" />

<ApiSchema name="ModifyChangeInstructionResponse" />

<ApiSchema name="ParamsChangeInstructionResponse" />

<ApiSchema name="DeleteChangeInstructionResponse" />

<ApiSchema name="ProducersChangeInstructionResponse" />

<ApiSchema name="MigrateChangeInstructionResponse" />

<ApiSchema name="TransactionDataChangeInstructionResponse" />

Create a Reversal Transaction [#create-a-reversal-transaction]

<ApiEndpoint name="reversePolicyChange" title="Create a Reversal Transaction" />

<ApiSchema name="PolicyTransactionReversalRequest" />

Updating [#updating]

Initialize Transaction [#initialize-transaction]

<ApiEndpoint name="initializeTransaction" />

Add Elements To Policy With Transaction [#add-elements-to-policy-with-transaction]

<ApiEndpoint name="addElementsToPolicyWithTransaction" />

Update Elements In Policy With Transaction [#update-elements-in-policy-with-transaction]

<ApiEndpoint name="updateElementsInPolicyWithTransaction" />

Remove Elements From Policy With Transaction [#remove-elements-from-policy-with-transaction]

<ApiEndpoint name="removeElementsFromPolicyWithTransaction" />

Add a Change Instruction to a Transaction [#add-a-change-instruction-to-a-transaction]

<ApiEndpoint name="createPolicyChangeInstruction" title="Add a Change Instruction to a Transaction" />

Update One of a Transaction's Change Instructions [#update-one-of-a-transactions-change-instructions]

<ApiEndpoint name="updateChangeInstruction" title="Update One of a Transaction's Change Instructions" />

Delete a Change Instruction from a Transaction [#delete-a-change-instruction-from-a-transaction]

<ApiEndpoint name="deleteChangeInstructionFromTransaction" title="Delete a Change Instruction from a Transaction" />

<Callout>
  Transactions can only be updated when they are in `draft` state.
</Callout>

Validation [#validation]

Validate a Transaction [#validate-a-transaction]

<ApiEndpoint name="validateTransaction" title="Validate a Transaction" />

<ApiSchema name="ValidationResult" />

<ApiSchema name="ValidationItemResponse" />

Get a stateless validation preview for a hypothetical transaction [#get-a-stateless-validation-preview-for-a-hypothetical-transaction]

<ApiEndpoint name="transactionValidatePreview" title="Get a stateless validation preview for a hypothetical transaction" />

Pricing [#pricing]

Price a Transaction [#price-a-transaction]

<ApiEndpoint name="priceTransaction" title="Price a Transaction" />

Fetch Pricing for a Transaction [#fetch-pricing-for-a-transaction]

<ApiEndpoint name="fetchTransactionPricing" title="Fetch Pricing for a Transaction" />

<ApiSchema name="TransactionPriceResponse" />

<ApiSchema name="PolicyChargeResponse" />

Get a stateless price preview for a hypothetical transaction [#get-a-stateless-price-preview-for-a-hypothetical-transaction]

<ApiEndpoint name="transactionPricePreview" title="Get a stateless price preview for a hypothetical transaction" />

<span id="policyTransactionUnderwritingApi" />

Underwriting [#underwriting]

Underwrite a Transaction [#underwrite-a-transaction]

<ApiEndpoint name="underwriteTransaction" title="Underwrite a Transaction" />

<ApiSchema name="TransactionUnderwritingResponse" />

Get a stateless underwriting preview for a hypothetical transaction [#get-a-stateless-underwriting-preview-for-a-hypothetical-transaction]

<ApiEndpoint name="underwritePreview" title="Get a stateless underwriting preview for a hypothetical transaction" />

Underwriting Flags [#underwriting-flags]

Update a Transaction's Underwriting Flags [#update-a-transactions-underwriting-flags]

<ApiEndpoint name="updateUnderwritingFlagsForPolicyTransaction" title="Update a Transaction's Underwriting Flags" />

Fetch Underwriting Flags [#fetch-underwriting-flags]

<ApiEndpoint name="fetchUnderwritingFlagsForTransaction" title="Fetch Underwriting Flags" />

<ApiSchema name="TransactionUnderwritingFlagsResponse" />

<ApiSchema name="UnderwritingFlagResponse" />

Add Approve Level Underwriting Flag for Transaction [#add-approve-level-underwriting-flag-for-transaction]

<ApiEndpoint name="addApproveUnderwritingFlagsForTransaction" title="Add Approve Level Underwriting Flag for Transaction" />

Add Decline Level Underwriting Flag for Transaction [#add-decline-level-underwriting-flag-for-transaction]

<ApiEndpoint name="addDeclineUnderwritingFlagsForTransaction" title="Add Decline Level Underwriting Flag for Transaction" />

Add Block Level Underwriting Flag for Transaction [#add-block-level-underwriting-flag-for-transaction]

<ApiEndpoint name="addBlockUnderwritingFlagsForTransaction" title="Add Block Level Underwriting Flag for Transaction" />

Add Reject Level Underwriting Flag for Transaction [#add-reject-level-underwriting-flag-for-transaction]

<ApiEndpoint name="addRejectUnderwritingFlagsForTransaction" title="Add Reject Level Underwriting Flag for Transaction" />

Add Info Level Underwriting Flag for Transaction [#add-info-level-underwriting-flag-for-transaction]

<ApiEndpoint name="addInfoUnderwritingFlagsForTransaction" title="Add Info Level Underwriting Flag for Transaction" />

Clear Approve Level Underwriting Flag for Transaction [#clear-approve-level-underwriting-flag-for-transaction]

<ApiEndpoint name="clearApproveUnderwritingFlagsForTransaction" title="Clear Approve Level Underwriting Flag for Transaction" />

Clear Decline Level Underwriting Flag for Transaction [#clear-decline-level-underwriting-flag-for-transaction]

<ApiEndpoint name="clearDeclineUnderwritingFlagsForTransaction" title="Clear Decline Level Underwriting Flag for Transaction" />

Clear Block Level Underwriting Flag for Transaction [#clear-block-level-underwriting-flag-for-transaction]

<ApiEndpoint name="clearBlockUnderwritingFlagsForTransaction" title="Clear Block Level Underwriting Flag for Transaction" />

Clear Reject Level Underwriting Flag for Transaction [#clear-reject-level-underwriting-flag-for-transaction]

<ApiEndpoint name="clearRejectUnderwritingFlagsForTransaction" title="Clear Reject Level Underwriting Flag for Transaction" />

Clear Info Level Underwriting Flag for Transaction [#clear-info-level-underwriting-flag-for-transaction]

<ApiEndpoint name="clearInfoUnderwritingFlagsForTransaction" title="Clear Info Level Underwriting Flag for Transaction" />

Acceptance [#acceptance]

Accept a Transaction [#accept-a-transaction]

<ApiEndpoint name="acceptTransaction" title="Accept a Transaction" />

Issuance [#issuance]

Issue a Transaction [#issue-a-transaction]

<ApiEndpoint name="issueTransaction" title="Issue a Transaction" />

Documents [#documents]

Fetch Documents For Transaction [#fetch-documents-for-transaction]

<ApiEndpoint name="fetchDocumentsForTransaction" />

Fetch Documents For Segment [#fetch-documents-for-segment]

<ApiEndpoint name="fetchDocumentsForSegment" />

<ApiSchema name="DocumentInstanceResponse" />

Transaction Details [#transaction-details]

Fetch Preferences For A Transaction [#fetch-preferences-for-a-transaction]

<ApiEndpoint name="fetchPreferencesForATransaction" />

Fetch Affected Transactions [#fetch-affected-transactions]

<ApiEndpoint name="fetchAffectedTransactions" />

<ApiSchema name="AffectedTransaction" />

Atypical States and Operations [#atypical-states-and-operations]

Reset a Transaction [#reset-a-transaction]

<ApiEndpoint name="resetTransaction" title="Reset a Transaction" />

<ApiSchema name="ResetOptions" />

<Callout>
  If the query parameter `resetToDraft` is `true`, then the transaction will revert to `draft` state and the generated segment data, including elements and data, will be discarded. If `false` (the default), then the transaction will revert to `initialized` state and the segment data will be retained. This is useful to preserve the locator data for generated elements.
</Callout>

Refuse a Transaction [#refuse-a-transaction]

<ApiEndpoint name="refuseTransaction" title="Refuse a Transaction" />

Discard a Transaction [#discard-a-transaction]

<ApiEndpoint name="discardTransaction" title="Discard a Transaction" />

Invoke the precommit plugin for a draft or initialized transaction [#invoke-the-precommit-plugin-for-a-draft-or-initialized-transaction]

<ApiEndpoint name="precommitTransaction" title="Invoke the precommit plugin for a draft or initialized transaction" />

Deprecated Items [#deprecated-items]

Fetch Affected Transactions For List Endpoint [#fetch-affected-transactions-for-list-endpoint]

<ApiEndpoint name="fetchAffectedTransactionsForListEndpoint" />

Fetch Transaction Segments [#fetch-transaction-segments]

<ApiEndpoint name="fetchTransactionSegments" />

Fetch Policy Segment Ex [#fetch-policy-segment-ex]

<ApiEndpoint name="fetchPolicySegmentEx" />

Transaction Data [#transaction-data]

<ApiEndpoint name="patchTransactionData" />

<ApiSchema name="PatchTransactionDataRequest" />


## API Reference

GET /policy/{tenantLocator}/transactions/{locator} — fetchTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

GET /policy/{tenantLocator}/transactions/{locator}/elements/changes — fetchPolicyTransactionWithUpdatedChanges
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

GET /policy/{tenantLocator}/policies/{locator}/branches — getTransactionsBranchesByPolicy
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, PolicyTransactionResponse[]> — OK

GET /policy/{tenantLocator}/transactions/{locator}/segment — fetchTransactionSegment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 SegmentResponse — OK

GET /policy/{tenantLocator}/transactions/segments/{segmentLocator} — fetchPolicySegment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  segmentLocator (ulid, path, required)
Responses:
  200 SegmentResponse — OK

GET /policy/{tenantLocator}/policies/{locator}/issuedTransactions/list — fetchIssuedTransactions
Fetches the 'local stack' of issued transactions, excluding those that have been reversed or reapplied
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 PolicyTransactionListResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/{transactionType} — createPolicyTransaction
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  transactionType (string, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/change — changePolicy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/renew — renewPolicy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/cancel — cancelPolicy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  baseLocator (ulid, query)
Request body (ParamsChangeInstructionCreateRequest):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/reinstate — reinstatePolicy
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/reversal — reversePolicyChange
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (PolicyTransactionReversalRequest):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/initialize — initializeTransaction
Permissions: write, initialize
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

PUT /policy/{tenantLocator}/transactions/{locator}/elements — addElementsToPolicyWithTransaction
Permissions: write, elements-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ElementCreateRequest[]):
Responses:
  200 SegmentResponse[] — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/elements — updateElementsInPolicyWithTransaction
Permissions: write, elements-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ElementUpdateRequest):
Responses:
  200 SegmentResponse[] — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/elements — removeElementsFromPolicyWithTransaction
Permissions: write, elements-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 SegmentResponse[] — OK

PUT /policy/{tenantLocator}/transactions/{locator}/changeInstructions — createPolicyChangeInstruction
Permissions: write, change-instruction-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/changeInstructions/{instructionLocator} — updateChangeInstruction
Permissions: write, change-instruction-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  instructionLocator (ulid, path, required)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>):
Responses:
  200 PolicyTransactionResponse — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/changeInstructions/{instructionLocator} — deleteChangeInstructionFromTransaction
Permissions: write, change-instruction-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  instructionLocator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/validate — validateTransaction
Permissions: write, validate
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  stateless (boolean, query)
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/{transactionType}/validatePreview — transactionValidatePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  transactionType (string, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/price — priceTransaction
Permissions: write, price
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  stateless (boolean, query)
Responses:
  200 TransactionPriceResponse — OK

GET /policy/{tenantLocator}/transactions/{locator}/price — fetchTransactionPricing
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 TransactionPriceResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/{transactionType}/pricePreview — transactionPricePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  transactionType (string, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 TransactionPriceResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/underwrite — underwriteTransaction
Permissions: write, underwrite
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  stateless (boolean, query)
Responses:
  200 TransactionUnderwritingResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/{transactionType}/underwritePreview — underwritePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  transactionType (string, path, required)
  baseLocator (ulid, query)
Request body (oneOf<AddChangeInstructionCreateRequest,DeleteChangeInstructionCreateRequest,MigrateChangeInstructionCreateRequest,ModifyChangeInstructionCreateRequest,ParamsChangeInstructionCreateRequest,ProducersChangeInstructionCreateRequest,ProxyPayerChangeInstructionRequest,TransactionDataChangeInstructionCreateRequest>[]):
Responses:
  200 TransactionUnderwritingResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/underwritingFlags — updateUnderwritingFlagsForPolicyTransaction
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagsUpdateRequest):
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

GET /policy/{tenantLocator}/transactions/{locator}/underwritingFlags — fetchUnderwritingFlagsForTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/approve — addApproveUnderwritingFlagsForTransaction
Permissions: write, approve-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/decline — addDeclineUnderwritingFlagsForTransaction
Permissions: write, decline-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/block — addBlockUnderwritingFlagsForTransaction
Permissions: write, block-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/reject — addRejectUnderwritingFlagsForTransaction
Permissions: write, reject-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/info — addInfoUnderwritingFlagsForTransaction
Permissions: write, info-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/approve/{flagLocator} — clearApproveUnderwritingFlagsForTransaction
Permissions: write, approve-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/decline/{flagLocator} — clearDeclineUnderwritingFlagsForTransaction
Permissions: write, decline-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/block/{flagLocator} — clearBlockUnderwritingFlagsForTransaction
Permissions: write, block-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/reject/{flagLocator} — clearRejectUnderwritingFlagsForTransaction
Permissions: write, reject-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/transactions/{locator}/underwritingFlags/info/{flagLocator} — clearInfoUnderwritingFlagsForTransaction
Permissions: write, info-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 TransactionUnderwritingFlagsResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/accept — acceptTransaction
Permissions: write, accept
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/issue — issueTransaction
Permissions: write, issue
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  autoRebase (boolean, query)
Responses:
  200 PolicyTransactionResponse — OK

GET /document/{tenantLocator}/documents/transaction/{locator}/list — fetchDocumentsForTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

GET /document/{tenantLocator}/documents/segment/{locator}/list — fetchDocumentsForSegment
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

GET /policy/{tenantLocator}/transactions/{locator}/preferences — fetchPreferencesForATransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 Preferences — OK

GET /policy/{tenantLocator}/transactions/{locator}/affectedTransactions — fetchAffectedTransactions
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AffectedTransaction[] — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/reset — resetTransaction
Permissions: write, reset
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  resetToDraft (boolean, query)
Request body (ResetOptions):
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/refuse — refuseTransaction
Permissions: write, refuse
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/discard — discardTransaction
Permissions: write, discard
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/precommit — precommitTransaction
Permissions: write, precommit
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyTransactionResponse — OK

GET /policy/{tenantLocator}/transactions/{locator}/affectedTransactions/list — fetchAffectedTransactionsForListEndpoint
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AffectedTransaction[] — OK

GET /policy/{tenantLocator}/transactions/{locator}/segments/list — fetchTransactionSegments
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 SegmentResponse[] — OK

GET /policy/{tenantLocator}/transactions/{locator}/segments/{segmentLocator} — fetchPolicySegmentEx
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  segmentLocator (ulid, path, required)
Responses:
  200 SegmentResponse — OK

PATCH /policy/{tenantLocator}/transactions/{locator}/transactionData — patchTransactionData
Permissions: write, transaction-data-patch
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (PatchTransactionDataRequest):
Responses:
  200 PolicyTransactionResponse — OK

PolicyTransactionResponse
Properties:
  locator (ulid, required)
  transactionCategory (Enum issuance | change | renewal | cancellation | reinstatement | reversal | aggregate, required)
  transactionState (Enum draft | initialized | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded | invalidated | reversed, required)
  underwritingStatus (string)
  policyLocator (ulid, required)
  baseTransactionLocator (ulid)
  aggregateTransactionLocator (ulid)
  createdAt (datetime, required)
  createdBy (uuid, required)
  validationResult (ValidationResult)
  changeInstructions (oneOf<AddChangeInstructionResponse,DeleteChangeInstructionResponse,ModifyChangeInstructionResponse,ParamsChangeInstructionResponse,ProducersChangeInstructionResponse,MigrateChangeInstructionResponse,TransactionDataChangeInstructionResponse>[])
  effectiveTime (datetime, required)
  aggregatedTransactions (PolicyTransactionResponse[])
  termLocator (ulid, required)
  preferences (Preferences)
  transactionType (string, required)
  issuedTime (datetime)
  acceptedTime (datetime)
  reapplicationOfLocator (ulid)
  maskingLevel (Enum none | level1 | level2)
  anonymizedAt (datetime)
  staticLocator (ulid, required) — Equals the locator of the first transaction this is based on.
  expirationTime (datetime)
  data (map<string, object>, required)

Preferences
Properties:
  installmentPreferences (InstallmentPreferences)

InstallmentPreferences
Properties:
  cadence (Enum none | fullPay | weekly | everyOtherWeek | monthly | quarterly | semiannually | annually | thirtyDays | everyNDays)
  anchorMode (Enum generateDay | termStartDay | dueDay)
  generateLeadDays (integer)
  dueLeadDays (integer)
  installmentWeights (number[], required)
  maxInstallmentsPerTerm (integer)
  installmentPlanName (string)
  anchorType (Enum none | dayOfMonth | anchorTime | dayOfWeek | weekOfMonth)
  dayOfMonth (integer)
  dayOfWeek (Enum monday | tuesday | wednesday | thursday | friday | saturday | sunday)
  weekOfMonth (Enum none | first | second | third | fourth | fifth)
  anchorTime (datetime)
  autopayLeadDays (number)

SegmentResponse
Properties:
  locator (ulid, required)
  transactionLocator (ulid, required)
  segmentType (Enum coverage | gap, required)
  startTime (datetime, required)
  endTime (datetime, required)
  element (ElementResponse, required) — The root element in the hierarchy
  duration (number, required)
  basedOn (ulid)
  anonymizedAt (datetime)
  producerInfo (ProducerInfo)
  proxyPayerLocator (ulid)

ProducerInfo
Properties:
  producerCode (string)
  producerCodeOfRecord (string)

PolicyTransactionListResponse
Properties:
  listCompleted (boolean, required)
  items (PolicyTransactionResponse[], required)

AddChangeInstructionCreateRequest
Properties:
  action (Enum add, required)
  elements (ElementCreateRequest[], required)

ParamsChangeInstructionCreateRequest
Properties:
  action (Enum params, required)
  effectiveTime (datetime, required)
  newPolicyEndTime (datetime)
  preferences (Preferences)
  billingModeChange (boolean) [deprecated] — Use triggerBillingChange instead.
  triggerBillingChange (boolean)
  inheritSettings (boolean) [deprecated]
  expirationTime (datetime)

ModifyChangeInstructionCreateRequest
Properties:
  action (Enum modify, required)
  staticLocator (ulid, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  setCoverageTerms (map<string, object>, required)
  removeCoverageTerms (map<string, object>, required)

DeleteChangeInstructionCreateRequest
Properties:
  action (Enum delete, required)
  staticElementLocators (ulid[], required)

ProducersChangeInstructionCreateRequest
Properties:
  action (Enum producers, required)
  setProducerCode (string)
  clearProducerCode (boolean)
  setProducerCodeOfRecord (string)
  revertProducerCodeOfRecord (boolean)

MigrateChangeInstructionCreateRequest
Properties:
  action (Enum migrate, required)
  configVersionLocator (ulid)

TransactionDataChangeInstructionCreateRequest
Properties:
  action (Enum transactionData, required)
  data (map<string, object>, required) — Policy transaction extension data can only be associated with a named policy transaction

ProxyPayerChangeInstructionRequest
Properties:
  action (Enum proxyPayer, required)
  setProxyPayerLocator (ulid)
  clearProxyPayerLocator (boolean)

AddChangeInstructionResponse
Properties:
  action (Enum add, required)
  elements (ElementCreateRequest[], required)
  transactionConflictResolution (Enum elidedInstruction, required)
  locator (ulid, required)

ModifyChangeInstructionResponse
Properties:
  action (Enum modify, required)
  staticLocator (ulid, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  setCoverageTerms (map<string, object>, required)
  removeCoverageTerms (map<string, object>, required)
  transactionConflictResolution (Enum elidedInstruction, required)
  locator (ulid, required)

ParamsChangeInstructionResponse
Properties:
  action (Enum params, required)
  effectiveTime (datetime, required)
  newPolicyEndTime (datetime)
  preferences (Preferences)
  billingModeChange (boolean) [deprecated] — Use triggerBillingChange instead.
  triggerBillingChange (boolean)
  inheritSettings (boolean) [deprecated]
  expirationTime (datetime)
  locator (ulid, required)

DeleteChangeInstructionResponse
Properties:
  action (Enum delete, required)
  staticElementLocators (ulid[], required)
  locator (ulid, required)

ProducersChangeInstructionResponse
Properties:
  action (Enum producers, required)
  setProducerCode (string)
  clearProducerCode (boolean)
  setProducerCodeOfRecord (string)
  revertProducerCodeOfRecord (boolean)
  locator (ulid, required)

MigrateChangeInstructionResponse
Properties:
  action (Enum migrate, required)
  configVersionLocator (ulid)
  locator (ulid, required)

TransactionDataChangeInstructionResponse
Properties:
  action (Enum transactionData, required)
  data (map<string, object>, required) — Policy transaction extension data can only be associated with a named policy transaction
  locator (ulid, required)

PolicyTransactionReversalRequest
Properties:
  toTransaction (ulid, required)
  reverseTransactions (ulid[], required)
  baseLocator (ulid)

ValidationResult
Properties:
  validationItems (ValidationItemResponse[])
  success (boolean, required)

ValidationItemResponse
Properties:
  elementType (string, required)
  locator (ulid, required)
  errors (string[], required)

TransactionPriceResponse
Properties:
  locator (ulid, required)
  policyLocator (ulid, required)
  transactionCategory (Enum issuance | change | renewal | cancellation | reinstatement | reversal | aggregate, required)
  transactionState (Enum draft | initialized | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded | invalidated | reversed, required)
  effectiveTime (datetime, required)
  charges (PolicyChargeResponse[], required)
  aggregatedTransactions (TransactionPriceResponse[])
  validationResult (ValidationResult)

PolicyChargeResponse
Properties:
  locator (ulid, required)
  elementLocator (ulid, required)
  chargeType (string, required)
  chargeCategory (Enum none | premium | tax | fee | credit | invoiceFee | cededPremium | nonFinancial | surcharge, required)
  amount (number, required)
  rate (number, required)
  referenceRate (number, required)
  tag (string)
  rateDifference (number)
  elementStaticLocator (ulid, required)
  reversalOfLocator (ulid)
  handling (Enum flat | normal | retention, required)
  invoicing (Enum scheduled | next | immediate, required)

TransactionUnderwritingResponse
Properties:
  locator (ulid, required)
  policyLocator (ulid, required)
  transactionCategory (Enum issuance | change | renewal | cancellation | reinstatement | reversal | aggregate, required)
  transactionState (Enum draft | initialized | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded | invalidated | reversed, required)
  effectiveTime (datetime, required)
  underwritingStatus (string, required)
  underwritingFlags (UnderwritingFlagResponse[])
  aggregatedTransactions (TransactionUnderwritingResponse[])
  validationResult (ValidationResult)

TransactionUnderwritingFlagsResponse
Properties:
  transactionLocator (ulid, required)
  flags (UnderwritingFlagResponse[], required)
  clearedFlags (UnderwritingFlagResponse[], required)

UnderwritingFlagResponse
Properties:
  locator (ulid, required)
  level (Enum info | block | decline | reject | approve, required)
  referenceType (Enum quote | transaction, required)
  referenceLocator (ulid, required)
  note (string, required)
  tag (string, required)
  elementLocator (ulid)
  createdBy (uuid, required)
  createdTime (datetime, required)
  clearedBy (uuid, required)
  clearedTime (datetime, required)
  taskCreationResponse (TaskCreationResponse, required)

DocumentInstanceResponse
Properties:
  locator (ulid, required)
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  referenceDocumentLocator (ulid)
  transactionLocator (ulid)
  segmentLocator (ulid)
  termLocator (ulid)
  policyLocator (ulid)
  name (string)
  staticName (string)
  documentInstanceState (Enum draft | dataReady | ready | dataError | renderError | conversionError | rendered | removed, required)
  documentFormat (Enum csv | doc | docx | html | jpeg | jpg | pdf | text | txt | xls | xlsx | zip, required)
  metadata (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid)
  readyAt (datetime)
  renderingData (map<string, object>, required)
  processingErrors (string)
  external (boolean, required)
  category (string)
  consolidatedFrom (ulid[], required)
  consolidatedTo (ulid[], required)
  copyOnIssuance (boolean)

AffectedTransaction
Properties:
  locator (ulid, required)
  action (Enum reversed | invalidated, required)

ResetOptions
Properties:
  resetAllUnderwritingFlags (boolean, required)
  resetFlags (ulid[], required)
  resetFlagsAction (Enum clear | delete, required)
  deleteAllAutomaticDocuments (boolean, required)
  discardSchedules (boolean, required)
  resetLockedResources (boolean, required)
  deleteDocuments (ulid[], required)

PatchTransactionDataRequest
Properties:
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

# Renewal Management and Auto-Renewal API



<EndpointIndex
  names={[
  	'fetchAutoRenewal',
  	'createAutoRenewal',
  	'updateAutoRenewal',
  	'putAutoRenewal',
  	'markPolicyForDoNotRenew',
  	'reactivateAutoRenewal',
  	'discardAutoRenewal',
  	'updatePolicyAutoRenewalPlan',
  	'updateQuoteAutoRenewalPlan',
  ]}
/>

Fetch [#fetch]

Fetch Auto Renewal [#fetch-auto-renewal]

<ApiEndpoint name="fetchAutoRenewal" />

<ApiSchema name="AutoRenewalResponse" />

Create [#create]

Create Auto Renewal [#create-auto-renewal]

<ApiEndpoint name="createAutoRenewal" />

<ApiSchema name="AutoRenewalCreateRequest" />

Update [#update]

Update Auto Renewal [#update-auto-renewal]

<ApiEndpoint name="updateAutoRenewal" />

<ApiSchema name="AutoRenewalUpdateRequest" />

Put Auto Renewal [#put-auto-renewal]

<ApiEndpoint name="putAutoRenewal" />

<ApiSchema name="AutoRenewalPutRequest" />

Mark Policy For Do Not Renew [#mark-policy-for-do-not-renew]

<ApiEndpoint name="markPolicyForDoNotRenew" />

Reactivate Auto Renewal [#reactivate-auto-renewal]

<ApiEndpoint name="reactivateAutoRenewal" />

Discard Auto Renewal [#discard-auto-renewal]

<ApiEndpoint name="discardAutoRenewal" />

Plan Updates [#plan-updates]

Update Policy Auto Renewal Plan [#update-policy-auto-renewal-plan]

<ApiEndpoint name="updatePolicyAutoRenewalPlan" />

Update Quote Auto Renewal Plan [#update-quote-auto-renewal-plan]

<ApiEndpoint name="updateQuoteAutoRenewalPlan" />

<ApiSchema name="AutoRenewalPlanUpdateRequest" />

See Also [#see-also]

* [Renewal Management and Auto-Renewal Feature Guide](/features/policy-management/renewal-management)
* <ApiLink name="AutoRenewalPlanRef">
    Configuration
  </ApiLink>


## API Reference

GET /policy/{tenantLocator}/autoRenewals/{locator} — fetchAutoRenewal
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AutoRenewalResponse — OK

POST /policy/{tenantLocator}/autoRenewals — createAutoRenewal
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (AutoRenewalCreateRequest):
Responses:
  200 AutoRenewalResponse — OK

PATCH /policy/{tenantLocator}/autoRenewals/{locator} — updateAutoRenewal
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (AutoRenewalUpdateRequest):
Responses:
  200 AutoRenewalResponse — OK

PUT /policy/{tenantLocator}/autoRenewals/{locator} — putAutoRenewal
Creates or replaces *all* the specified data on the auto renewal, including null values.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (AutoRenewalPutRequest):
Responses:
  200 AutoRenewalResponse — OK

PATCH /policy/{tenantLocator}/autoRenewals/{locator}/doNotRenew — markPolicyForDoNotRenew
Prevents renewal of the policy, either with auto-renew or manually.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AutoRenewalResponse — OK

PATCH /policy/{tenantLocator}/autoRenewals/{locator}/activate — reactivateAutoRenewal
Restarts autorenewal when it has been previously put into doNotRenew, error, or terminated state.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AutoRenewalResponse — OK

PATCH /policy/{tenantLocator}/autoRenewals/{locator}/discard — discardAutoRenewal
Discards and prevents auto renewal unless a new one is created.
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 AutoRenewalResponse — OK

PATCH /policy/{tenantLocator}/policies/{locator}/autoRenewalPlan — updatePolicyAutoRenewalPlan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (AutoRenewalPlanUpdateRequest):
Responses:
  200 PolicyResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/autoRenewalPlan — updateQuoteAutoRenewalPlan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (AutoRenewalPlanUpdateRequest):
Responses:
  200 QuoteResponse — OK

AutoRenewalResponse
Properties:
  locator (ulid, required)
  autoRenewalState (Enum active | discarded | doNotRenew | issued | error | terminated | invalidated, required)
  policyLocator (ulid, required)
  termLocator (ulid, required)
  renewalTransactionType (string, required)
  renewalTransactionLocator (ulid)
  renewalTransactionCreateTime (datetime)
  renewalTransactionCreatedTime (datetime)
  renewalTransactionAcceptTime (datetime)
  renewalTransactionAcceptedTime (datetime)
  renewalTransactionIssueTime (datetime)
  renewalTransactionIssuedTime (datetime)
  newTermDuration (integer)
  validationResult (ValidationResult)

AutoRenewalCreateRequest
Properties:
  termLocator (ulid, required)
  policyLocator (ulid, required)
  autoRenewalState (Enum active | discarded | doNotRenew | issued | error | terminated | invalidated)
  renewalTransactionType (string)
  newTermDuration (integer)
  renewalTransactionCreateTime (datetime, required)
  renewalTransactionAcceptTime (datetime)
  renewalTransactionIssueTime (datetime)
  renewalTransactionLocator (ulid)

AutoRenewalUpdateRequest
Properties:
  renewalTransactionType (string)
  newTermDuration (integer)
  renewalTransactionCreateTime (datetime)
  renewalTransactionAcceptTime (datetime)
  renewalTransactionIssueTime (datetime)
  renewalTransactionLocator (ulid)

AutoRenewalPutRequest
Properties:
  renewalTransactionType (string)
  newTermDuration (integer)
  renewalTransactionCreateTime (datetime, required)
  renewalTransactionAcceptTime (datetime)
  renewalTransactionIssueTime (datetime)
  renewalTransactionLocator (ulid)

AutoRenewalPlanUpdateRequest
Properties:
  autoRenewalPlanName (string, required)

# Quotes Schedules API



<EndpointIndex
  names={[
  	'fetchSchedules',
  	'fetchScheduleItems',
  	'fetchScheduleItem',
  	'uploadDeserializedScheduleItems',
  	'uploadScheduleItems',
  	'addScheduleItems',
  	'updateScheduleItems',
  	'deleteScheduleItems',
  ]}
  titles={{
  	fetchSchedules: 'Fetch Quote Schedules',
  	fetchScheduleItems: 'Fetch a Quote Schedule and Items',
  	fetchScheduleItem: 'Fetch a Quote Schedule Item',
  	uploadDeserializedScheduleItems:
  		'Upload Quote Schedule Items for Deserialization',
  	uploadScheduleItems: 'Upload a CSV of Quote Schedule Items',
  	addScheduleItems: 'Add Items to Quote Schedule',
  	updateScheduleItems: 'Update a Quote Schedule Item',
  	deleteScheduleItems: 'Delete an Item From Quote Schedule',
  }}
/>

Fetch [#fetch]

Fetch Quote Schedules [#fetch-quote-schedules]

<ApiEndpoint name="fetchSchedules" title="Fetch Quote Schedules" />

<ApiSchema name="ElementScheduleResponse" />

Fetch a Quote Schedule and Items [#fetch-a-quote-schedule-and-items]

<ApiEndpoint name="fetchScheduleItems" title="Fetch a Quote Schedule and Items" />

<ApiSchema name="ScheduleItemsResponse" />

Fetch a Quote Schedule Item [#fetch-a-quote-schedule-item]

<ApiEndpoint name="fetchScheduleItem" title="Fetch a Quote Schedule Item" />

<ApiSchema name="ScheduleItem" />

Update [#update]

Upload Quote Schedule Items for Deserialization [#upload-quote-schedule-items-for-deserialization]

<ApiEndpoint name="uploadDeserializedScheduleItems" title="Upload Quote Schedule Items for Deserialization" />

<ApiSchema name="DeserializationResponse" />

Upload a CSV of Quote Schedule Items [#upload-a-csv-of-quote-schedule-items]

<ApiEndpoint name="uploadScheduleItems" title="Upload a CSV of Quote Schedule Items" />

CSV for bulk upload of schedule items only supports flat item data structures,
meaning no nested objects in the schedule definition.

Add Items to Quote Schedule [#add-items-to-quote-schedule]

<ApiEndpoint name="addScheduleItems" title="Add Items to Quote Schedule" />

<ApiSchema name="AddScheduleItemRequest" />

<ApiSchema name="ScheduleItem" />

API requests to add items to a schedule are limited to 500 items

Update a Quote Schedule Item [#update-a-quote-schedule-item]

<ApiEndpoint name="updateScheduleItems" title="Update a Quote Schedule Item" />

<ApiSchema name="PatchScheduleItemRequest" />

Delete an Item From Quote Schedule [#delete-an-item-from-quote-schedule]

<ApiEndpoint name="deleteScheduleItems" title="Delete an Item From Quote Schedule" />

Delete individual items from a schedule by specifying their locator within the
string array of the request.

See Also [#see-also]

* [Schedules Feature Guide](/features/schedules)


## API Reference

GET /policy/{tenantLocator}/quotes/{locator}/schedules — fetchSchedules
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, ElementScheduleResponse> — OK

GET /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — fetchScheduleItems
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  lastSeenLocator (ulid, query)
Responses:
  200 ScheduleItemsResponse — OK

GET /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator}/{scheduleItemLocator} — fetchScheduleItem
Permissions: read, schedule-read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  scheduleItemLocator (ulid, path, required)
Responses:
  200 ScheduleItem — OK

POST /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator}/deserialize — uploadDeserializedScheduleItems
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
  params (map<string, string>, query, required)
Responses:
  200 DeserializationResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — uploadScheduleItems
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Responses:
  200 ValidationResult — OK

PUT /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — addScheduleItems
Permissions: write, schedule-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (AddScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — updateScheduleItems
Permissions: write, schedule-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (PatchScheduleItemRequest[]):
Responses:
  200 ValidationResult — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/schedules/{staticElementLocator} — deleteScheduleItems
Permissions: write, schedule-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  staticElementLocator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 — OK

ElementScheduleResponse
Properties:
  staticElementLocator (ulid, required)
  elementType (string, required)
  scheduleItemType (string, required)
  complexData (boolean, required)
  maxValidationErrors (integer, required)

ScheduleItemsResponse
Properties:
  items (ScheduleItem[], required)
  lastSeenLocator (ulid, required)

ScheduleItem
Properties:
  locator (ulid, required)
  staticElementLocator (ulid, required)
  type (string, required)
  data (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid, required)

DeserializationResponse
Properties:
  jobLocator (ulid, required)

AddScheduleItemRequest
Properties:
  data (map<string, object>, required)

PatchScheduleItemRequest
Properties:
  locator (ulid, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

# Quotes API



<EndpointIndex
  names={[
  	'fetchQuote',
  	'fetchQuotesInATenant',
  	'createQuote',
  	'updateQuote',
  	'addElementsToQuote',
  	'removeElementsFromQuote',
  	'validateQuote',
  	'quoteValidatePreview',
  	'priceQuote',
  	'fetchPricedQuote',
  	'quotePricePreview',
  	'underwriteQuote',
  	'fetchUnderwritingFlagsForQuote',
  	'updateUnderwritingFlagsForQuote',
  	'addUnderwritingApproveFlagForQuote',
  	'addUnderwritingDeclineFlagForQuote',
  	'addUnderwritingBlockFlagForQuote',
  	'addUnderwritingRejectFlagForQuote',
  	'addUnderwritingInfoFlagForQuote',
  	'clearUnderwritingApproveFlagForQuote',
  	'clearUnderwritingDeclineFlagForQuote',
  	'clearUnderwritingBlockFlagForQuote',
  	'clearUnderwritingRejectFlagForQuote',
  	'clearUnderwritingInfoFlagForQuote',
  	'acceptQuote',
  	'issueQuote',
  	'copyQuote',
  	'createQuoteGroup',
  	'fetchQuoteGroup',
  	'fetchAllQuotesInGroup',
  	'fetchQuoteGroupByName',
  	'fetchQuoteGroupsInATenant',
  	'updateQuoteGroup',
  	'validateQuoteGroup',
  	'deleteQuoteGroup',
  	'assignQuoteGroup',
  	'addStaticDataForQuote',
  	'updateStaticDataForQuote',
  	'replaceAllStaticDataForQuote',
  	'fetchStaticDataForQuote',
  	'listStaticDataForQuote',
  	'updateBillingLevelForAQuote',
  	'addQuoteContact',
  	'deleteQuoteContact',
  	'fetchQuoteContacts',
  	'updateQuoteContact',
  	'fetchQuotesWithNumber',
  	'setQuoteNumber',
  	'generateQuoteNumber',
  	'resetQuote',
  	'refuseQuote',
  	'discardQuote',
  	'precommitQuote',
  ]}
  titles={{
  	fetchQuote: 'Fetch a Quote',
  	fetchQuotesInATenant: 'Fetch All Quotes',
  	createQuote: 'Create a Quote',
  	updateQuote: 'Update a Quote',
  	addElementsToQuote: 'Add Elements to a Quote',
  	removeElementsFromQuote: 'Remove Elements from a Quote',
  	validateQuote: 'Validate a Quote',
  	quoteValidatePreview:
  		'Get a stateless validation preview for a hypothetical quote',
  	priceQuote: 'Price a Quote',
  	fetchPricedQuote: 'Fetch Quote Pricing',
  	quotePricePreview: 'Get a stateless price preview for a hypothetical quote',
  	underwriteQuote: 'Underwrite a Quote',
  	fetchUnderwritingFlagsForQuote: 'Fetch Underwriting Flags',
  	updateUnderwritingFlagsForQuote: "Update a Quote's Underwriting Flags",
  	addUnderwritingApproveFlagForQuote:
  		'Add Approve Level Underwriting Flag for Quote',
  	addUnderwritingDeclineFlagForQuote:
  		'Add Decline Level Underwriting Flag for Quote',
  	addUnderwritingBlockFlagForQuote:
  		'Add Block Level Underwriting Flag for Quote',
  	addUnderwritingRejectFlagForQuote:
  		'Add Reject Level Underwriting Flag for Quote',
  	addUnderwritingInfoFlagForQuote:
  		'Add Info Level Underwriting Flag for Quote',
  	clearUnderwritingApproveFlagForQuote:
  		'Clear Approve Level Underwriting Flag for Quote',
  	clearUnderwritingDeclineFlagForQuote:
  		'Clear Decline Level Underwriting Flag for Quote',
  	clearUnderwritingBlockFlagForQuote:
  		'Clear Block Level Underwriting Flag for Quote',
  	clearUnderwritingRejectFlagForQuote:
  		'Clear Reject Level Underwriting Flag for Quote',
  	clearUnderwritingInfoFlagForQuote:
  		'Clear Info Level Underwriting Flag for Quote',
  	acceptQuote: 'Accept a Quote',
  	issueQuote: 'Issue a Quote',
  	copyQuote: 'Copy a Quote',
  	addStaticDataForQuote: 'Add Static Data to a Quote',
  	updateStaticDataForQuote: 'Update Static Data on a Quote',
  	replaceAllStaticDataForQuote: 'Replace All Static Data on a Quote',
  	fetchStaticDataForQuote: 'Fetch Static Data for a Quote',
  	listStaticDataForQuote: 'List Static Data for a Quote',
  	addQuoteContact: 'Add quote contact',
  	deleteQuoteContact: 'Delete quote contact',
  	fetchQuoteContacts: 'Fetch quote contacts',
  	updateQuoteContact: 'Update quote contact',
  	resetQuote: 'Reset a Quote',
  	refuseQuote: 'Refuse a Quote (Insured Declined Coverage)',
  	discardQuote: 'Discard a Quote',
  	precommitQuote: 'Invoke the precommit plugin for a draft quote',
  }}
/>

Main Flow [#main-flow]

Fetch [#fetch]

Fetch a Quote [#fetch-a-quote]

<ApiEndpoint name="fetchQuote" title="Fetch a Quote" />

Fetch All Quotes [#fetch-all-quotes]

<ApiEndpoint name="fetchQuotesInATenant" title="Fetch All Quotes" />

Fetch All Quotes for an Account [#fetch-all-quotes-for-an-account]

<ApiEndpoint name="fetchQuotesForAccount" title="Fetch All Quotes for an Account" />

<ApiSchema name="QuoteListResponse" />

<ApiSchema name="QuoteResponse" />

<Callout>
  The properties `accountLocator`, `productName`, `startTime`, `endTime`, `duration`, `durationBasis`, `currency`, `element`, and `timezone` will all be non-null for quotes that have been validated.
</Callout>

<ApiSchema name="ElementResponse" />

<ApiSchema name="Preferences" />

<ApiSchema name="InstallmentPreferences" />

Quote Creation [#quote-creation]

Create a Quote [#create-a-quote]

<ApiEndpoint name="createQuote" title="Create a Quote" />

<ApiSchema name="QuoteCreateRequest" />

<ApiSchema name="ElementCreateRequest" />

Update [#update]

Update a Quote [#update-a-quote]

<ApiEndpoint name="updateQuote" title="Update a Quote" />

<ApiSchema name="QuoteUpdateRequest" />

<ApiSchema name="ElementUpdateRequest" />

Add Elements to a Quote [#add-elements-to-a-quote]

<ApiEndpoint name="addElementsToQuote" title="Add Elements to a Quote" />

Remove Elements from a Quote [#remove-elements-from-a-quote]

<ApiEndpoint name="removeElementsFromQuote" title="Remove Elements from a Quote" />

Validation [#validation]

Validate a Quote [#validate-a-quote]

<ApiEndpoint name="validateQuote" title="Validate a Quote" />

<ApiSchema name="ValidationResult" />

<ApiSchema name="ValidationItemResponse" />

Get a stateless validation preview for a hypothetical quote [#get-a-stateless-validation-preview-for-a-hypothetical-quote]

<ApiEndpoint name="quoteValidatePreview" title="Get a stateless validation preview for a hypothetical quote" />

Pricing [#pricing]

Price a Quote [#price-a-quote]

<ApiEndpoint name="priceQuote" title="Price a Quote" />

Fetch Quote Pricing [#fetch-quote-pricing]

<ApiEndpoint name="fetchPricedQuote" title="Fetch Quote Pricing" />

<ApiSchema name="QuotePriceResponse" />

<ApiSchema name="ChargeResponse" />

Get a stateless price preview for a hypothetical quote [#get-a-stateless-price-preview-for-a-hypothetical-quote]

<ApiEndpoint name="quotePricePreview" title="Get a stateless price preview for a hypothetical quote" />

<span id="quoteUnderwritingApi" />

Underwriting [#underwriting]

Underwrite a Quote [#underwrite-a-quote]

<ApiEndpoint name="underwriteQuote" title="Underwrite a Quote" />

<ApiSchema name="QuoteUnderwritingResponse" />

Underwriting Flags [#underwriting-flags]

Fetch Underwriting Flags [#fetch-underwriting-flags]

<ApiEndpoint name="fetchUnderwritingFlagsForQuote" title="Fetch Underwriting Flags" />

<ApiSchema name="QuoteUnderwritingFlagsResponse" />

<ApiSchema name="UnderwritingFlagResponse" />

Update a Quote's Underwriting Flags [#update-a-quotes-underwriting-flags]

<ApiEndpoint name="updateUnderwritingFlagsForQuote" title="Update a Quote's Underwriting Flags" />

<ApiSchema name="UnderwritingFlagsUpdateRequest" />

<ApiSchema name="UnderwritingFlagCreateRequest" />

<ApiSchema name="UnderwritingTaskCreateRequest" />

Add Approve Level Underwriting Flag for Quote [#add-approve-level-underwriting-flag-for-quote]

<ApiEndpoint name="addUnderwritingApproveFlagForQuote" title="Add Approve Level Underwriting Flag for Quote" />

Add Decline Level Underwriting Flag for Quote [#add-decline-level-underwriting-flag-for-quote]

<ApiEndpoint name="addUnderwritingDeclineFlagForQuote" title="Add Decline Level Underwriting Flag for Quote" />

Add Block Level Underwriting Flag for Quote [#add-block-level-underwriting-flag-for-quote]

<ApiEndpoint name="addUnderwritingBlockFlagForQuote" title="Add Block Level Underwriting Flag for Quote" />

Add Reject Level Underwriting Flag for Quote [#add-reject-level-underwriting-flag-for-quote]

<ApiEndpoint name="addUnderwritingRejectFlagForQuote" title="Add Reject Level Underwriting Flag for Quote" />

Add Info Level Underwriting Flag for Quote [#add-info-level-underwriting-flag-for-quote]

<ApiEndpoint name="addUnderwritingInfoFlagForQuote" title="Add Info Level Underwriting Flag for Quote" />

Clear Approve Level Underwriting Flag for Quote [#clear-approve-level-underwriting-flag-for-quote]

<ApiEndpoint name="clearUnderwritingApproveFlagForQuote" title="Clear Approve Level Underwriting Flag for Quote" />

Clear Decline Level Underwriting Flag for Quote [#clear-decline-level-underwriting-flag-for-quote]

<ApiEndpoint name="clearUnderwritingDeclineFlagForQuote" title="Clear Decline Level Underwriting Flag for Quote" />

Clear Block Level Underwriting Flag for Quote [#clear-block-level-underwriting-flag-for-quote]

<ApiEndpoint name="clearUnderwritingBlockFlagForQuote" title="Clear Block Level Underwriting Flag for Quote" />

Clear Reject Level Underwriting Flag for Quote [#clear-reject-level-underwriting-flag-for-quote]

<ApiEndpoint name="clearUnderwritingRejectFlagForQuote" title="Clear Reject Level Underwriting Flag for Quote" />

Clear Info Level Underwriting Flag for Quote [#clear-info-level-underwriting-flag-for-quote]

<ApiEndpoint name="clearUnderwritingInfoFlagForQuote" title="Clear Info Level Underwriting Flag for Quote" />

Acceptance [#acceptance]

Accept a Quote [#accept-a-quote]

<ApiEndpoint name="acceptQuote" title="Accept a Quote" />

Issuance [#issuance]

Issue a Quote [#issue-a-quote]

<ApiEndpoint name="issueQuote" title="Issue a Quote" />

Copying [#copying]

Copy a Quote [#copy-a-quote]

<ApiEndpoint name="copyQuote" title="Copy a Quote" />

Create Quote From Policy [#create-quote-from-policy]

<ApiEndpoint name="createQuoteFromPolicy" />

Quote Groups [#quote-groups]

Create Quote Group [#create-quote-group]

<ApiEndpoint name="createQuoteGroup" />

<ApiSchema name="QuoteGroupCreateRequest" />

<ApiSchema name="QuoteGroupSettings" />

<ApiSchema name="QuoteGroupFieldEnforcementDeclaration" />

<ApiSchema name="QuoteGroupResponse" />

Fetch Quote Group [#fetch-quote-group]

<ApiEndpoint name="fetchQuoteGroup" />

Fetch All Quotes In Group [#fetch-all-quotes-in-group]

<ApiEndpoint name="fetchAllQuotesInGroup" />

<ApiSchema name="ListPageResponseQuote" />

Fetch Quote Group By Name [#fetch-quote-group-by-name]

<ApiEndpoint name="fetchQuoteGroupByName" />

Fetch Quote Groups In ATenant [#fetch-quote-groups-in-atenant]

<ApiEndpoint name="fetchQuoteGroupsInATenant" />

<ApiSchema name="ListPageResponseQuoteGroup" />

Update Quote Group [#update-quote-group]

<ApiEndpoint name="updateQuoteGroup" />

<ApiSchema name="QuoteGroupUpdateRequest" />

Validate Quote Group [#validate-quote-group]

<ApiEndpoint name="validateQuoteGroup" />

<ApiSchema name="QuoteGroupValidationResponse" />

Delete Quote Group [#delete-quote-group]

<ApiEndpoint name="deleteQuoteGroup" />

Assign Quote Group [#assign-quote-group]

<ApiEndpoint name="assignQuoteGroup" />

<ApiSchema name="QuoteGroupAssignmentRequest" />

Static Data [#static-data]

Add Static Data to a Quote [#add-static-data-to-a-quote]

<ApiEndpoint name="addStaticDataForQuote" title="Add Static Data to a Quote" />

Update Static Data on a Quote [#update-static-data-on-a-quote]

<ApiEndpoint name="updateStaticDataForQuote" title="Update Static Data on a Quote" />

<ApiSchema name="StaticDataUpdateRequest" />

Replace All Static Data on a Quote [#replace-all-static-data-on-a-quote]

<ApiEndpoint name="replaceAllStaticDataForQuote" title="Replace All Static Data on a Quote" />

Fetch Static Data for a Quote [#fetch-static-data-for-a-quote]

<ApiEndpoint name="fetchStaticDataForQuote" title="Fetch Static Data for a Quote" />

List Static Data for a Quote [#list-static-data-for-a-quote]

<ApiEndpoint name="listStaticDataForQuote" title="List Static Data for a Quote" />

<ApiSchema name="ListPageResponseStaticDataHistoryResponse" />

<ApiSchema name="StaticDataHistoryResponse" />

Documents [#documents]

Fetch Documents for a Quote [#fetch-documents-for-a-quote]

<ApiEndpoint name="fetchDocumentsForQuote" title="Fetch Documents for a Quote" />

<ApiSchema name="DocumentInstanceResponse" />

Billing [#billing]

Update Billing Level For AQuote [#update-billing-level-for-aquote]

<ApiEndpoint name="updateBillingLevelForAQuote" />

<ApiSchema name="UpdateBillingLevelRequest" />

Update the Delinquency Plan Assigned to a Quote [#update-the-delinquency-plan-assigned-to-a-quote]

<ApiEndpoint name="updateQuoteDelinquencyPlan" title="Update the Delinquency Plan Assigned to a Quote" />

Contacts [#contacts]

Add quote contact [#add-quote-contact]

<ApiEndpoint name="addQuoteContact" title="Add quote contact" />

<ApiSchema name="ContactRoles" />

Delete quote contact [#delete-quote-contact]

<ApiEndpoint name="deleteQuoteContact" title="Delete quote contact" />

Fetch quote contacts [#fetch-quote-contacts]

<ApiEndpoint name="fetchQuoteContacts" title="Fetch quote contacts" />

Update quote contact [#update-quote-contact]

<ApiEndpoint name="updateQuoteContact" title="Update quote contact" />

Numbering [#numbering]

Fetch Quotes With Number [#fetch-quotes-with-number]

<ApiEndpoint name="fetchQuotesWithNumber" />

Set Quote Number [#set-quote-number]

<ApiEndpoint name="setQuoteNumber" />

Generate Quote Number [#generate-quote-number]

<ApiEndpoint name="generateQuoteNumber" />

Holds [#holds]

Fetch Quote Holds [#fetch-quote-holds]

<ApiEndpoint name="fetchQuoteHolds" />

Atypical States and Operations [#atypical-states-and-operations]

Reset a Quote [#reset-a-quote]

<ApiEndpoint name="resetQuote" title="Reset a Quote" />

<ApiSchema name="ResetOptions" />

Refuse a Quote (Insured Declined Coverage) [#refuse-a-quote-insured-declined-coverage]

<ApiEndpoint name="refuseQuote" title="Refuse a Quote (Insured Declined Coverage)" />

Discard a Quote [#discard-a-quote]

<ApiEndpoint name="discardQuote" title="Discard a Quote" />

Invoke the precommit plugin for a draft quote [#invoke-the-precommit-plugin-for-a-draft-quote]

<ApiEndpoint name="precommitQuote" title="Invoke the precommit plugin for a draft quote" />


## API Reference

GET /policy/{tenantLocator}/quotes/{locator} — fetchQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/quotes/list — fetchQuotesInATenant
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 QuoteListResponse — OK

GET /policy/{tenantLocator}/accounts/{locator}/quotes/list — fetchQuotesForAccount
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  includeStaticData (boolean, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 QuoteListResponse — OK

POST /policy/{tenantLocator}/quotes — createQuote
Permissions: write, create
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuoteCreateRequest):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator} — updateQuote
Permissions: write, update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (QuoteUpdateRequest):
Responses:
  200 QuoteResponse — OK

PUT /policy/{tenantLocator}/quotes/{locator}/elements — addElementsToQuote
Permissions: write, elements-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ElementCreateRequest[]):
Responses:
  200 QuoteResponse — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/elements — removeElementsFromQuote
Permissions: write, elements-delete
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ulid[]):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/validate — validateQuote
Permissions: write, validate
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  stateless (boolean, query)
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/quotes/validatePreview — quoteValidatePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuoteCreateRequest):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/price — priceQuote
Permissions: write, price
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  stateless (boolean, query)
Responses:
  200 QuotePriceResponse — OK

GET /policy/{tenantLocator}/quotes/{locator}/price — fetchPricedQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuotePriceResponse — OK

POST /policy/{tenantLocator}/quotes/pricePreview — quotePricePreview
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuoteCreateRequest):
Responses:
  200 QuotePriceResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/underwrite — underwriteQuote
Permissions: write, underwrite
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  stateless (boolean, query)
Responses:
  200 QuoteUnderwritingResponse — OK

GET /policy/{tenantLocator}/quotes/{locator}/underwritingFlags — fetchUnderwritingFlagsForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/underwritingFlags — updateUnderwritingFlagsForQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagsUpdateRequest):
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/approve — addUnderwritingApproveFlagForQuote
Permissions: write, approve-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/decline — addUnderwritingDeclineFlagForQuote
Permissions: write, decline-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/block — addUnderwritingBlockFlagForQuote
Permissions: write, block-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/reject — addUnderwritingRejectFlagForQuote
Permissions: write, reject-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/info — addUnderwritingInfoFlagForQuote
Permissions: write, info-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UnderwritingFlagCreateRequest):
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/approve/{flagLocator} — clearUnderwritingApproveFlagForQuote
Permissions: write, approve-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/decline/{flagLocator} — clearUnderwritingDeclineFlagForQuote
Permissions: write, decline-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/block/{flagLocator} — clearUnderwritingBlockFlagForQuote
Permissions: write, block-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/reject/{flagLocator} — clearUnderwritingRejectFlagForQuote
Permissions: write, reject-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

DELETE /policy/{tenantLocator}/quotes/{locator}/underwritingFlags/info/{flagLocator} — clearUnderwritingInfoFlagForQuote
Permissions: write, info-clear
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  flagLocator (ulid, path, required)
Responses:
  200 QuoteUnderwritingFlagsResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/accept — acceptQuote
Permissions: write, accept
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/issue — issueQuote
Permissions: write, issue
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/copy — copyQuote
Permissions: write, create
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (QuoteGroupAssignmentRequest):
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/policies/{locator}/quote — createQuoteFromPolicy
Permissions: write, create-quote
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  date (datetime, query)
  byIssuedTime (boolean, query)
  includeStaticData (boolean, query)
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/quotes/groups — createQuoteGroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuoteGroupCreateRequest):
Responses:
  200 QuoteGroupResponse — OK

GET /policy/{tenantLocator}/quotes/groups/{locator} — fetchQuoteGroup
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteGroupResponse — OK

GET /policy/{tenantLocator}/quotes/groups/{locator}/list — fetchAllQuotesInGroup
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseQuote — OK

GET /policy/{tenantLocator}/quotes/groups/name/{name} — fetchQuoteGroupByName
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 QuoteGroupResponse — OK

GET /policy/{tenantLocator}/quotes/groups/list — fetchQuoteGroupsInATenant
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseQuoteGroup — OK

PATCH /policy/{tenantLocator}/quotes/groups/{locator} — updateQuoteGroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (QuoteGroupUpdateRequest):
Responses:
  200 QuoteGroupResponse — OK

PATCH /policy/{tenantLocator}/quotes/groups/{locator}/validate — validateQuoteGroup
Permissions: write, validate
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteGroupValidationResponse — OK

DELETE /policy/{tenantLocator}/quotes/groups/{locator} — deleteQuoteGroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/assignToGroup — assignQuoteGroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (QuoteGroupAssignmentRequest):
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/static — addStaticDataForQuote
Set the static extension data on a quote
Permissions: write, static-data-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, object>):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/static — updateStaticDataForQuote
Updates some of the static data on a quote
Permissions: write, static-data-update
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (StaticDataUpdateRequest):
Responses:
  200 QuoteResponse — OK

PUT /policy/{tenantLocator}/quotes/{locator}/static — replaceAllStaticDataForQuote
Replaces all of the static data on a quote
Permissions: write, static-data-add
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, object>):
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/quotes/{locator}/static — fetchStaticDataForQuote
Gets static data for a quote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, object> — OK

GET /policy/{tenantLocator}/quotes/{locator}/static/history/list — listStaticDataForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 ListPageResponseStaticDataHistoryResponse — OK

GET /document/{tenantLocator}/documents/quote/{locator}/list — fetchDocumentsForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  suppressRenderingData (boolean, query)
Responses:
  200 DocumentListResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/billingLevel — updateBillingLevelForAQuote
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (UpdateBillingLevelRequest):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/delinquencyPlan — updateQuoteDelinquencyPlan
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (DelinquencyPlanUpdateRequest):
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/quotes/{quoteLocator}/contacts — addQuoteContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
Request body (ContactRoles):
Responses:
  200 QuoteResponse — OK

DELETE /policy/{tenantLocator}/quotes/{quoteLocator}/contacts/{contactLocator} — deleteQuoteContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/quotes/{quoteLocator}/contacts — fetchQuoteContacts
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
Responses:
  200 ContactRoles[] — OK

PATCH /policy/{tenantLocator}/quotes/{quoteLocator}/contacts/{contactLocator} — updateQuoteContact
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  quoteLocator (ulid, path, required)
  contactLocator (ulid, path, required)
Request body (ContactAssociationUpdateRequest):
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/quotes/numbers/{quoteNumber} — fetchQuotesWithNumber
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  quoteNumber (string, path, required)
Responses:
  200 QuoteResponse[] — OK

POST /policy/{tenantLocator}/quotes/{locator}/number/set — setQuoteNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
  quoteNumber (string, query, required)
Responses:
  200 QuoteResponse — OK

POST /policy/{tenantLocator}/quotes/{locator}/number/generate — generateQuoteNumber
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/quotes/{locator}/holds — fetchQuoteHolds
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 EntityHold[] — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/reset — resetQuote
Permissions: write, reset
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ResetOptions):
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/refuse — refuseQuote
Permissions: write, refuse
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/discard — discardQuote
Permissions: write, discard
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

PATCH /policy/{tenantLocator}/quotes/{locator}/precommit — precommitQuote
Permissions: write, precommit
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

QuoteListResponse
Properties:
  listCompleted (boolean, required)
  items (QuoteResponse[], required)

QuoteResponse
Properties:
  locator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  productName (string, required)
  accountLocator (ulid, required)
  startTime (datetime)
  endTime (datetime)
  timezone (string)
  currency (string)
  underwritingStatus (string)
  expirationTime (datetime)
  element (ElementResponse, required) — The root element in the hierarchy
  preferences (Preferences) — Plan selections and setting overrides
  policyLocator (ulid)
  delinquencyPlanName (string)
  durationBasis (Enum years | months | weeks | days | hours)
  groupLocator (ulid)
  autoRenewalPlanName (string)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  quoteNumber (string)
  duration (number) — The duration of the prospective policy in units of durationBasis
  acceptedTime (datetime)
  issuedTime (datetime)
  validationResult (ValidationResult)
  quickQuoteLocator (ulid)
  contacts (ContactRoles[], required)
  anonymizedAt (datetime)
  invoiceFeeAmount (number)
  createdBy (uuid)
  createdAt (datetime)
  jurisdiction (string)
  producerCode (string)
  reservedPolicyNumber (string)
  proxyPayerLocator (ulid)
  static (map<string, object>)
  policyNumber (string)

ElementResponse
Properties:
  type (string, required)
  locator (ulid, required)
  parentLocator (ulid, required)
  elements (ElementResponse[])
  coverageTerms (map<string, object>)
  data (map<string, object>)
  staticLocator (ulid, required)
  originalEffectiveTime (datetime, required) — Indicates when the element was first added to the policy
  category (Enum product | coverage | exposure | exposureGroup | policyLine)

Preferences
Properties:
  installmentPreferences (InstallmentPreferences)

InstallmentPreferences
Properties:
  cadence (Enum none | fullPay | weekly | everyOtherWeek | monthly | quarterly | semiannually | annually | thirtyDays | everyNDays)
  anchorMode (Enum generateDay | termStartDay | dueDay)
  generateLeadDays (integer)
  dueLeadDays (integer)
  installmentWeights (number[], required)
  maxInstallmentsPerTerm (integer)
  installmentPlanName (string)
  anchorType (Enum none | dayOfMonth | anchorTime | dayOfWeek | weekOfMonth)
  dayOfMonth (integer)
  dayOfWeek (Enum monday | tuesday | wednesday | thursday | friday | saturday | sunday)
  weekOfMonth (Enum none | first | second | third | fourth | fifth)
  anchorTime (datetime)
  autopayLeadDays (number)

QuoteCreateRequest
Properties:
  productName (string, required)
  accountLocator (ulid, required)
  startTime (datetime, required)
  endTime (datetime)
  expirationTime (datetime)
  currency (string)
  timezone (string)
  jurisdiction (string)
  coverageTerms (map<string, object>)
  data (map<string, object>, required)
  elements (ElementCreateRequest[])
  durationBasis (Enum years | months | weeks | days | hours)
  preferences (Preferences)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  billingLevel (Enum account | inherit | policy)
  region (string)
  quoteGroupLocator (ulid)
  static (map<string, object>)
  contacts (ContactRoles[], required)
  invoiceFeeAmount (number, required)
  termDuration (integer)
  producerCode (string)
  proxyPayerLocator (ulid)

ElementCreateRequest
Properties:
  type (string, required)
  parentLocator (ulid)
  elements (ElementCreateRequest[], required)
  coverageTerms (map<string, object>)
  data (map<string, object>)
  staticLocator (ulid)

QuoteUpdateRequest
Properties:
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  setCoverageTerms (map<string, object>, required)
  removeCoverageTerms (map<string, object>, required)
  currency (string, required)
  timezone (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  resetEndTime (boolean, required)
  expirationTime (datetime, required)
  elements (ElementUpdateRequest[], required)
  preferences (Preferences, required)
  delinquencyPlanName (string, required)
  autoRenewalPlanName (string, required)
  billingLevel (Enum account | inherit | policy, required)
  setContacts (ContactRoles[], required)
  removeContacts (ulid[], required)
  invoiceFeeAmount (number, required)
  jurisdiction (string)
  producerCode (string)
  accountLocator (ulid, required)
  proxyPayerLocator (ulid, required)
  clearProxyPayerLocator (boolean, required)

ElementUpdateRequest
Properties:
  locator (ulid, required)
  setData (map<string, object>, required)
  removeData (map<string, object>, required)
  setCoverageTerms (map<string, object>, required)
  removeCoverageTerms (map<string, object>, required)

ValidationResult
Properties:
  validationItems (ValidationItemResponse[])
  success (boolean, required)

ValidationItemResponse
Properties:
  elementType (string, required)
  locator (ulid, required)
  errors (string[], required)

QuotePriceResponse
Properties:
  tenantLocator (uuid, required)
  quoteLocator (ulid, required)
  accountLocator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  productName (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  duration (number, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  items (PolicyChargeResponse[], required)
  quoteNumber (string)
  validationResult (ValidationResult)

ChargeResponse
Properties:
  locator (ulid, required)
  amount (number, required)
  currency (string, required)
  chargeCategory (Enum none | premium | tax | fee | credit | invoiceFee | cededPremium | nonFinancial | surcharge, required)
  chargeType (string, required)
  chargeInvoicing (Enum scheduled | next | immediate, required)
  accountLocator (ulid, required)
  tag (string)
  policyLocator (ulid)
  transactionLocator (ulid)
  elementLocator (ulid)
  elementStaticLocator (ulid)
  reversalOfLocator (ulid)
  bundleTransactionLocator (ulid)

QuoteUnderwritingResponse
Properties:
  tenantLocator (uuid, required)
  quoteLocator (ulid, required)
  accountLocator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  productName (string, required)
  startTime (datetime, required)
  endTime (datetime, required)
  duration (number, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  underwritingStatus (string, required)
  underwritingFlags (UnderwritingFlagResponse[], required)
  validationResult (ValidationResult)

QuoteUnderwritingFlagsResponse
Properties:
  quoteLocator (ulid, required)
  flags (UnderwritingFlagResponse[], required)
  clearedFlags (UnderwritingFlagResponse[])

UnderwritingFlagResponse
Properties:
  locator (ulid, required)
  level (Enum info | block | decline | reject | approve, required)
  referenceType (Enum quote | transaction, required)
  referenceLocator (ulid, required)
  note (string, required)
  tag (string, required)
  elementLocator (ulid)
  createdBy (uuid, required)
  createdTime (datetime, required)
  clearedBy (uuid, required)
  clearedTime (datetime, required)
  taskCreationResponse (TaskCreationResponse, required)

UnderwritingFlagsUpdateRequest
Properties:
  addFlags (UnderwritingFlagCreateRequest[], required)
  clearFlags (ulid[], required)

UnderwritingFlagCreateRequest
Properties:
  level (Enum info | block | decline | reject | approve, required)
  note (string, required)
  tag (string, required)
  elementLocator (ulid, required)
  taskCreation (UnderwritingTaskCreateRequest, required)

UnderwritingTaskCreateRequest
Properties:
  type (string, required)
  references (TaskReference[], required)
  underwritingFlagLocators (ulid[], required)
  deadlineTime (datetime)
  assignedTo (uuid)
  description (string)
  workgroupToBeAssignedLocator (ulid)
  source (string)
  tag (string)
  labels (string[], required)

QuoteGroupCreateRequest
Properties:
  name (string, required)
  quoteGroupNumber (string, required)
  settings (QuoteGroupSettings, required)
  quoteLocators (ulid[], required)
  preferredQuoteLocator (ulid, required)

QuoteGroupSettings
Properties:
  stateUniqueness (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  enforceProductUniformity (boolean, required) — default: false
  fieldEnforcementDeclarations (QuoteGroupFieldEnforcementDeclaration[], required)

QuoteGroupFieldEnforcementDeclaration
Properties:
  name (string, required)
  paths (map<string, string>, required)

QuoteGroupResponse
Properties:
  locator (ulid, required)
  name (string, required)
  quoteGroupNumber (string)
  quoteGroupState (Enum open | locked, required)
  settings (QuoteGroupSettings, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  quoteLocators (ulid[], required)
  preferredQuoteLocator (ulid)

ListPageResponseQuote
Properties:
  listCompleted (boolean, required)
  items (QuickQuoteQuoteDetails[], required)

ListPageResponseQuoteGroup
Properties:
  listCompleted (boolean, required)
  items (QuoteGroupResponse[], required)

QuoteGroupUpdateRequest
Properties:
  name (string, required)
  quoteGroupNumber (string, required)
  quotesToRemove (ulid[], required)
  quotesToAdd (ulid[], required)
  preferredQuoteLocator (ulid, required)
  resetPreferredQuote (boolean, required)

QuoteGroupValidationResponse
Properties:
  errors (string[], required)
  valid (boolean, required)

QuoteGroupAssignmentRequest
Properties:
  groupLocator (ulid, required)

StaticDataUpdateRequest
Properties:
  setData (map<string, object>, required)
  removeData (map<string, object>, required)

ListPageResponseStaticDataHistoryResponse
Properties:
  listCompleted (boolean, required)
  items (StaticDataHistoryResponse[], required)

StaticDataHistoryResponse
Properties:
  historyLocator (ulid, required)
  staticData (map<string, object>, required)
  updatedBy (uuid, required)
  updatedAt (datetime, required)

DocumentInstanceResponse
Properties:
  locator (ulid, required)
  referenceLocator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  referenceDocumentLocator (ulid)
  transactionLocator (ulid)
  segmentLocator (ulid)
  termLocator (ulid)
  policyLocator (ulid)
  name (string)
  staticName (string)
  documentInstanceState (Enum draft | dataReady | ready | dataError | renderError | conversionError | rendered | removed, required)
  documentFormat (Enum csv | doc | docx | html | jpeg | jpg | pdf | text | txt | xls | xlsx | zip, required)
  metadata (map<string, object>, required)
  createdAt (datetime, required)
  createdBy (uuid)
  readyAt (datetime)
  renderingData (map<string, object>, required)
  processingErrors (string)
  external (boolean, required)
  category (string)
  consolidatedFrom (ulid[], required)
  consolidatedTo (ulid[], required)
  copyOnIssuance (boolean)

UpdateBillingLevelRequest
Properties:
  billingLevel (Enum account | inherit | policy, required)

ContactRoles
Properties:
  contactLocator (ulid, required)
  roles (string[], required)

ResetOptions
Properties:
  resetAllUnderwritingFlags (boolean, required)
  resetFlags (ulid[], required)
  resetFlagsAction (Enum clear | delete, required)
  deleteAllAutomaticDocuments (boolean, required)
  discardSchedules (boolean, required)
  resetLockedResources (boolean, required)
  deleteDocuments (ulid[], required)

# Data Lake Delta Files API



<EndpointIndex
  names={['fetchDeltaFiles', 'fetchDeltaFile']}
  titles={{
  	getMetadata: 'Fetch List of Delta Files',
  	download: 'Fetch Specific Delta File',
  }}
/>

Delta File Endpoints [#delta-file-endpoints]

Fetch List of Delta Files [#fetch-list-of-delta-files]

<ApiEndpoint name="fetchDeltaFiles" title="Fetch List of Delta Files" />

Fetch Specific Delta File [#fetch-specific-delta-file]

<ApiEndpoint name="fetchDeltaFile" title="Fetch Specific Delta File" />

Delta File Request and Response Objects [#delta-file-request-and-response-objects]

<ApiSchema name="DeltaFilesGetRequest" />

<ApiSchema name="DeltaFilesGetResponse" />

<ApiSchema name="DeltaFile" />

<ApiSchema name="DeltaFileDownloadRequest" />

See Also [#see-also]

* [Data Lake Delta File Feature Guide](/features/reporting/delta-files)


## API Reference

POST /business-stats/delta-files/list — fetchDeltaFiles
Permissions: read
Request body (DeltaFilesGetRequest):
Responses:
  200 DeltaFilesGetResponse — OK

POST /business-stats/delta-files/download — fetchDeltaFile
Permissions: read
Request body (DeltaFileDownloadRequest):
Responses:
  200 — OK

DeltaFilesGetRequest
Properties:
  tenantLocator (uuid, required) — Locator of the tenant corresponding to the data
  transformationTable (Enum DataLakeAccountDataExtensions | DataLakeAccounts | DataLakeAffectedTransactions | DataLakeAuxData | DataLakeBillingHolds | DataLakeClaimDataExtensions | DataLakeClaims | DataLakeCreditDistributions | DataLakeCreditItems | DataLakeDelinquencies | DataLakeDelinquencyReferences | DataLakeDiaries | DataLakeDisbursementDataExtensions | DataLakeDisbursements | DataLakeFaTransactionAccountLines | DataLakeFaTransactions | DataLakeFnolDataExtensions | DataLakeFnols | DataLakeInstallmentItems | DataLakeInstallments | DataLakeInstallmentSettings | DataLakeInvoiceItems | DataLakeInvoices | DataLakeLedgerAccountLineItems | DataLakeLedgerAccounts | DataLakeMoratoriumElections | DataLakeMoratoriums | DataLakeMoratoriumStatuses | DataLakePaymentDataExtensions | DataLakePayments | DataLakePolicies | DataLakePolicyAutoRenewals | DataLakePolicyCoverageTerms | DataLakePolicyDataExtensions | DataLakePolicyElementCharges | DataLakePolicyElements | DataLakePolicyElementTree | DataLakePolicyElementUnderwritingFlags | DataLakePolicyPreferences | DataLakePolicySegments | DataLakePolicyStatuses | DataLakePolicyTerms | DataLakePolicyTransactionChangeInstructions | DataLakePolicyTransactions | DataLakeProducerCodeDataExtensions | DataLakeProducerCodes | DataLakeProducerDataExtensions | DataLakeProducerHierarchy | DataLakeProducers | DataLakeQuoteCoverageTerms | DataLakeQuoteDataExtensions | DataLakeQuoteElementCharges | DataLakeQuoteElements | DataLakeQuoteElementTree | DataLakeQuoteElementUnderwritingFlags | DataLakeQuotes | DataLakeTaskReferences | DataLakeTasks | DataLakeUserAssociations | DataLakeUserQualifications | DataLakeWriteOffs, required) — Name of the desired Data Lake table
  deltaFileType (Enum sql | csv) — The format of the delta files to be returned. Defaults to `sql` if omitted
  version (integer) — Target a specific schema version; defaults to latest if omitted
  startTime (integer) — Files in returned index will all have a `generationTime` later than `startTime`. Format is UNIX timestamp in UTC milliseconds (e.g. 1741713134934)
  lastFile (string) — Only files after this file in the index will be returned. Must provide full `fileName`
  dataProcessedThroughTime (integer) — Only files with a `dataProcessedThroughTime` prior to or equal to this time will be returned. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)

DeltaFilesGetResponse
Properties:
  version (integer, required) — Target a specific schema version; defaults to latest if omitted
  createTableFile (string, required) — Path & name of file with necessary sql statement to create the table in the destination schema
  dropTableFile (string, required) — Path & name of file with necessary sql statement to drop the existing version of the table in the destination schema
  s3Bucket (string, required) — The source S3 bucket required for the <ApiLink name='DeltaFileDownloadRequest' />
  dataProcessedThroughTime (integer, required) — The time of the latest operational change that will be reflected in the data. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)
  deltaFiles (DeltaFile[], required) — The index of individual delta files

DeltaFile
Properties:
  deltaFileType (Enum sql | csv, required) — The format of the delta file
  fileName (string, required) — The name of the delta file
  jobStartTime (integer, required) — The that the job to generate the file began. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)
  jobEndTime (integer, required) — The that the job to generate the file ended. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)
  generationTime (integer, required) — The time that the file was generated. Format is UNIX timestamp in UTC milliseconds (e.g. 1741713134934)
  recordCount (integer) — For files with `deltaFileType` = `csv`, the number of rows in the file, excluding headers
  md5HashSum (string) — For files with `deltaFileType` = `csv`, the MD5 format hashsum for the file contents, including headers

DeltaFileDownloadRequest
Properties:
  tenantLocator (uuid, required) — Locator of the tenant corresponding to the data
  s3Bucket (string) — The name of the S3 bucket as returned by the <ApiLink name='DeltaFilesGetResponse' />. Only required if requesting `createTableFile` or `dropTableFile`, and `deltaFileType` is `csv`
  fileName (string, required) — The name of the file to be requested. Value may be `fileName`, `createTableFile`, or `dropTableFile`

# Metrics API



<EndpointIndex
  names={[
  	'getGWP',
  	'getIssuedPolicies',
  	'getPricedQuotes',
  	'getConversionRate',
  	'getRenewedPolicies',
  	'getExpiredPolicies',
  	'getRenewalRate',
  	'downloadGWP',
  	'downloadIssuedPolicies',
  	'downloadPricedQuotes',
  	'downloadConversionRate',
  	'downloadRenewedPolicies',
  	'downloadExpiredPolicies',
  	'downloadRenewalRate',
  ]}
  titles={{
  	getGWP: 'Fetch GWP metrics',
  	getIssuedPolicies: 'Fetch Issued Policy Metrics',
  	getPricedQuotes: 'Fetch Priced Quote Metrics',
  	getConversionRate: 'Fetch New Business Conversion Metrics',
  	getRenewedPolicies: 'Fetch Issued Renewal Metrics',
  	getExpiredPolicies: 'Fetch Expired Policy Metrics',
  	getRenewalRate: 'Fetch Renewal Conversion Metrics',
  	downloadGWP: 'Download csv of GWP metrics',
  	downloadIssuedPolicies: 'Download csv of Issued Policy Metrics',
  	downloadPricedQuotes: 'Download csv of Priced Quote Metrics',
  	downloadConversionRate: 'Download csv of New Business Conversion Metrics',
  	downloadRenewedPolicies: 'Download csv of Issued Renewal Metrics',
  	downloadExpiredPolicies: 'Download csv of Expired Policy Metrics',
  	downloadRenewalRate: 'Download csv of Renewal Conversion Metrics',
  }}
/>

Metrics Data Response Endpoints [#metrics-data-response-endpoints]

Fetch GWP metrics [#fetch-gwp-metrics]

<ApiEndpoint name="getGWP" title="Fetch GWP metrics" />

Fetch Issued Policy Metrics [#fetch-issued-policy-metrics]

<ApiEndpoint name="getIssuedPolicies" title="Fetch Issued Policy Metrics" />

Fetch Priced Quote Metrics [#fetch-priced-quote-metrics]

<ApiEndpoint name="getPricedQuotes" title="Fetch Priced Quote Metrics" />

Fetch New Business Conversion Metrics [#fetch-new-business-conversion-metrics]

<ApiEndpoint name="getConversionRate" title="Fetch New Business Conversion Metrics" />

Fetch Issued Renewal Metrics [#fetch-issued-renewal-metrics]

<ApiEndpoint name="getRenewedPolicies" title="Fetch Issued Renewal Metrics" />

Fetch Expired Policy Metrics [#fetch-expired-policy-metrics]

<ApiEndpoint name="getExpiredPolicies" title="Fetch Expired Policy Metrics" />

Fetch Renewal Conversion Metrics [#fetch-renewal-conversion-metrics]

<ApiEndpoint name="getRenewalRate" title="Fetch Renewal Conversion Metrics" />

Metrics CSV Download Endpoints [#metrics-csv-download-endpoints]

Download csv of GWP metrics [#download-csv-of-gwp-metrics]

<ApiEndpoint name="downloadGWP" title="Download csv of GWP metrics" />

Download csv of Issued Policy Metrics [#download-csv-of-issued-policy-metrics]

<ApiEndpoint name="downloadIssuedPolicies" title="Download csv of Issued Policy Metrics" />

Download csv of Priced Quote Metrics [#download-csv-of-priced-quote-metrics]

<ApiEndpoint name="downloadPricedQuotes" title="Download csv of Priced Quote Metrics" />

Download csv of New Business Conversion Metrics [#download-csv-of-new-business-conversion-metrics]

<ApiEndpoint name="downloadConversionRate" title="Download csv of New Business Conversion Metrics" />

Download csv of Issued Renewal Metrics [#download-csv-of-issued-renewal-metrics]

<ApiEndpoint name="downloadRenewedPolicies" title="Download csv of Issued Renewal Metrics" />

Download csv of Expired Policy Metrics [#download-csv-of-expired-policy-metrics]

<ApiEndpoint name="downloadExpiredPolicies" title="Download csv of Expired Policy Metrics" />

Download csv of Renewal Conversion Metrics [#download-csv-of-renewal-conversion-metrics]

<ApiEndpoint name="downloadRenewalRate" title="Download csv of Renewal Conversion Metrics" />

Metrics Request and Response Objects [#metrics-request-and-response-objects]

<ApiSchema name="MetricRequest" />

<ApiSchema name="MetricResponse" />

<ApiSchema name="DataPoint" />

See Also [#see-also]

* [Metrics Feature Guide](/features/reporting/metrics)


## API Reference

POST /business-stats/metrics/gwp — getGWP
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/issued — getIssuedPolicies
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/quotes — getPricedQuotes
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/conversionRate — getConversionRate
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/renewedPolicies — getRenewedPolicies
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/expiredPolicies — getExpiredPolicies
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/renewalRate — getRenewalRate
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 MetricResponse — OK

POST /business-stats/metrics/gwp/download — downloadGWP
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

POST /business-stats/metrics/issued/download — downloadIssuedPolicies
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

POST /business-stats/metrics/quotes/download — downloadPricedQuotes
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

POST /business-stats/metrics/conversionRate/download — downloadConversionRate
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

POST /business-stats/metrics/renewedPolicies/download — downloadRenewedPolicies
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

POST /business-stats/metrics/expiredPolicies/download — downloadExpiredPolicies
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

POST /business-stats/metrics/renewalRate/download — downloadRenewalRate
Permissions: read
Parameters:
  offset (integer, query)
  count (integer, query)
  backfillZeroes (boolean, query)
Request body (MetricRequest):
Responses:
  200 — OK

MetricRequest
Properties:
  groupByProduct (boolean)
  groupByTenant (boolean)
  tenantLocators (uuid[])
  products (string[])
  tenantType (Enum test | production | retired | deleted)
  startTime (datetime, required)
  endTime (datetime, required)
  periodic (Enum none | day | week | month | quarter | year)
  currencies (string[])
  localStartDateAdjusted (date, required)
  localEndDateAdjusted (date, required)

MetricResponse
Properties:
  offset (integer, required)
  count (integer, required)
  startDate (date, required)
  endDate (date, required)
  periodic (Enum none | day | week | month | quarter | year, required)
  results (DataPoint[], required)

DataPoint
Properties:
  productName (string, required)
  tenantLocator (uuid, required)
  currency (string, required)
  dataPointStartDate (date, required)
  value (number, required)

# Document Resources API



<EndpointIndex
  names={[
  	'fetchDocumentResourceByName',
  	'createDocumentResource',
  	'updateDocument',
  	'fetchDocumentTemplate',
  	'createVelocityDocumentTemplate',
  	'updateVelocityDocumentTemplate',
  	'createLiquidDocumentTemplate',
  	'updateLiquidDocumentTemplate',
  	'fetchTemplate',
  	'uploadVelocity',
  	'updateVelocity',
  	'uploadLiquid',
  	'updateLiquid',
  	'addFont',
  ]}
  titles={{
  	fetchDocumentResourceByName: 'Fetch a Document Resource by Name',
  	createDocumentResource: 'Create a New Document Resource',
  	updateDocument: 'Update a Document Resource',
  	fetchDocumentTemplate: 'Fetch a Template',
  	createVelocityDocumentTemplate: 'Upload a Velocity Template',
  	updateVelocityDocumentTemplate: 'Update a Velocity Template',
  	createLiquidDocumentTemplate: 'Upload a Liquid Template',
  	updateLiquidDocumentTemplate: 'Update a Liquid Template',
  	fetchTemplate: 'Fetch a Template Snippet',
  	uploadVelocity: 'Upload a Velocity Template Snippet',
  	updateVelocity: 'Update a Velocity Template Snippet',
  	uploadLiquid: 'Upload a Liquid Template Snippet',
  	updateLiquid: 'Update a Liquid Template Snippet',
  	addFont: 'Add a custom font',
  }}
/>

Document Resources [#document-resources]

Fetch a Document Resource by Name [#fetch-a-document-resource-by-name]

<ApiEndpoint name="fetchDocumentResourceByName" title="Fetch a Document Resource by Name" />

Create a New Document Resource [#create-a-new-document-resource]

<ApiEndpoint name="createDocumentResource" title="Create a New Document Resource" />

Update a Document Resource [#update-a-document-resource]

<ApiEndpoint name="updateDocument" title="Update a Document Resource" />

<span id="document_template_creation_and_update_endpoints" />

Document Templates [#document-templates]

Fetch a Template [#fetch-a-template]

<ApiEndpoint name="fetchDocumentTemplate" title="Fetch a Template" />

Upload a Velocity Template [#upload-a-velocity-template]

<ApiEndpoint name="createVelocityDocumentTemplate" title="Upload a Velocity Template" />

Update a Velocity Template [#update-a-velocity-template]

<ApiEndpoint name="updateVelocityDocumentTemplate" title="Update a Velocity Template" />

Upload a Liquid Template [#upload-a-liquid-template]

<ApiEndpoint name="createLiquidDocumentTemplate" title="Upload a Liquid Template" />

Update a Liquid Template [#update-a-liquid-template]

<ApiEndpoint name="updateLiquidDocumentTemplate" title="Update a Liquid Template" />

<Callout>
  Document templates are limited to 5MB in size.
</Callout>

<ApiSchema name="StreamingResponseBody" />

Document Snippets [#document-snippets]

Fetch a Template Snippet [#fetch-a-template-snippet]

<ApiEndpoint name="fetchTemplate" title="Fetch a Template Snippet" />

Upload a Velocity Template Snippet [#upload-a-velocity-template-snippet]

<ApiEndpoint name="uploadVelocity" title="Upload a Velocity Template Snippet" />

Update a Velocity Template Snippet [#update-a-velocity-template-snippet]

<ApiEndpoint name="updateVelocity" title="Update a Velocity Template Snippet" />

Upload a Liquid Template Snippet [#upload-a-liquid-template-snippet]

<ApiEndpoint name="uploadLiquid" title="Upload a Liquid Template Snippet" />

Update a Liquid Template Snippet [#update-a-liquid-template-snippet]

<ApiEndpoint name="updateLiquid" title="Update a Liquid Template Snippet" />

Custom Fonts [#custom-fonts]

Add a custom font [#add-a-custom-font]

<ApiEndpoint name="addFont" title="Add a custom font" />- [Documents
API](/api/documents) - [Documents Configuration
Guide](/configuration/resources/documents)


## API Reference

GET /resource/{tenantLocator}/documents/{name} — fetchDocumentResourceByName
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  byStaticName (boolean, query)
  date (datetime, query)
  jurisdiction (string, query)
Responses:
  200 — OK

POST /resource/{tenantLocator}/documents — createDocumentResource
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  Content-Type (string, header, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 — OK

PATCH /resource/{tenantLocator}/documents/{name} — updateDocument
Permissions: update
Parameters:
  tenantLocator (uuid, path, required)
  Content-Type (string, header, required)
  name (string, path, required)
Responses:
  200 — OK

GET /resource/{tenantLocator}/templates/{name} — fetchDocumentTemplate
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  byStaticName (boolean, query)
  date (datetime, query)
  jurisdiction (string, query)
Responses:
  200 — OK

POST /resource/{tenantLocator}/templates/velocity — createVelocityDocumentTemplate
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/templates/velocity — updateVelocityDocumentTemplate
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
Responses:
  200 BasicResourceResponse — OK

POST /resource/{tenantLocator}/templates/liquid — createLiquidDocumentTemplate
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/templates/liquid — updateLiquidDocumentTemplate
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
Responses:
  200 BasicResourceResponse — OK

GET /resource/{tenantLocator}/templateSnippets/{name} — fetchTemplate
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  byStaticName (boolean, query)
  date (datetime, query)
  jurisdiction (string, query)
Responses:
  200 — OK

POST /resource/{tenantLocator}/templateSnippets/velocity — uploadVelocity
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/templateSnippets/velocity — updateVelocity
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
Responses:
  200 BasicResourceResponse — OK

POST /resource/{tenantLocator}/templateSnippets/liquid — uploadLiquid
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/templateSnippets/liquid — updateLiquid
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
Responses:
  200 BasicResourceResponse — OK

POST /resource/{tenantLocator}/fonts — addFont
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 — OK

StreamingResponseBody

# Resource Service API



<EndpointIndex
  names={[
  	'fetchResourceGroup',
  	'fetchResourceGroups',
  	'createResourceGroup',
  	'updateResourceGroup',
  	'retire',
  	'fetchResource',
  	'fetchMultipleResources',
  	'fetchMultipleResourcesByType',
  	'getResourceSelections',
  	'lockResourceSelection',
  	'unlockResourceSelection',
  	'unlockResourceSelections',
  ]}
  titles={{
  	fetchResourceGroup: 'Fetch a Resource Group',
  	fetchResourceGroups: 'Fetch all Resource Groups',
  	createResourceGroup: 'Create a Resource Group',
  	updateResourceGroup: 'Update a Resource Group',
  	retire: 'Retire a ResourceGroup',
  	fetchResource: 'Fetch a Resource',
  	fetchMultipleResources: 'Fetch Multiple Resources',
  	fetchMultipleResourcesByType: 'Fetch Multiple Resources by Type',
  	getResourceSelections: 'Fetch Resource Selections',
  	lockResourceSelection: 'Lock Resource Selection',
  	unlockResourceSelection: 'Unlock Resource Selection',
  	unlockResourceSelections: 'Unlock Resource Selections',
  }}
/>

Resource Groups [#resource-groups]

Fetch a Resource Group [#fetch-a-resource-group]

<ApiEndpoint name="fetchResourceGroup" title="Fetch a Resource Group" />

<ApiSchema name="ResourceGroupResponse" />

Fetch all Resource Groups [#fetch-all-resource-groups]

<ApiEndpoint name="fetchResourceGroups" title="Fetch all Resource Groups" />

<ApiSchema name="ResourceGroupListResponse" />

Create a Resource Group [#create-a-resource-group]

<ApiEndpoint name="createResourceGroup" title="Create a Resource Group" />

<ApiSchema name="ResourceGroupCreateRequest" />

Update a Resource Group [#update-a-resource-group]

<ApiEndpoint name="updateResourceGroup" title="Update a Resource Group" />

<ApiSchema name="ResourceGroupUpdateRequest" />

Retire a ResourceGroup [#retire-a-resourcegroup]

<ApiEndpoint name="retire" title="Retire a ResourceGroup" />

Resources [#resources]

Fetch a Resource [#fetch-a-resource]

<ApiEndpoint name="fetchResource" title="Fetch a Resource" />

<ApiSchema name="ResourceResponse" />

<ApiSchema name="BasicResourceResponse" />

Fetch Multiple Resources [#fetch-multiple-resources]

<ApiEndpoint name="fetchMultipleResources" title="Fetch Multiple Resources" />

Fetch Multiple Resources by Type [#fetch-multiple-resources-by-type]

<ApiEndpoint name="fetchMultipleResourcesByType" title="Fetch Multiple Resources by Type" />

<ApiSchema name="ResourceListResponse" />

<ApiSchema name="TemplateResponse" />

Resource Locking [#resource-locking]

Fetch Resource Selections [#fetch-resource-selections]

<ApiEndpoint name="getResourceSelections" title="Fetch Resource Selections" />

<ApiSchema name="ResourceResponse" />

Lock Resource Selection [#lock-resource-selection]

<ApiEndpoint name="lockResourceSelection" title="Lock Resource Selection" />

Unlock Resource Selection [#unlock-resource-selection]

<ApiEndpoint name="unlockResourceSelection" title="Unlock Resource Selection" />

Unlock Resource Selections [#unlock-resource-selections]

<ApiEndpoint name="unlockResourceSelections" title="Unlock Resource Selections" />


## API Reference

GET /resource/{tenantLocator}/groups/{locator} — fetchResourceGroup
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 ResourceGroupResponse — OK

GET /resource/{tenantLocator}/groups/list — fetchResourceGroups
Permissions: list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
  excludeRetired (boolean, query) — Default value true.
  excludeActive (boolean, query) — Default value false.
Responses:
  200 ResourceGroupListResponse — OK

POST /resource/{tenantLocator}/groups — createResourceGroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (ResourceGroupCreateRequest):
Responses:
  200 ResourceGroupResponse — OK

PATCH /resource/{tenantLocator}/groups/{locator} — updateResourceGroup
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (ResourceGroupUpdateRequest):
Responses:
  200 ResourceGroupResponse — OK

PATCH /resource/{tenantLocator}/groups/{locator}/retire — retire
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 — OK

GET /resource/{tenantLocator}/resources/{name} — fetchResource
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  byStaticName (boolean, query)
  date (datetime, query)
  jurisdiction (string, query)
Responses:
  200 ResourceResponse — OK

GET /resource/{tenantLocator}/resources/list — fetchMultipleResources
Permissions: list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 ResourceListResponse — OK

GET /resource/{tenantLocator}/resources/type/{type}/list — fetchMultipleResourcesByType
Permissions: list
Parameters:
  tenantLocator (uuid, path, required)
  type (string, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query) — When false, returns a bare array.
Responses:
  200 ResourceListResponse — OK

GET /resource/{tenantLocator}/resources/locks/{referenceLocator} — getResourceSelections
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  referenceLocator (ulid, path, required)
Responses:
  200 — OK

POST /resource/{tenantLocator}/resources/locks/{referenceLocator}/{resourceName} — lockResourceSelection
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  referenceLocator (ulid, path, required)
  resourceName (string, path, required)
Responses:
  200 — OK

DELETE /resource/{tenantLocator}/resources/locks/{referenceLocator}/{staticName} — unlockResourceSelection
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  referenceLocator (ulid, path, required)
  staticName (string, path, required)
Responses:
  200 — OK

DELETE /resource/{tenantLocator}/resources/locks/{referenceLocator} — unlockResourceSelections
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  referenceLocator (ulid, path, required)
Responses:
  200 — OK

ResourceGroupResponse
Properties:
  locator (ulid, required)
  name (string, required)
  retired (boolean, required)
  selectionStartTime (datetime, required)
  resourceNames (string[], required)
  createdBy (uuid, required)
  createdAt (datetime, required)

ResourceGroupListResponse
Properties:
  listCompleted (boolean, required)
  items (ResourceGroupResponse[], required)

ResourceGroupCreateRequest
Properties:
  name (string, required)
  selectionStartTime (datetime, required)
  resourceNames (string[], required)

ResourceGroupUpdateRequest
Properties:
  name (string, required)
  selectionStartTime (datetime, required)
  removeResources (string[], required)
  addResources (string[], required)

ResourceResponse
Properties:
  name (string, required)
  staticName (string)
  resourceType (Enum constraintTable | customFont | documentTemplate | documentTemplateSnippet | rangeTable | secret | staticDocument | table, required)
  lookupTableLocator (ulid)
  template (string)
  staticDocumentLocator (ulid)
  templateFormat (Enum liquid | velocity)
  createdBy (uuid, required)
  createdAt (datetime, required)
  scope (Enum transaction | policy | term | segment | invoice)
  trigger (Enum validated | priced | accepted | underwritten | issued | generated | declined | rejected | refused)
  format (Enum text | html | pdf | jpg | jpeg | doc | docx | xls | xlsx | csv | txt | zip)
  rendering (Enum dynamic | prerendered)
  jurisdictions (string[], required)

BasicResourceResponse
Properties:
  name (string, required)
  staticName (string)
  resourceType (Enum constraintTable | customFont | documentTemplate | documentTemplateSnippet | rangeTable | secret | staticDocument | table, required)
  lookupTableLocator (ulid)
  rangeTableLocator (ulid)
  constraintTableLocator (ulid)
  template (string)
  staticDocumentLocator (ulid)
  fontLocator (ulid)
  riskAssessmentCriteriaLocator (ulid)
  uiConfigLocator (ulid)
  templateFormat (Enum liquid | velocity)
  createdBy (uuid, required)
  createdAt (datetime, required)
  jurisdictions (string[], required)

ResourceListResponse
Properties:
  listCompleted (boolean, required)
  items (ResourceResponse[], required)

TemplateResponse
Properties:
  file (object)
  template (string)

# Secrets API



<EndpointIndex
  names={['fetchSecret', 'createSecret', 'updateSecret', 'deleteSecret']}
  titles={{
  	fetchSecret: 'Fetch a Secret',
  	createSecret: 'Create a Secret',
  	updateSecret: 'Update a Secret',
  }}
/>

Fetch a Secret [#fetch-a-secret]

<ApiEndpoint name="fetchSecret" title="Fetch a Secret" />

<ApiSchema name="SecretResponse" />

Create a Secret [#create-a-secret]

<ApiEndpoint name="createSecret" title="Create a Secret" />

<ApiSchema name="SecretCreateRequest" />

Update a Secret [#update-a-secret]

<ApiEndpoint name="updateSecret" title="Update a Secret" />

Delete Secret [#delete-secret]

<ApiEndpoint name="deleteSecret" />


## API Reference

GET /resource/{tenantLocator}/secrets/{name} — fetchSecret
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  byStaticName (boolean, query)
  date (datetime, query)
  jurisdiction (string, query)
Responses:
  200 SecretResponse — OK

POST /resource/{tenantLocator}/secrets — createSecret
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (SecretCreateRequest):
Responses:
  200 SecretResponse — OK

PATCH /resource/{tenantLocator}/secrets/{name} — updateSecret
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Request body (map<string, object>):
Responses:
  200 SecretResponse — OK

DELETE /resource/{tenantLocator}/secrets/{name} — deleteSecret
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 — OK

SecretResponse
Properties:
  resource (BasicResourceResponse, required)
  secret (object, required)

SecretCreateRequest
Properties:
  name (string, required)
  staticName (string, required)
  jurisdictions (string[], required)
  secret (map<string, object>, required)

# Tables API



<Callout>
  *Data Tables* are used in plugins to support calculations. *Constraint Tables* are used to support UI development by filtering options for the user.
</Callout>

<EndpointIndex
  names={[
  	'fetchTableRecord',
  	'fetchLookupTableInZipFormat',
  	'createLookupTable',
  	'replaceLookupTable',
  	'fetchRangeTableRecord',
  	'fetchRangeTableInZipFormat',
  	'createRangeTable',
  	'replaceRangeTable',
  	'evaluateConstraintsForAccount',
  	'fetchDependencyMapForAccount',
  	'fetchDependencyMapForQuote',
  	'evaluateConstraintsForQuote',
  	'evaluateConstraintsForQuickQuote',
  	'fetchDependencyMapForQuickQuote',
  	'fetchDependencyMapForPolicyTransaction',
  	'evaluateConstraintsForPolicyTransaction',
  	'fetchConstraints',
  	'createConstraintTable',
  	'replaceConstraintTable',
  	'zipConstraintTable',
  ]}
  titles={{
  	fetchTableRecord: 'Fetch a Table Record',
  	fetchLookupTableInZipFormat: 'Fetch a Lookup Table in ZIP Format',
  	createLookupTable: 'Create a Lookup Table',
  	replaceLookupTable: 'Replace a Lookup Table',
  	fetchRangeTableRecord: 'Fetch a Range Table Record',
  	fetchRangeTableInZipFormat: 'Fetch a Range Table in ZIP Format',
  	createRangeTable: 'Create a Range Table',
  	replaceRangeTable: 'Replace a Range Table',
  }}
/>

Data Tables [#data-tables]

Usage [#usage]

Fetch a Table Record [#fetch-a-table-record]

<ApiEndpoint name="fetchTableRecord" title="Fetch a Table Record" />

<ApiSchema name="TableLookupResponse" />

Configuration [#configuration]

Fetch a Lookup Table in ZIP Format [#fetch-a-lookup-table-in-zip-format]

<ApiEndpoint name="fetchLookupTableInZipFormat" title="Fetch a Lookup Table in ZIP Format" />

Create a Lookup Table [#create-a-lookup-table]

<ApiEndpoint name="createLookupTable" title="Create a Lookup Table" />

<Callout type="warn">
  Files must be converted to ZIP files before uploading.
</Callout>

Replace a Lookup Table [#replace-a-lookup-table]

<ApiEndpoint name="replaceLookupTable" title="Replace a Lookup Table" />

<Callout type="warn">
  Files must be converted to ZIP files before uploading.
</Callout>

Range Tables [#range-tables]

Usage [#usage-1]

Fetch a Range Table Record [#fetch-a-range-table-record]

<ApiEndpoint name="fetchRangeTableRecord" title="Fetch a Range Table Record" />

Configuration [#configuration-1]

Fetch a Range Table in ZIP Format [#fetch-a-range-table-in-zip-format]

<ApiEndpoint name="fetchRangeTableInZipFormat" title="Fetch a Range Table in ZIP Format" />

Create a Range Table [#create-a-range-table]

<ApiEndpoint name="createRangeTable" title="Create a Range Table" />

<Callout type="warn">
  Files must be converted to ZIP files before uploading.
</Callout>

Replace a Range Table [#replace-a-range-table]

<ApiEndpoint name="replaceRangeTable" title="Replace a Range Table" />

<Callout type="warn">
  Files must be converted to ZIP files before uploading.
</Callout>

<span id="constraint_tables_api" />

Constraint Tables [#constraint-tables]

Accounts [#accounts]

Evaluate Constraints For Account [#evaluate-constraints-for-account]

<ApiEndpoint name="evaluateConstraintsForAccount" />

Fetch Dependency Map For Account [#fetch-dependency-map-for-account]

<ApiEndpoint name="fetchDependencyMapForAccount" />

Quotes [#quotes]

Fetch Dependency Map For Quote [#fetch-dependency-map-for-quote]

<ApiEndpoint name="fetchDependencyMapForQuote" />

<ApiSchema name="ConstraintDependency" />

<ApiSchema name="ConditionValue" />

Evaluate Constraints For Quote [#evaluate-constraints-for-quote]

<ApiEndpoint name="evaluateConstraintsForQuote" />

Quick Quotes [#quick-quotes]

Evaluate Constraints For Quick Quote [#evaluate-constraints-for-quick-quote]

<ApiEndpoint name="evaluateConstraintsForQuickQuote" />

Fetch Dependency Map For Quick Quote [#fetch-dependency-map-for-quick-quote]

<ApiEndpoint name="fetchDependencyMapForQuickQuote" />

Policy Transactions [#policy-transactions]

Fetch Dependency Map For Policy Transaction [#fetch-dependency-map-for-policy-transaction]

<ApiEndpoint name="fetchDependencyMapForPolicyTransaction" />

Evaluate Constraints For Policy Transaction [#evaluate-constraints-for-policy-transaction]

<ApiEndpoint name="evaluateConstraintsForPolicyTransaction" />

Configuration [#configuration-2]

Fetch Constraints [#fetch-constraints]

<ApiEndpoint name="fetchConstraints" />

Create Constraint Table [#create-constraint-table]

<ApiEndpoint name="createConstraintTable" />

<Callout type="warn">
  Files must be converted to ZIP files before uploading.
</Callout>

Replace Constraint Table [#replace-constraint-table]

<ApiEndpoint name="replaceConstraintTable" />

<Callout type="warn">
  Files must be converted to ZIP files before uploading.
</Callout>

Zip Constraint Table [#zip-constraint-table]

<ApiEndpoint name="zipConstraintTable" />


## API Reference

GET /resource/{tenantLocator}/tables/{name}/record — fetchTableRecord
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  date (datetime, query)
  jurisdiction (string, query)
  byStaticName (boolean, query)
  key (string[], query, required)
Responses:
  200 TableLookupResponse — OK

GET /resource/{tenantLocator}/tables/{name} — fetchLookupTableInZipFormat
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 — OK

POST /resource/{tenantLocator}/tables — createLookupTable
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/tables/{name} — replaceLookupTable
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 BasicResourceResponse — OK

GET /resource/{tenantLocator}/rangeTables/{name}/record — fetchRangeTableRecord
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  date (datetime, query)
  jurisdiction (string, query)
  byStaticName (boolean, query)
  key (string[], query, required)
  boundValue (number, query, required)
Responses:
  200 TableLookupResponse — OK

GET /resource/{tenantLocator}/rangeTables/{name} — fetchRangeTableInZipFormat
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 — OK

POST /resource/{tenantLocator}/rangeTables — createRangeTable
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/rangeTables/{name} — replaceRangeTable
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 BasicResourceResponse — OK

POST /policy/{tenantLocator}/accounts/{locator}/constraints/evaluate — evaluateConstraintsForAccount
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, map<string, string>>):
Responses:
  200 map<string, map<string, string[]>> — OK

GET /policy/{tenantLocator}/accounts/{locator}/constraints/dependency — fetchDependencyMapForAccount
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, map<string, ConstraintDependency>> — OK

GET /policy/{tenantLocator}/quotes/{locator}/constraints/dependency — fetchDependencyMapForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, map<string, ConstraintDependency>> — OK

POST /policy/{tenantLocator}/quotes/{locator}/constraints/evaluate — evaluateConstraintsForQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, map<string, map<string, string>>>):
Responses:
  200 map<string, map<string, string[]>> — OK

POST /policy/{tenantLocator}/quickquotes/{locator}/constraints/evaluate — evaluateConstraintsForQuickQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, map<string, map<string, string>>>):
Responses:
  200 map<string, map<string, string[]>> — OK

GET /policy/{tenantLocator}/quickquotes/{locator}/constraints/dependency — fetchDependencyMapForQuickQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, map<string, ConstraintDependency>> — OK

GET /policy/{tenantLocator}/transactions/{locator}/elements/constraints/dependency — fetchDependencyMapForPolicyTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 map<string, map<string, ConstraintDependency>> — OK

POST /policy/{tenantLocator}/transactions/{locator}/elements/constraints/evaluate — evaluateConstraintsForPolicyTransaction
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Request body (map<string, map<string, map<string, string>>>):
Responses:
  200 map<string, map<string, string[]>> — OK

GET /resource/{tenantLocator}/constraints/{name}/record — fetchConstraints
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
  date (datetime, query)
  jurisdiction (string, query)
  byStaticName (boolean, query)
  key (string[], query)
Responses:
  200 map<string, object[]> — OK

POST /resource/{tenantLocator}/constraints — createConstraintTable
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, query, required)
  staticName (string, query, required)
  jurisdiction (string[], query)
Responses:
  200 BasicResourceResponse — OK

PATCH /resource/{tenantLocator}/constraints/{name} — replaceConstraintTable
Permissions: upload
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 BasicResourceResponse — OK

GET /resource/{tenantLocator}/constraints/{name} — zipConstraintTable
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  name (string, path, required)
Responses:
  200 — OK

TableLookupResponse
Properties:
  value (object, required)

ConstraintDependency
Properties:
  table (string, required)
  column (string, required)
  where (map<string, ConditionValue>, required)

ConditionValue
Properties:
  staticLocator (ulid, required)
  fieldName (string, required)
  values (string[], required)

# Custom Data Types



[Data extensions](/configuration/data-extensions/overview) can be defined using custom data types in addition to [built-in data types](/configuration/data-extensions/data-extension-types) such as `string` and `int`.

Usage [#usage]

For example, rather than adding properties to an auto policy such as `driverName1`, `driverName2`, `driverLicense`, `driverLicense2`, and then having to guess how many of each of these you will need, you could do the following:

* First, create a custom data type called `Driver` by adding this to the configuration:

```json
{
    "dataTypes": {
        "Driver": {
            "data": {
                "firstName": { "type": "string" },
                "lastName": { "type": "string" },
                "licenseNumber": { "type": "string", "maxLength: 20" },
                "licenseState": { "type": "string", "maxLength": 2 }
            }
        }
    }
}
```

* Then, for your `policy` element (or any element) in the configuration for the auto product, declare a property that uses the type `Driver` in its extension data:

```json
{
    "products": {
        "personalAuto": {
            "data": [
                "drivers": { "type": "Driver+" }
            ],
            "contents": "vehicle+"
        }
    }
}
```

As shown in the example above, you may use [quantifiers](/configuration/general-topics/quantifiers) such as `+` with custom data types. This includes the automatic creation quantifier `!`, which should be used if you want an item of your custom type to be created automatically. The platform does not infer the intent for automatic creation, even if all the custom type's fields have default values.

Custom Data Inheritance [#custom-data-inheritance]

Custom data types can use inheritance, similar to how elements and accounts can use inheritance to keep related types simpler to manage. Common information is put in a base and the differences expressed with individual declarations.

For example, maybe you want to have two different types of people in your system, with the general "Person" having just names, but a "Driver" adding driver's license information. You could do that as follows:

First, declare the `Person` type:

```json
"Person": {
    "data": {
        "firstName": {
            "type": "string"
        },
        "lastName": {
            "type": "string"
        }
    }
}
```

And then extend `Person` with added properties in a `Driver`:

```json
"Driver": {
    "extends": "Person",
    "data": {
        "licenseNumber": {
            "type": "string",
            "maxLength: 20"
        },
        "licenseState": {
            "type": "string",
            "maxLength": 2
        }
    }
}
```

Inheritance can be many levels deep. You could extend `Driver` to manage a `CommercialDriver` type:

```json
"CommercialDriver": {
    "extends": "Driver",
    "data": {
        "stateQualificationExamDate": {
            "type":
            "date"
        },
    }
}
```

Each custom type will have its properties validated in the same way as for built-in types. Custom types are also available for inspection and validation using the Validation Plugin.


# Extension Data Constraints



Overview [#overview]

*Extension Data Constraints* are a tool to help ensure that extension data fields that are related are persisted in valid combinations. For example, suppose you had a table of vehicle data like this:

**Vehicles**

| Make   | Model   | Year |
| ------ | ------- | ---- |
| Ford   | Mustang | 2020 |
| Ford   | Mustang | 2021 |
| Ford   | F150    | 2021 |
| Toyota | Camry   | 2020 |
| Toyota | Camry   | 2021 |
| Toyota | Camry   | 2022 |

In this case, if the user first chooses *Ford* as the Make, then you would want to present only *Mustang* and *F150* as options for Model, and not *Camry*. Likewise, if the user then selects *F150* for the Model, they should be constrained to select only *2021* as the Year, and not *2020*.

Extension Data Constraints support this sort of constraint building for user interfaces, and can also be used as a validation step to ensure that data created outside of the normal UI also conforms to the constraints desired (though this validation can be bypassed if needed.)

Structure [#structure]

Data Constraints may be simple (such as constraining the value of a field based on the value of another field on that same element), or complex, where the interdependent fields are on completely different elements within the policy structure. The components used are:

* **Configuration**, where you declare dependencies, using a path structure
* **Dependency Maps**, which are generated for segments based on the actual data in a segment
* **Filter Evaluation API**, which will compute allowed values for fields based on existing or prospective updated data
* **Constraint Tables**, which are a special kind of [table](/api/resources/tables#constraint_tables_api) used for defining valid combinations of data
* **Extended Validation**, which can ensure that data on the segment meets constraint requirements, regardless of whether it originated in a UI

Configuration [#configuration]

Each <ApiLink name="PropertyRef">property</ApiLink> in a data extension has a <ApiLink name="PropertyConstraint">constraint</ApiLink> field, which defines:

* The name of the `table` that contains the valid combinations
* The `column` of the table that has valid values for that particular field
* The `where` clause, which contains constraints for other columns in the table, or a static list of allowed values

For example, a configuration might include the following field declarations within a `vehicle` element declaration:

```json
{
	"vehicleMake": {
		"type": "string",
		"constraint": {
			"table": "vehicle_data",
			"column": "make_name"
		}
	},
	"vehicleModel": {
		"type": "string",
		"constraint": {
			"table": "vehicle_data",
			"column": "model_name",
			"where": {
				"make_name": {
					"key": "vehicleMake"
				}
			}
		}
	},
	"vehicleYear": {
		"table": "vehicle_data",
		"column": "year",
		"where": {
			"make_name": {
				"key": "vehicleMake"
			},
			"model_name": {
				"key": "vehicleModel"
			}
		}
	}
}
```

In this example, we declare that:

* The vehicle make must be one of the values in the `vehicle_data` table's `make_name` column.
* The model must be one of the values in the `model_name` column of that same table, but only including those rows that have `make_name` matching the make selected by the user.
* The year must be one of the values in the `year` column of the table, but only including those rows that have `make_name` matching the selected make *and* `model_name` matching the selected model.

Dependency Maps [#dependency-maps]

After a quote or policy transaction is created, the UI can call the <ApiLink name="fetchDependencyMapForQuote" /> or <ApiLink name="fetchDependencyMapForPolicyTransaction" /> endpoint. The result will be the *Dependency Map*, which describes the dependencies and constraints that apply for that quote or policy transaction.

A DependencyMap is a nested map that references <ApiLink name="ConstraintDependency" /> objects, each of which has the same structure as the constraints in configuration. The difference is that each of these is referenced by the actual locator of data for the quote or policy transaction. For example, a dependency map using the above configuration might look like this:

```json
{
  "01HTKMYZ0W7QT7VMSMMCFQNT1Q": {
    "vehicleMake": {
      "table": "vehicle_data",
      "column": "make_name"
    },
    "vehicleModel": {
      "table": "vehicle_data",
      "column": "model_name",
      "where": {
        "make_name": {
          "fieldName": "vehicleMake",
          "staticLocator": "01HTKMYZ0W7QT7VMSMMCFQNT1Q"
        }
    },
    "vehicleYear": {
      "table": "vehicle_data",
      "column": "year",
      "where": {
        "make_name": {
           "fieldName": "vehicleMake",
           "staticLocator": "01HTKMYZ0W7QT7VMSMMCFQNT1Q"
        },
        "model_name": {
          "fieldName": "vehicleModel",
          "staticLocator": "01HTKMYZ0W7QT7VMSMMCFQNT1Q"
        }
      }
    }
  }
}
```

This map indicates that:

* The only element that has constrained data is the vehicle, which has a `staticLocator` of `01HTKMYZ0W7QT7VMSMMCFQNT1Q`.
* The vehicle make is still dependant on the table data only, as declared in the configuration
* The vehicle model has the same table dependency but also only rows with a `make_name` that equal the `vehicleMake` property for that vehicle will be considered.
* The vehicle year is similar but will only match rows with a matching make name (like the model), but also where `model_name` matches the `vehicleModel` on the element.

Now, with the dependency map, the UI has enough information to ask Socotra what the *actual* allowed values should be for the make and model fields.

<Callout>
  When adding elements, the client should fetch a new dependency map if any of those elements could affect constraint processing in the UI.
</Callout>

Constraint Evaluation API [#constraint-evaluation-api]

The UI can use the dependency map, together with the values selected so far by the user, in order to get updates of what values are valid for remaining inputs. This is done by calling the <ApiLink name="evaluateConstraintsForQuote" /> or <ApiLink name="evaluateConstraintsForPolicyTransaction" /> endpoints.

For example, with the dependency map above, the UI could send this request:

```json
{
	/* as received earlier */
	"01HTKMYZ0W7QT7VMSMMCFQNT1Q": {
		"vehicleMake": {},
		"vehicleModel": {},
		"vehicleYear": {}
	},
	"01HTKN7Y5PSYF0D95RWTTZ88QT": {}
}
```

In this case, the user hasn't selected anything yet, and so the response is basic:

```json
{
  "01HTKMYZ0W7QT7VMSMMCFQNT1Q": {
    "vehicleMake": ["Toyota", "Ford"]
}
```

The system has determined that the `vehicleMake` options are fully determined since they only depend on table data, and there are no `where` restrictions, so all values found in the table are valid from the beginning. In contrast, the `vehicleModel` selection *does* depend on the `vehicleMake`, and since there are no rows with an empty `vehicleMake` value, there are no matches for the inputs, so there are no valid values returned.

Constraint Evaluation for Accounts [#constraint-evaluation-for-accounts]

Accounts do not require the specification of top-level element locators, so the call to the constraint evaluation is simpler. This difference is suggested by the request body formally specified in the [Tables API](/api/resources/tables), but the contrast can be illustrated in this simple example:

*Request:*

```json
{
	"make": {}
}
```

*Response:*

```json
{
	"01JKVQE9G9GG6Y1NY6VVXJ7W8X": {
		"make": ["Audi", "honda", "toyota"]
	}
}
```

<Callout>
  When there are no values returned for a particular field, the UI could be programmed to disable or hide those fields depending on the user experience they require.
</Callout>

<Callout type="warn">
  If a value is *not* included in the evaluation request, the system will defer to the currently persisted value of the element to fill those values. This behavior may change to treating those cases as having "no value" as described above.
</Callout>

After the user chooses a vehicle make, such as *Ford*, the UI can update the evaluation request as follows:

```json
{
	/* this hasn't changed from the earlier request */
	"01HTKMYZ0W7QT7VMSMMCFQNT1Q": {
		"vehicleModel": {
			"make_name": "Ford"
		}
	}
}
```

And the response is:

```json
{
	"vehicleMake": ["Toyota", "Ford"],
	"vehicleModel": ["Mustang", "F150"]
}
```

Or set the `data.vehicleMake` in the quote/transaction data extension, save and now the value is used:

```json
/* quote or transaction data extension field */
{
	"data": {
		"vehicleMake": "Toyota"
	}
}
```

```json
{
	/* quote/transaction: data.vehicleMake field value is automatically used */
	"01HTKMYZ0W7QT7VMSMMCFQNT1Q": {
		"vehicleMake": {},
		"vehicleModel": {}
	}
}
```

And the response is:

```json
{
	"vehicleMake": ["Toyota", "Ford"],
	"vehicleModel": ["Camry"]
}
```

The system determined that `vehicleModel` has a valid match with the input value from quote or transaction `Toyota`.

Referencing Other Elements [#referencing-other-elements]

When specifying the reference field that constrains another field, that reference field does not have to be in the same element. If only its name is included in the `key` property, it refers to that field on the same element. If prefixed with `..`, such as `"../driverPoints"`, the constraint comes from the `driverPoints` field on the *parent* element. These can be chained; for example, `../../driverPoints` refers to the `driverPoints` field on the parent's parent element.

The root (product) element can be referred to by prefixing a slash, such as `/driverPoints`.

Validation [#validation]

The discussion above refers to the up-front process used while the quote or policy transaction is still in `draft` state. When the user has made their selections, the transaction can proceed to the `validated` state. By default, the system will apply the constraints implied by the configuration and constraint tables to ensure that the actual data meets the constraints, even if the origin of the data was not the UI.

<Callout type="warn">
  The ability to bypass this validation is not yet present, but will be added in an upcoming release.
</Callout>


# Data Extension Types



Overview [#overview]

This topic discusses the types of data that can be used with configured [data extensions](/configuration/data-extensions/overview).

<span id="built-in-types" />

Built-In Data Types [#built-in-data-types]

These data types are supported without additional configuration:

* `string`: A string, or enum-like type with a fixed set of possible values, set with the options property for the type
* `int` : A 32-bit signed integer
* `long`: A 64-bit signed integer
* `decimal`: A floating point number with arbitrary precision, which internally uses base 10 representation and so is appropriate for financial calculations
* `datetime`: A value that includes a date and a time
* `date`: The same as `datetime` except that no time component is included
* `boolean`: A datatype that can have either the value `true` or `false`
* `object`: An object that can contain multiple properties

<Callout>
  - The type can be omitted. If so, the default type of `string` will be used.
  - Booleans can take a number `0` or `1`, which will be interpreted as `false` or `true`, respectively.
</Callout>

Date Types [#date-types]

datetime [#datetime]

The `datetime` type includes a date and a time, with precision to milliseconds, and includes a time-zone context, which by default will be the policy's time zone. In the API, these are passed as strings using ISO8601 format, such as `"2023-07-15T12:30:00−07:00"`.

Clients may express datetime values with any time zone, but they will be handled according to the time zone for the quote or policy. For example, if the time zone for a policy is `America/Los_Angeles` but a `startTime` of `2023-07-15T00:00:00Z` (which specifies UTC), then the start time of the policy will be July 15, 2023, at 8AM (which equals midnight in UTC).

<Callout>
  ISO 8601 allows for times to be expressed to milliseconds precision, such as `2023-07-15T12:30:00.444−07:00`. The milliseconds component is optional and will be interpreted as zero if it is not included.
</Callout>

date [#date]

The `date` is the same as `datetime` except that no time or time zone component is included. These are passed by a string such as `"2023-04-15"`.

object [#object]

The `object` type can contain multiple properties. Object properties cannot be defined in tenant configurations.

Custom Data Types [#custom-data-types]

Along with built-in data types, you can use *custom* data types to manage more complicated or specialized data.

See the [Custom Data Types](/configuration/data-extensions/custom-data-types) topic for details.

Limitations [#limitations]

* `string` types are limited to a maximum of 20,000 characters.


# Data Extensions



Overview [#overview]

Entities such as accounts, quotes, and policies can contain custom data properties. These entities will include a `data` property when accessed through the API or plugins, which contains data that was set for the entity in accordance with the configuration.

For example, a `vehicle` element might have the following configuration:

```json
{
	"data": {
		"make": {
			"displayName": "Make",
			"type": "string",
			"scope": "Q,P"
		},
		"model": {
			"displayName": "Model",
			"type": "string",
			"scope": "Q,P"
		},
		"year": {
			"displayName": "Year",
			"type": "int",
			"scope": "Q,P"
		},
		"vin": {
			"displayName": "VIN",
			"type": "string",
			"scope": "Q,P"
		}
	}
}
```

Here's an example of what the `data` values would look like when a `vehicle` element is created:

```json
{
	"data": {
		"make": "Toyota",
		"model": "Camry",
		"year": 2020,
		"vin": "4T1M11AK9LU893499"
	}
}
```

[Segment](/getting-started/execute-policy-transactions#segments)-specific `data` and `data` associated with [policy transactions](/features/policy-management/policy-transactions) through <ApiLink name="TransactionDataChangeInstructionCreateRequest">TransactionDataChangeInstructionCreateRequest</ApiLink> objects or the <ApiLink name="patchTransactionData">Patch Transaction Data</ApiLink> API endpoint are only mutable when a policy transaction is in the `draft` state.

<span id="data-scopes" />

Data Scopes [#data-scopes]

Each data property has an associated scope. In configuration, the scope is specified with a string such as `"scope": "Q, P"`. These are the `scope` options:

* `QQ`: The property is associated with [Quick Quotes](/features/policy-quotation/quick-quotes)
* `Q`: The property is associated with Quotes
* `P`: The property is associated with Policies

Because quotes must have all the data required to issue a policy, a data scope of `P` must also have `Q`.

Data Types [#data-types]

Each property is declared with a data type. There are several built-in data types that can be used, or you may define your own custom types. See the [Data Extension Types](/configuration/data-extensions/data-extension-types) topic for details.

<Callout>
  If the type is not specified for a given data property, the default of `string` will be used.
</Callout>

Quantifiers and Arrays [#quantifiers-and-arrays]

Each property type may be modified by the use of a [quantifier](/configuration/general-topics/quantifiers), which specifies how many of the given value the property may store. The valid quantifiers for a data extension property type are:

* (no suffix): The value is scalar and not `null` (i.e. it has exactly one value)
* `?`: The value is scalar but may be `null`
* `+`: The value is an array with *one or more* values of the given type
* `*`: The value is an array with *any number* of values of the given type

If you have a property with base type `int`, which can store an integer, the type could be declared as any of:

* `int`: `0`, `42`, and `-13` are all valid values, but `null` is not
* `int?`: Like `int` but also allows `null`
* `int+`: `[0, 1]`, and `[-13, 42, 103]` are valid values.
* `int*`: `[]`, `[0, 1]`, and `[-13, 42, 103]` are valid values. Note that the `*` does not permit a `null` array; but the array can be empty.

Validation Requirements [#validation-requirements]

You may specify additional requirements for data properties:

| Property    | Applicable Type(s) | Details                                                         |
| ----------- | ------------------ | --------------------------------------------------------------- |
| `min`       | numerical          | The minimum allowed value.                                      |
| `max`       | numerical          | The maximum allowed value.                                      |
| `minLength` | strings            | The minimum string length.                                      |
| `maxLength` | strings            | The maximum string length.                                      |
| `regex`     | strings            | The regular expression pattern to which the value must conform. |
| `options`   | strings            | The array of strings from which the value may be selected.      |

`regex` provides powerful basic validation that the platform can enforce for you; for example, you may use a regex pattern to specify the acceptable shape for a string representing a legal identifier in a particular locale:

```json
{
	"data": {
		"insureds_socialSecurityNumber": {
			"displayName": "Social Security Number",
			"type": "string",
			"regex": "[0-9]{3}[-][0-9]{2}[-][0-9]{4}",
			"maxLength": 11
		}
	}
}
```

Other Data Properties [#other-data-properties]

You may add additional properties to your data:

| Property       | Applicable Type(s) | Details                                                                              |
| -------------- | ------------------ | ------------------------------------------------------------------------------------ |
| `tag`          | all                | An array of metadata strings for all fields - generally consumed by UI clients.      |
| `precision`    | long \| decimal    | An integer specifying the number of places to persist floating-point numeric values. |
| `roundingMode` | long \| decimal    | The rounding mode to be employed when rounding of the value is invoked.              |
| `defaultValue` | all                | The value to be used if a required field is absent upon validation.                  |

```json
{
  "data": {
    "vechile_class_risk_factor": {
      "type": "decimal",
      "max": "1",
      "min": "0",
      "precision": 7,
      "roundingMode": "halfUp",
      "tag": ["tab1", "uneditable"]
    }
  }
```

Comprehensive Properties List [#comprehensive-properties-list]

* `displayName`
* `type`
* `scope`
* `defaultValue`
* `min`
* `max`
* `minLength`
* `maxLength`
* `precision`
* `roundingMode`
* `options`
* `regex`
* `tag`

See Also [#see-also]

* [Data Extension Types](/configuration/data-extensions/data-extension-types)
* [Identifiers](/configuration/general-topics/identifiers)
* [Quantifiers](/configuration/general-topics/quantifiers)


# Static Data



Overview [#overview]

Some information that pertains to quotes, policies, and other entities need not be governed by the data revision rules of policy transactions. Static Data supports the management of such information.

Context and Use Cases [#context-and-use-cases]

Static Data was designed to enable customers to capture context-setting, structured data as they saw fit, and to manage such data without having to execute policy transactions.

Some use cases include:

* Capturing a custom quote name generated externally
* Capturing a custom quote or policy number generated externally
* Capturing contact data related to a quote or policy
* Capturing diaries or notes about a quote or transaction

While Static Data remains a viable approach for managing such context data, Socotra now supports many of these use cases through a variety of targeted features, including;

* [Custom Entity Numbering](/configuration/general-topics/entity-numbering)
* [Contact Management](/features/contacts)
* [Diaries](/features/work-management/diaries)

A common question is, "How does static data differ from [Auxiliary Data](/api/aux-data/aux-data)?". There are several key distinctions:

* Static data is declared in configuration and is explicitly associated with the root element of a product.
* The extension data approach to this configuration gives static data a highly defined structure.
* Data can be set as part of a quote create request (can also be set and modified directly).
* Data can be retrieved as part of a quote or policy fetch request (can also be retrieved directly).
* Auxiliary data has none of these properties.

Configuration [#configuration]

You may configure up to ten fields of static data at the root element of any given product definition.

Configuration is the same as for regular extension data, but fields are defined within the `staticData` property of the <ApiLink name="ProductRef" />.

**Configuration Example**

```json
{
    "products": {
        "exampleProduct": {
            "displayName" : "Example Product",
            // other product configuration properties
            "data" : {"someExtensionDataConfig"},
            "staticData" : {
                "applicationNumber" : {
                        "displayName" : "Application Number",
                        "type" : "string",
                        "maxLength" : 20000,
                        "searchable" : true
                },
                "paidThroughDate" : {
                        "displayName" : "Paid Through Date",
                        "type" : "date"
                }
            }
        }
    }
}
```

Usage - Quotes [#usage---quotes]

Setting Static Data [#setting-static-data]

Static Data can be included when <ApiLink name="createQuote">creating a quote</ApiLink> via a <ApiLink name="QuoteCreateRequest" />:

**Example: Add Static Data at Quote Creation**

```
POST /policy/{tenantLocator}/quotes
```

```json
{
    "productName": "exampleProduct",
    "accountLocator": "abc123def456"
    "elements": [],
    "static": {
        "applicationNumber": "eAPP-0000001",
        "paidThroughDate": "2020-01-01"
    }
}
```

**Example: Add Static Data to a Validated Quote**

Static fields and values can be added or updated even after a quote has been validated and its structure and data have become immutable.

Adding Static Data to an existing quote after creation, including post-validation, can be done via the <ApiLink name="addStaticDataForQuote">addStaticDataForQuote</ApiLink> request.

```
POST /policy/{tenantLocator}/quotes/{locator}/static
```

```json
{
	"applicationNumber": "eAPP-0000005",
	"paidThroughDate": "2025-03-03"
}
```

**Example: Update Static Data on a Validated Quote**

To update the existing Static Data of a quote use the <ApiLink name="updateStaticDataForQuote">updateStaticDataForQuote</ApiLink> endpoint:

```
PATCH /policy/{tenantLocator}/quotes/{locator}/static
```

```json
{
    "removeData": {
        "applicationNumber": "eAPP-0000005",
    }
    "setData": {
        "paidThroughDate": "2027-04-17"
    }
}
```

**Example: Replace all Static Data on a Quote**

To replace all of the existing Static Data of a quote use the <ApiLink name="replaceAllStaticDataForQuote">replaceAllStaticDataForQuote</ApiLink> endpoint:

```
PUT /policy/{tenantLocator}/quotes/{locator}/static
```

```json
{
	"applicationNumber": "eAPP-0000005",
	"paidThroughDate": "2025-03-03"
}
```

Fetching Static Data [#fetching-static-data]

**Example: Fetch current Static Data values for a Quote**

To retrieve only the static data values on a quote use use the <ApiLink name="fetchStaticDataForQuote">fetchStaticDataForQuote</ApiLink> endpoint:

```
GET /policy/{tenantLocator}/quotes/{locator}/static
```

```json
{
	"applicationNumber": "eAPP-0000005",
	"paidThroughDate": "2025-03-03"
}
```

**Example: Fetch the history of Static Data for a Quote**

To retrieve the history of static data values on a quote use use the <ApiLink name="fetchStaticDataForQuote">fetchStaticDataForQuote</ApiLink> endpoint:

```
GET /policy/{tenantLocator}/quotes/{locator}/static/history/list
```

```json
{
    "listCompleted" : true,
    "items" : [
        {
            "historyLocator" :  "01JPR0S9H4D6R23387EGCWVXXX"
            "updatedAt" :  "2020-01-01T00:00:00Z"
            "updatedBy" :  "6ca2e546-613b-4212-845b-0b085e243XXX",
            "staticData" :      {
                "applicationNumber": "eAPP-0000001",
                "paidThroughDate": "2025-01-01"
            }
        },
        {
            "historyLocator" :  "01JPR0S9H4D6R23387EGCWVXXX"
            "updatedAt" :  "2020-01-02T00:00:00Z"
            "updatedBy" :  "6ca2e546-613b-4212-845b-0b085e243XXX",
            "staticData" :      {
                "applicationNumber": "eAPP-0000005",
                "paidThroughDate": "2025-03-03"
            }
        }
}
```

Usage - Policies [#usage---policies]

If present on the quote prior to issuance, the static data fields will be automatically carried forward to the static property of the subsequent policy.

Setting Static Data [#setting-static-data-1]

**Example: Add Static Data to an Issued Policy**

To add static data after policy creation use the <ApiLink name="addStaticDataForPolicy">addStaticDataForPolicy</ApiLink> endpoint:

```
POST /policy/{tenantLocator}/policies/{locator}/static
```

```json
{
	"applicationNumber": "eAPP-0000005",
	"paidThroughDate": "2025-03-03"
}
```

**Example: Update Static Data on an Issued Policy**

To update Static Data on a Policy use the <ApiLink name="updateStaticDataForPolicy">updateStaticDataForPolicy</ApiLink> endpoint:

```
PATCH /policy/{tenantLocator}/policies/{locator}/static
```

```json
{
    "removeData": {}
    "setData": {
        "applicationNumber": "eAPP-0000005",
        "paidThroughDate": "2025-03-03"
    }
}
```

**Example: Replace all Static Data on an Issued Policy**

To replace all static data on a policy use use the <ApiLink name="replaceAllStaticDataForPolicy">replaceAllStaticDataForPolicy</ApiLink> endpoint:

```
PUT /policy/{tenantLocator}/policies/{locator}/static
```

```json
{
	"applicationNumber": "eAPP-0000005",
	"paidThroughDate": "2025-03-03"
}
```

Fetching Static Data [#fetching-static-data-1]

**Example: Fetch current Static Data values for an Issued Policy**

To retrieve only the static data values on a policy use use the <ApiLink name="fetchStaticDataForPolicy">fetchStaticDataForPolicy</ApiLink> endpoint:

```
GET /policy/{tenantLocator}/policies/{locator}/static
```

```json
{
	"applicationNumber": "eAPP-0000005",
	"paidThroughDate": "2025-03-03"
}
```

**Example: Fetch the history of Static Data for an Issued Policy**

To retrieve the history of static data values on a policy use use the <ApiLink name="fetchStaticDataForPolicy">fetchStaticDataForPolicy</ApiLink> endpoint:

```
GET /policy/{tenantLocator}/policies/{locator}/static/history/list
```

```json
{
    "listCompleted" : true,
    "items" : [
        {
            "historyLocator" :  "01JPR0S9H4D6R23387EGCWVXXX"
            "updatedAt" :  "2020-01-01T00:00:00Z"
            "updatedBy" :  "6ca2e546-613b-4212-845b-0b085e243XXX",
            "staticData" :      {
                "applicationNumber": "eAPP-0000001",
                "paidThroughDate": "2025-01-01"
            }
        },
        {
            "historyLocator" :  "01JPR0S9H4D6R23387EGCWVXXX"
            "updatedAt" :  "2020-01-02T00:00:00Z"
            "updatedBy" :  "6ca2e546-613b-4212-845b-0b085e243XXX",
            "staticData" :      {
                "applicationNumber": "eAPP-0000005",
                "paidThroughDate": "2025-03-03"
            }
        }
    ]
}
```


# Socotra Assistant Configuration



The [Socotra Assistant](/ai-guide/assistant/overview) can be configured through the top-level <ApiLink name="AssistantRef">AssistantRef</ApiLink> configuration object. This configuration allows the assistant to authenticate requests performed on behalf of a tenant and controls how inbound emails are routed to [tasks](/features/work-management/tasks) in the [email intake workflow](/ai-guide/assistant/email-intake).

Here's an example of an `AssistantRef` configuration:

```json
{
	"assistant": {
		"patTokenSecretRef": {
			"name": "SocotraAssistantPat",
			"key": "patToken"
		},
		"inquiryIntents": {
			"newQuoteIntake": {
				"intentType": "newQuote",
				"taskType": "newSubmission",
				"workgroup": "new-business-team"
			},
			"generalIntake": {
				"intentType": "unknown",
				"taskType": "emailIntake"
			}
		}
	}
}
```

Secrets [#secrets]

The `patTokenSecretRef` object references the static name of the <ApiLink name="SecretRef">SecretRef</ApiLink> configuration object containing the [personal access token](/features/security/personal-access-tokens) (PAT) used by the Socotra Assistant, and contains the following fields:

* `name` - The static name of the SecretRef object
* `key` - The name of the secret item containing the PAT

Secrets can be created by using the <ApiLink name="createSecret">Create a Secret</ApiLink> API endpoint. Once a secret is created, it must be added to a [resource group](/api/resources/resource-service) by using the <ApiLink name="createResourceGroup">Create a Resource Group</ApiLink> or <ApiLink name="updateResourceGroup">Update a Resource Group</ApiLink> API endpoint.

<Callout>
  Ensure secret configurations are deployed before using the Socotra Assistant.
</Callout>

Intent Plans [#intent-plans]

When the Socotra Assistant intercepts an inbound email, the assistant classifies the email into an intent and creates a [task](/features/work-management/tasks) using the matching intent plan. The `inquiryIntents` object maps intent plan names to intent plans.

Each intent plan contains the following fields:

* `intentType` - The intent handled by the plan. Supported values are `newQuote`, `policyChange`, `policyCancellation`, `policyReinstatement`, and `unknown`.
* `taskType` - The type of task that will be created for emails matching the intent. The value must match a task type defined in the <ApiLink name="WorkManagementRef">WorkManagementRef</ApiLink> configuration for your tenant.
* `workgroup` - An optional reference to the name of the [workgroup](/features/work-management/workgroups) used to auto-assign tasks created for the intent

Workgroup names must be between 1 and 128 characters, must start with a letter or digit, and can only contain letters, digits, periods, underscores, and hyphens.

Validation Rules [#validation-rules]

The following rules are enforced when an `AssistantRef` configuration is deployed:

* The `inquiryIntents` object must include exactly one intent plan with the `unknown` intent type. This plan acts as a fallback for emails that don't match any other intent.
* Each intent type can be used by at most one intent plan.
* Each `taskType` must match a task type defined in the <ApiLink name="WorkManagementRef">WorkManagementRef</ApiLink> configuration for your tenant.

See Also [#see-also]

* <ApiLink name="AssistantRef">
    AssistantRef
  </ApiLink>
* [Socotra Assistant Overview](/ai-guide/assistant/overview)
* [Email Intake Workflow](/ai-guide/assistant/email-intake)
* [Integrations Plugin](/configuration/plugins/integrations)
* [Tasks](/features/work-management/tasks)
* [Workgroups](/features/work-management/workgroups)
* [Configuration Deployment](/configuration/general-topics/deployment)


# Availability



Overview [#overview]

Socotra can be configured to help manage the introduction and retirement of products, [data extensions](/configuration/data-extensions/overview), [policy elements](/features/policy-management/policy-elements), and [coverage terms](/features/policy-management/coverage-terms), supporting use cases like these:

* Retiring a product after a certain time, or for all new quotes.
* Specifying a future date after which certain elements can be added to policies.
* Automatically removing certain coverage terms on policy renewal.

Socotra's availability implementation has two fundamental characteristics:

1. Availability configuration can only be made on *optional* data elements, avoiding a range of edge cases and the need for migration solutions that would be needed if it were offered for required items as well. Data extension fields must have the `*` or `?` quantifiers to be eligible for availability configuration.
2. The platform enforces availability at the validation step, so any quotes, accounts, etc. that made it through that step prior to the deployment of a contradictory availability rule will not be blocked or otherwise invalidated; instead, you can implement more fine-grained handling for such cases in your plugin logic. You may also leverage [Data Lake](/features/reporting/datalake) to identify validated records you consider to be out of alignment with your latest availability specification.

A key benefit of Socotra's availability design is that such configuration updates are [always considered to be "safe"](/configuration/general-topics/redeployment#redeployment_safety).

The feature is not exclusive to policies and quotes, but can also be used for data extensions associated with other entities, including [accounts](/features/accounts), [payments](/features/billing/payments), and [disbursements](/features/billing/disbursements).

Configuration [#configuration]

Here is the `AvailabilityRef` configuration specification:

<ApiSchema name="AvailabilityRef" />

The specification supports three major "availability" concepts, which can be applied individually or in combination:

1. Availability: the time after which the item can be added
2. Retirement: the time at which the item cannot be added
3. Remove on Renewal: the time at which the item will be automatically stripped from new terms

The distinction between truly required and optional configuration properties follows an intuitive rule: if you opt in to one of these core availability concepts, you must provide the platform with enough information to determine a clear intent. For example, you could have an availability configuration that is as simple as this:

```javascript
{
    // ... other config ...,
    "availability": {
        "retireAfter": "2024-06-01T00:00:00+0000"
    }
}
```

In this case, the platform would understand that you merely want to retire the element as of a certain time, and will apply the default time basis `termStartTime`. If you were to <ApiLink name="fetchConfigDefinition">fetch the deployed datamodel</ApiLink>, you would see the equivalent configuration with explicit defaults:

```javascript
{
    // ... other config ...,
    "availability": {
        "availabilityTimeBasis": "termStartTime",
        "retireAfter": "2024-06-01T00:00:00Z",
        "retire": false,
        "retirementTimeBasis": "termStartTime",
        "removeOnRenewal": false
    }
}
```

The `retire` property is `false` since a specific retirement time is set. Both the `retire` and `removeOnRenewal` boolean properties are `true` only when retirement or removal on renewal are meant to be applied for all time, respectively.

<Callout>
  Removal on renewal is not available for products. Deployment attempts with such configuration will fail.
</Callout>

Examples [#examples]

Setting a product to retire after a certain time [#setting-a-product-to-retire-after-a-certain-time]

Suppose you have a product that should no longer be allowed on new quotes taking effect after midnight on June 1, 2025. In the product configuration, you could set availability like this:

```javascript
{
    // ... other config ...,
    "availability": {
        "retireAfter": "2025-06-01T00:00:00+0000"
    }
}
```

Following configuration deployment, any attempt to validate a quote with `startTime` after `2025-06-01T00:00:00+0000` will fail with a validation error:

<span id="product_availability_error_example" />

```javascript
{
    // ...,
    "validationResult": {
        "validationItems": [
            {
                "elementType": "FloodProtectionQuote",
                "locator": "01JGBXEQ0BS4KCNNM6NAG9JXDT",
                "errors": [
                    "Product 'FloodProtection' expired based on the availability config"
                ]
            }
        ],
        "success": false
    }
}
```

<Callout>
  As mentioned earlier, any quotes with `startTime` after `2025-06-01T00:00:00+0000` that had been validated prior to the introduction of this availability constraint will not be blocked from issuance.
</Callout>

Retiring a product [#retiring-a-product]

If you want to retire a product regardless of the effective time of the quote, you could set validation configuration as follows:

```javascript
{
    // ... other config ...,
    "availability": {
        "retire": true
    }
}
```

After deploying this change, an attempt to validate any quote with this product will fail with an error [like the one shown above](#product_availability_error_example). Any existing validated quotes with that product are still considered valid since they had been validated prior to the imposition of the availability constraint.

<Callout>
  Socotra's transaction model means that availability rules will apply to reinstatement. For example, if an issued `SomeProduct` policy is cancelled, followed by configuration deployment that retires `SomeProduct`, attempts to validate a reinstatement of the policy will fail.
</Callout>

Making an element available to new policies starting after a certain time [#making-an-element-available-to-new-policies-starting-after-a-certain-time]

In the following example, a "Bodily Injury" coverage is set to be available on policy terms starting after June 1, 2024:

```javascript
{
    "displayName" : "Bodily Injury",
    "charges" : [ "Bodily_Injury" ],
    "abstract" : false,
    "availability": {
        "availableAfter": "2024-06-01T00:00:00Z"
    }
}
```

An attempt to validate a quote with this element starting before midnight on June 1, 2024 will fail:

```javascript
{
    // ...,
    "validationResult": {
        "validationItems": [
            {
                "elementType": "LocationQuote",
                "locator": "01JGCJ64YVYTAV5YAQES2AYHTY",
                "errors": [
                    "Element 'BodilyInjury' not available yet based on the availability config"
                ]
            }
        ],
        "success": false
    }
}
```

Since the availability time basis is the default, `termStartTime`, this quote could be validated and issued without the element, but later add "Bodily Injury" in a renewal term, assuming that the renewal term starts on or after June 1, 2024. If the availability configuration had specified `policyStartTime` as the `availabilityTimeBasis`, then "Bodily Injury" could not be added to the policy, even as part of a renewal term after the specified availability date.

Note that by setting `availableAfter` to a sufficiently early time, you can effectively say "make this element available to any new policies".

Automatically removing certain coverage terms on policy renewal [#automatically-removing-certain-coverage-terms-on-policy-renewal]

In the following example, a coverage called "GeneralLimit" is set for removal on any quote renewal:

```javascript
{
    "type" : "splitLimit",
    "options" : {
        "cv5001000200" : {
        "displayName" : "$5,000/$3,000/$8,000",
        "value" : 1700,
        "tag" : "500/1000/200"
        },
        // ...,
    },
    "availability": {
        "removeOnRenewal": true
    }
}
```

As a result, a renewal transaction for the policy will automatically have a change instruction to remove "GeneralLimit":

```javascript
{
    "locator": "01JGEDKZMVZ36VCTKX6QC9YT2R",
    "transactionType": "renewal",
    "transactionCategory": "renewal",
    // ...,
    "changeInstructions": [
        // ...,
        {
            "locator": "01JGEDMGA5VEM1DABWA94S9CAZ",
            "action": "modify",
            "staticLocator": "01JGEDHJEAGWQN3Q10FGW6FDR6",
            "removeCoverageTerms": {
                "GeneralLimit": "cv5001000200"
            }
        },
        // ...,
    ],
    // ...,
}
```

Of course, `removeOnRenewalAfter` works in a similar way, but only applies for renewal transactions taking effect after the provided datetime.

Additional Considerations [#additional-considerations]

Inheritance [#inheritance]

Availability follows simple rules for elements and products using inheritance:

1. If the parent item has an availability option, it will be used for child items.
2. Availability configuration on a child item completely supersedes any parent availability configuration.

Non-Policy Entities [#non-policy-entities]

Time basis settings on data extensions associated with non-policy entities such as accounts, payments, and disbursements always resolve to "now" at validation, even if some other value is provided. For example, if you have a data extension on a field set with `availableAfter` of `"2024-06-01T00:00:00Z"`, you should expect the platform to compare that value against the moment that account validation is attempted.

Any "remove on renewal" configuration on such entities will not have any impact.


## API Reference

AvailabilityRef
Specifies availability. At least one of availableAfter, retireAfter, retire, removeOnRenewalAfter, or removeOnRenewal must be set.
Properties:
  availableAfter (datetime)
  availabilityTimeBasis (Enum policyStartTime | termStartTime, required) — default: TermStartTime
  retireAfter (datetime)
  retire (boolean) — default: false
  retirementTimeBasis (Enum policyStartTime | termStartTime, required) — default: TermStartTime
  removeOnRenewalAfter (datetime)
  removeOnRenewal (boolean) — default: false

# Configuration Bootstrap



Overview [#overview]

The Socotra Insurance Suite configurations generally contain settings and definitions for various components, such as account and policy structures, data extensions, and other behaviors and structures that are defined within the platform.

While [resources](/configuration/resources/data-tables) such as [data tables](/configuration/resources/data-tables) and [documents](/configuration/resources/documents) are defined in the main <ApiLink name="ConfigurationRef">configuration</ApiLink>, the management of those resources—including deploying actual resource instances and creating resource groups—occurs at the tenant level, after deployment is complete.

To facilitate a more streamlined tenant creation experience, <ApiLink name="BootstrapRef">configuration bootstrap</ApiLink> — an optional component of the <ApiLink name="ConfigurationRef">config</ApiLink> structure — allows for the inclusion of both resource instance files and resource group definitions within a tenant configuration, as well as their automatic deployment as part of the tenant creation process.

Notes [#notes]

The bootstrap directory only applies on tenant **creation**. It is ignored for subsequent redeployments.

Bootstrap Directory [#bootstrap-directory]

To support this streamlined deployment approach, the <ApiLink name="BootstrapRef">bootstrap</ApiLink> directory enables the inclusion of necessary resource files and metadata. The directory structure within the configuration is as follows:

```text
└── bootstrap
    └── resources
        ├── config.json
        └── resourceFiles
            ├── tables                    // only .csv files
            ├── constraintTables          // only .csv files
            ├── documentTemplates         // only .liquid or .velocity/.vm files
            ├── documentTemplatesSnippets // only .liquid or .velocity/.vm files
            ├── staticDocuments           // only .pdf or .html files
            ├── customFonts               // only .ttf or .otf files
            └── secrets
                └── config.json
```

The `config.json` file defines the resource instances and groups used for deployment.

Validations [#validations]

The Bootstrap process is triggered only if the following conditions are met:

* The bootstrap directory is present in the config.

* There is at least one valid combination of a <ApiLink name="ResourceInstanceRef" /> defined in the `resources/config.json` file and a corresponding file in the `resourceFiles` directory.
  * i.e. There must be a file in one of the resource specific directories within the `resourceFiles` folder that matches the name of one of the entries in the `resourceInstances`.

* The file type (and its directory within `resourceFiles`) aligns with the type defined by the main <ApiLink name="ConfigurationRef" /> resource declaration, matched by the `staticName`.

* All names specified in the <ApiLink name="ResourceInstanceRef" /> must be unique.

* All names specified in the <ApiLink name="ResourceGroupRef" /> must be unique.

* Any `staticName` specified in the `ResourceInstanceRef` must correspond to a valid resource declaration in the main <ApiLink name="ConfigurationRef" />.

* All names in the <ApiLink name="ResourceGroupRef" /> must have been declared in the <ApiLink name="ResourceInstanceRef" />.

Example [#example]

Below is an example structure for the bootstrap directory:

```text
└── bootstrap
    └── resources
        ├── config.json
        └── resourceFiles
            ├── tables
            │   ├── VehicleDamageRates01.csv
            │   └── VehicleRegistrationStateRates01.csv
            └── documentTemplates
                └── Declarations01.velocity
```

Contents of the `config.json` file:

```json
{
	"resourceInstances": {
		"VehicleDamageRates01": {
			"staticName": "VehicleDamage"
		},
		"VehicleRegistrationStateRates01": {
			"staticName": "VehicleRegistrationState"
		},
		"Declarations01": {
			"staticName": "Declarations"
		}
	},
	"resourceGroups": {
		"initialGroup": {
			"selectionStartTime": "1970-01-01T00:00:00-05:00",
			"resourceNames": [
				"VehicleDamageRates01",
				"VehicleRegistrationStateRates01",
				"Declarations01"
			]
		}
	}
}
```


# Configuration SDK



import Image from 'next/image';

Overview [#overview]

The Configuration SDK accelerates Socotra Insurance Suite config development, getting you up and running with industry-standard development tools following best practices for product creation, maintenance, and troubleshooting. The Configuration SDK exemplifies "convention over configuration": instead of piecing together all the parts you need for a productive environment, you start with a system ready for use, with the option to pick and choose components or integrate with alternative tools if you want.

The SDK consists of a template to organize your configuration's source code, along with a collection of Gradle tasks packaged as a Gradle plugin. Though these could be used in any Java development environment, including editors like VS Code with Java-specific extensions, we test against and recommend IntelliJ (Community Edition or better) for use with the Configuration SDK.

Do I really need an SDK to write and maintain configs? [#do-i-really-need-an-sdk-to-write-and-maintain-configs]

Technically, no. Practically, yes.

Socotra Insurance Suite configuration could be done in any text editor, since you're working with JSON and Java. However, going without our SDK and a compatible IDE is to deprive yourself of all the advantages that come with our fundamental data model and static typing, such as IDE-assisted code generation, inspection, and proactive plugin and configuration validity checks.

For example, suppose you've defined a new product with some underlying elements and data extensions in your JSON config, and now wish to write a validation plugin. The Java code for your plugin must refer to the types you've defined in your config, in addition to the core Socotra data types. While you *could* write all code without typing assistance, it is far easier to have your IDE reference compiled classes for all Socotra and custom types, and gain all the advantages of type-checking and automatic code generation. We supply [developer endpoints](/api/configuration-and-development/developer) to support this process, where you send a config to a tenant and receive compiled Java classes corresponding to the types therein. The SDK's Gradle plugin task set streamlines this process, placing compiled classes from the target tenant or your in-progress config into a directory that your IDE can treat as a library.

Getting Started [#getting-started]

Getting started with the Configuration SDK is simple:

1. Get the source control template
2. Update the Config SDK Gradle plugin to point at a target tenant
3. Use tasks as you build your config

The "target tenant" is crucial for plugin development: even if you never intend to deploy to the target tenant directly from your config development environment, the Gradle task set will leverage the tenant's development endpoints for tasks like validating your config and refreshing your data model for reference by your plugin code.

<Callout>
  The Config SDK requires Java 21+.
</Callout>

Get the source control template [#get-the-source-control-template]

The template is available as [a public GitHub repository ](https://github.com/socotra/config-sdk-template). It includes the Gradle plugin as a dependency that is fetched from the repository's Maven package index.

A GitHub username and Personal Access Token (PAT) with the `read:packages` scope is **required** in order to download the config developer plugin dependency. The `settings.gradle.kts` file is configured to read those credentials from environment variables.

If the Config SDK plugin fetch does not succeed (typically resulting in a `Could not download socotra-ec-config-developer` message with an associated `401 (Unauthorized)` error), check to ensure that Gradle is using valid GitHub credentials. You can put a `println` statement in `settings.gradle.kts` to see whether expected values are being used, or set the credentials in some other preferred way, such as a Gradle properties file.

<Callout>
  If you'd rather not set up credentials to fetch the plugin dependency from GitHub's package index, you can download the JAR directly from the "Packages" section on the front page of the Config SDK Template repository. Just click on [com.socotra.socotra-ec-config-developer`and select the JAR from "Assets". See the`manual-jarfile-plugin` `branch ](https://github.com/socotra/config-sdk-template/tree/manual-jarfile-plugin) of the template repository for an example of such a setup, which has the JAR file in a directory with requisite updates to `settings.gradle.kts`.
</Callout>

Source template file structure [#source-template-file-structure]

The template is intended to serve as the canonical source repository for your configuration. It closely resembles a typical Gradle project:

```text
├── README.md
├── build
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
├── socotra-config
│   └── config.json
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── socotra
    │               └── deployment
    │                   └── customer
    │                       ├── DocDataSnapshotPlugin.java
    │                       ├── RatingPlugin.java
    │                       ├── UnderwritingPluginImpl.java
    │                       └── ValidationPluginImpl.java
    └── test
        └── java
            └── com
                └── socotra
                    └── deployment
                        └── customer
                            └── RatingPluginTest.java
```

Notable components:

* `socotra-config`: the local configuration, containing JSON (and [bootstrap resources](/configuration/general-topics/bootstrap), if defined) for deployment. Can be created manually or will be automatically created when pulling config from a tenant using one of the Gradle tasks.
* `com.socotra.deployment.customer` package in `src/main/java` and `src/test/java`: canonical plugin code for development and testing. Placement here enables your IDE's Java code support. When ready for deployment, tasks like `createArchive` or `createTenant` will bundle the plugin code with your `socotra-config` contents to create a deployable config archive.
* `build`: directory containing build artifacts, including compiled classes for the core Socotra data model and any custom types defined in your product configuration.

Update the config plugin to point at a target tenant [#update-the-config-plugin-to-point-at-a-target-tenant]

In the template's `build.gradle.kts` file, you'll see the following section:

```kotlin
`socotra-developer` {
    apiUrl.set(System.getenv("SOCOTRA_KERNEL_API_URL") ?: "http://hardcoded-fallback-tenant-url")
    tenantLocator.set(System.getenv("SOCOTRA_KERNEL_TENANT_LOCATOR") ?: "hardcoded-fallback-tenant-locator")
    personalAccessToken.set(System.getenv("SOCOTRA_KERNEL_ACCESS_TOKEN") ?: "hardcoded-fallback-access-token")
}
```

You can set your environment variables with the requisite information, or write the string values directly. We recommend using environment variables if you are committing your configuration template to source. See the [Authentication API](/api/business-accounts/authentication) reference to learn how to manage Auth ("Personal Access") Tokens.

<span id="config_sdk_tasks" />

Use tasks as you build your config [#use-tasks-as-you-build-your-config]

The Gradle plugin enables two task groups: `kernel-developer`, and `kernel-developer-aux` ("auxiliary"). The auxiliary group contains smaller-scale tasks composing the larger tasks found in `kernel-developer`. You'll tend to use the `kernel-developer` tasks the most, which are summarized below:

| Task                         | Description                                                                                                                                                                                                                                                                                                                         |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cleanupSocotraFolders`      | Deletes temporary artifacts produced by the other Gradle plugin tasks.                                                                                                                                                                                                                                                              |
| `createArchive`              | Creates a deployable configuration zip. If successful, a `config.zip` archive will be placed at the project root (a peer of `socotra-config`).                                                                                                                                                                                      |
| `createTenant`               | Creates a deployable config from your `socotra-config` directory contents and plugin sources, then deploys it to a brand-new tenant, writing the new tenant locator into the `socotra-config-developer` section in `build.gradle.kts`. Will fail if there is already a `tenantLocator.set` statement in `socotra-config-developer`. |
| `deployConfigToTenant`       | Deploys config in your `socotra-config` directory to the tenant. Will fail if there are [unsafe changes](/configuration/general-topics/redeployment#redeployment_safety).                                                                                                                                                           |
| `overwriteConfigOnTenant`    | Deploys config in your `socotra-config` directory, overwriting existing configuration.                                                                                                                                                                                                                                              |
| `downloadConfigAndPlugins`   | Downloads the tenant's config, along with plugin code and compiled class files for reference by plugins.                                                                                                                                                                                                                            |
| `downloadReferenceDataModel` | Downloads compiled class files for reference by plugins.                                                                                                                                                                                                                                                                            |
| `refreshReferenceDataModel`  | Places compiled classes corresponding to your local `socotra-config` definition for reference by plugin code.                                                                                                                                                                                                                       |
| `validateConfig`             | Validates the config in `socotra-config`.                                                                                                                                                                                                                                                                                           |

After you've configured the plugin to point to a target tenant, you can run tasks against it. For example, to work on modifications to a tenant's config, you can execute `downloadConfigAndPlugins`.

Once you've run one of the data model tasks that places your compiled types in the `build` directory, you'll be able to use your IDE's code assistance facilities (auto-completion, type inspection, method generation, etc.) for plugin development.

<Image src="/images/configuration_sdk/config-sdk-code-assistance.gif" alt="config sdk code assistance" width={1024} height={562} unoptimized />

<Callout>
  Whenever you download a data model, you may need to refresh your Gradle dependencies to ensure that all the latest type definitions are recognized by your IDE. You can do this from the Gradle sidebar in IntelliJ, or by running `./gradlew --refresh-dependencies` in the terminal.
</Callout>

Bootstrapping [#bootstrapping]

Effective use of the Configuration SDK requires a tenant. If you're starting without a tenant, you'll need to make an initial config deployment to create one (see "Create a Tenant" in the [Configuration Deployments API](/api/configuration-and-development/deployments) reference). You can also use the `createTenant` task in the [Config SDK task set](#config_sdk_tasks) to deploy to a new tenant.


# Data Access Controls



<Callout type="warn">
  This guide has been deprecated. For information about current data security capabilities, see the [Data Access Controls](/features/security/data-access-controls), [Data Masking](/features/security/data-masking), and [Data Anonymization](/features/security/data-anonymization) guides in the [Security Topic](/features/security/security-overview).
</Callout>

Overview [#overview]

*Data Access Controls* enable restricting the accounts and policies that users can access in the system. Basically, the data in the account or policy is compared to a mask that is assigned to each user. If the mask values are set for the particular values of the data, then the user is granted access, and otherwise access will fail with an `HTTP 403 / Forbidden` response.

By default, data access controls are disabled, and so users are not restricted based on data, but they may be blocked if they do not have the proper [roles or permissions](/features/security/roles-and-permissions) for the operation.

Enabling Data Access Controls [#enabling-data-access-controls]

Data access controls are enabled and disabled in configuration. The top level `dataAccessControl` property's `enabled` property should be set to true to enable:

<ApiSchema name="DataAccessControlRef" />

<Callout type="warn">
  Before enabling data access controls, assign masks to users to prevent unintentionally blocking access.
</Callout>

Configuring Data Fields [#configuring-data-fields]

The following fields can be used as part of the decision whether to grant access to entities:

* The `region` of the account or policy
* The `product` (for policies only)
* The extension data for the account, or top (product) element on the policy.

<Callout>
  For policy extension data, the data on the product element on the latest issued segment is used.
</Callout>

The particular fields for accounts and policies are set with the `account` and `policy` properties on the <ApiLink name="DataAccessControlRef" /> configuration block. Each field is described as one of `region`, `product`, or `data.<my_field_name>`. The particular values that are used for user access aren't set here; this only describes which fields are used in the process.

Each of the [extension data fields](/configuration/data-extensions/overview) used for data access control must be a `string` type with an accompanying `options` list.

Assigning User Data Masks [#assigning-user-data-masks]

The <ApiLink name="addDataSecurityMask" /> endpoint is used to assign a mask to a user. Each user can have multiple masks; an individual mask is needed for every tenant, and separate masks are used for policy and account access.

The `fields` in the mask are a map from mask field names (`region`, `data.my_field`, etc) to arrays of the values that are allowed for that user. Access is granted if, for *every* field in the mask, the value in the data appears among the values listed. All fields in the mask must match.

A field in a mask can be set to always match with use of the `*` wildcard. For example, `{ "customerSegment": ["*"] }`.

See Also [#see-also]

* [Data Access Controls API Guide](/api/configuration-and-development/data-access-controls)


## API Reference

DataAccessControlRef
Properties:
  enabled (boolean, required)
  dataMasking (boolean, required)
  account (DataAccessControlFieldRef, required)
  policy (DataAccessControlFieldRef, required)

# Configuration Deployment



Overview [#overview]

Socotra Insurance Suite configurations are defined using files, mostly JSON, organized in a pre-defined folder structure. The application loads this folder structure to get settings and definitions for things like account and policy structure, [data extensions](/configuration/data-extensions/overview), [data table definitions](/configuration/resources/data-tables), [document declarations](/configuration/resources/documents) and other behaviors and structures that you define.

Configuration Structure [#configuration-structure]

The basic structure of the configuration payload is a zip archive with a top-level `config.json` file that contains the desired <ApiLink name="ConfigurationRef" /> entities.
Users can also choose to structure the config with directories named for the various entities and their instances, each containing their own `config.json`.

For example, the following two config structures are equivalent:

**Single top-level** `config.json`:

```json
{
	"accounts": {
		"ConsumerAccount": {
			// ...
		},
		"CommercialAccount": {
			// ...
		}
	},
	"products": {
		"PersonalAuto": {
			// ...
		},
		"HO3": {
			// ...
		}
	},
	"defaultCurrency": "USD"
}
```

**Structure with directories named for the various entities and their instances:**

```text
config
└── config.json //contains some global defaults e.g. defaultCurrency
└── Accounts
│   └── ConsumerAccount
│   │   └── config.json
│   └── CommercialAccount
│       └── config.json
└── Products
    └── PersonalAuto
    │   └── config.json
    └── HO3
        └── config.json
```

The system will merge these files into a single logical datamodel which can be retrieved from the <ApiLink name="fetchConfigDefinition">datamodel API</ApiLink>.
If creating a configuration zip file manually, users should ensure that the archive is made at the same level as top-level `config.json` file and any top-level folders. It is also permissible to create the zip at another level above this, but there may only be a single folder path - encountering multiple folders or other levels of depth will result in a failed deployment with a path validation error.

See the complete <ApiLink name="ConfigurationRef">Configuration reference here</ApiLink>

Configuration Validation [#configuration-validation]

In order for a configuration deployment to pass validation, it must meet the following criteria:

* At least one *Account* definition must be included.

* At least one *Product* definition must be included.

* It must have at least one *Charge* with `type: premium`.

* The following referential integrity checks are also run:
  * If `eligibleAccountTypes` is specified in the definition of a *Product*, each must be the name of an account definition.

  * If `eligibleTransactionTypes` is specified in the definition of a *Product*, each must be the name of a transaction definition.

  * Each *Charge* `category` must be a valid choice.

  * Each *Contents* value for a product or element must be a valid element name.

  * Each field type for accounts, products, and element extension data must be a valid pre-defined type or a type declared in `dataTypes`.

  * If an `assistant` section is included, its [intent plans](/configuration/general-topics/assistant#intent-plans) must include exactly one plan with the `unknown` intent type. Each intent type may be used by at most one plan, and each `taskType` must match a task type defined in the work management configuration. See the [Socotra Assistant Configuration](/configuration/general-topics/assistant) guide for more information.

  * Each coverage term for a product or element must be one declared in <ApiLink name="CoverageTermRef">coverageTerms</ApiLink>.

  * Any product, element or other config entity that uses `extend` to inherit, must do so from a valid, like-typed entity
    * e.g. Products may only be extended from other products, exposure elements may only be extended from other exposure elements etc.

  * Quantifiers must be valid for the type (i.e. coverage terms may only have blank, ?, or !)

* In a config, for deployment or re-deployment, at the top level or for any product, if `defaultTermDuration` is specified, then `defaultDurationBasis` must also be included.

* The built-in validation will include both whether the element's `data` is conformant with the definition in the config, but also that the JSON itself is conformant. So, if a field is specified as a string but the payload looks like `{ "name": 42 }` then the element may be created and will save, but validation will fail.

<span id="configuration_element_name_length_limits" />

Configuration Element Name Length Limits [#configuration-element-name-length-limits]

Names for the following configuration elements are limited to 65 characters:

* Accounts
* Products
* Payments
* Disbursements
* Tables
* Constraint Tables
* Range Tables
* Secrets
* Custom Events
* Contacts
* FNOLs
* Schedules

Names for all other configuration elements with `data` extensions are limited to 67 characters, and those without `data` extensions are limited to 120 characters.

<span id="configuration-case-sensitivity" />

Configuration Case Sensitivity [#configuration-case-sensitivity]

Upon deployment, Socotra converts many of the elements in the configuration package to a Java data model that is used throughout the system to govern the structure of data and enforce strict typing.
As a result, there are implications for the casing of configuration entities which are enforced through validation prior to deployment.

In short, the following convention applies:

1. The name of any configuration entities that will be rendered to a **Java Class**, must be declared in `PascalCase`.
2. Any enum or attribute of Class entities, must be declared in `camelCase`.
3. References between custom data types, elements and coverage terms must be declared in the same casing as the original definition.
4. References between other entities are case sensitive: For example, while an <ApiLink name="AutoRenewalPlanRef">Auto-Renewal Plan</ApiLink> name may be defined in either `PascalCase` or `camelCase`, when that plan name is referenced as a Product's `defaultAutoRenewalPlan`, casing should be consistent.
5. The *level* an entity resides within the config hierarchy has no bearing on its casing requirements.

The following configuration class entities are rendered as Java Classes and so must be declared in `PascalCase`:

* <ApiLink name="AccountRef">
    Accounts
  </ApiLink>
* <ApiLink name="ProductRef">
    Products
  </ApiLink>
* <ApiLink name="ElementRef">
    PolicyLines
  </ApiLink>
* <ApiLink name="ElementRef">
    ExposureGroups
  </ApiLink>
* <ApiLink name="ElementRef">
    Exposures
  </ApiLink>
* <ApiLink name="ElementRef">
    Coverages
  </ApiLink>
* <ApiLink name="CoverageTermRef">
    CoverageTerms
  </ApiLink>
* <ApiLink name="DataTypeRef">
    Custom DataTypes
  </ApiLink>
* <ApiLink name="TableRef">
    Tables
  </ApiLink>
* <ApiLink name="ConstraintTableRef">
    ConstraintTables
  </ApiLink>
* <ApiLink name="SecretRef">
    Secrets
  </ApiLink>
* <ApiLink name="PaymentRef">
    Payments
  </ApiLink>
* <ApiLink name="DisbursementRef">
    Disbursements
  </ApiLink>

The following properties of configuration class entities must be declared in `camelCase`:

* <ApiLink name="CoverageTermOptionRef">
    CoverageTerm Options
  </ApiLink>
* <ApiLink name="ColumnRef">
    Table Columns
  </ApiLink>
* <ApiLink name="ColumnRef">
    ConstraintTables Columns
  </ApiLink>
* <ApiLink name="SecretRef">
    Secrets attributes
  </ApiLink>
* <ApiLink name="WorkManagementRef">
    Work Management Task categories and types
  </ApiLink>
* <ApiLink name="WorkManagementRef">
    Work Management Qualification categories
  </ApiLink>
* <ApiLink name="WorkManagementRef">
    Work Management User Association Roles
  </ApiLink>
* <ApiLink name="PropertyRef">
    All extension data properties (data field names for any entity)
  </ApiLink>

Inheritance Case Sensitivity [#inheritance-case-sensitivity]

Entities that are eligible for inheritance (such as <ApiLink name="ProductRef">Products</ApiLink>, <ApiLink name="ElementRef">Elements</ApiLink>, and <ApiLink name="PaymentRef">Payments</ApiLink> etc) may be designated as being `abstract`, meaning they can only be inherited and never instantiated themselves.
While it is best practice to consistently apply casing styles, *abstract* entities are not strictly subject to the same `PascalCase` validations as concrete versions of the same class entity. When actually inherited however, the `camelCase` validations still applies to the class entities properties.

<Callout>
  Built-in property names leveraged when exercising the API (like `startTime` or `autoRenewalPlanName` for quote requests) are case insensitive (i.e. case does not matter, so `STARTTIME`, `AUTORENEWALPLANNAME`, or even `starttiME` would be valid.)
</Callout>

See Also [#see-also]

* [Redeployment](/configuration/general-topics/redeployment)


# Entity Numbering



Overview [#overview]

Entity numbering is a structured way for the system to generate “numbers” of various kinds, such as an account number or policy number.

Numbering is available for these entities:

* Accounts
* Quotes
* Policies
* Policy Terms
* Invoices
* Disbursements
* Payments
* Tasks
* FNOLs

Entities that are insured-facing and are likely to be attached to a paper document or shown prominently on a screen are generally capable of being assigned a number. This is particularly important in customer service situations, where the insured will present a problem and then can be asked for the relevant number for lookup and reference.

<Callout>
  While the data described here are called "numbers," they really are strings and aren't typically interesting from a numerical perspective.
</Callout>

Process [#process]

For each entity type that is to have numbers assigned, a template string called `format` is added in configuration to describe how the numbers should be generated. Then, when entities are created, the format string is applied to the next sequential "core number" to create a full number.

These string are part of configured *Numbering Plans*. Each numberable entity type can be associated with a numbering plan which describes how numbers are to be generated, using the `format` property of the plan.

For example, a format string for a personal auto product might look like: `X#####-{product}`. For this, the system will generate a sequence of core numbers, each starting with a character from `A` to `Z`, based on the `X` in the format, and then five digits each ranging from `0` to `9`, and based on the `#` signs in the format. If the personal auto product defined a numbering string of "PA", then the numbers would have a `-PA` suffix. The number sequence for personal auto policies would then be:

* `A00000-PA`
* `A00001-PA`
* ...
* `A99999-PA`
* `B00000-PA`
* `B00001-PA`
* etc.

The starting point of the "core" part of the sequence above is `A00000`. This starting point can be controlled using the `initialCoreNumber` property of the numbering plan. For example, you can set it to `"G51234"` and then the first generated number will be `G51234-PA`. (See *Configuration*, below.)

<Callout>
  With the exception of invoices generated with the `enableSerialInvoiceNumbering` flag set to `true`, entities with auto-generated numbers will not necessarily have sequential/contiguous numbers, nor will they be ordered by assignment. They **will** be unique, pulled from monotonically increasing number sequence pools that optimize system performance.
</Callout>

By default the numbering process is triggered immediately after validation for entities that have a validation step. For other entity types, numbers are generated on creation. The following entities can be configured to have their number generated at creation:

* Accounts
* Quotes
* Invoices
* Payments
* Disbursements
* Tasks

Configuration [#configuration]

Each numberable entity type has an optional `numberingPlan` property, with the name of the numbering plan for that type. Any number of numbering plans can be created, and each one can have a different `numberingPlan` field (referring to the name of a specific numbering plan). Plans can specify the following:

* `format`: The template used to generate an entity number from the sequential core number
* `initialCoreNumber`: The starting point in the sequence, not including any delimiting characters, prefixes, suffixes, etc
* `termNumberFormat`: A special format string for constructing term numbers given a policy number
* `copyFromQuote`: A boolean flag to determine whether, when quotes are issued, the policy should share the same number as the quote
* `numberingTrigger`: A boolean flag to determine, for entities with a validation step, whether the number should be generated at the time of creation, or validation (the default).

Numbering is disabled when the `numberingPlan` property on the entity type is left empty.

<Callout>
  For invoices, the plan is defined for the account type using the account configuration's `invoiceNumberingPlan` property.
</Callout>

Prefixes, Suffixes, and Numbering Strings [#prefixes-suffixes-and-numbering-strings]

*Numbering Strings* are assigned to product types and regions and can be used in `format` templates to add additional context. For example, if the `US_WEST` region has `numberingString: "USW"` and the Business Auto product has `numberingString: "BA"`, then a business auto policy created in the US West region with a format of `"{product}-XX-#####-{region}"` could then have a number assigned like `"BA-TQ-23456-USW"`.

The `{product}` string only applies to quotes and policies. The `{region}` string applies to any supported entity type, and will use the relevant account's region for all but quotes and policies. Quotes and policies will use their own assigned region.

Numbering strings can be used anywhere in the format, and do not need to be strictly defined as prefixes or suffixes. For example, `"##{product}-#X"` is a valid format string.

Numbering strings can use any letter casing and/or numeric digits.

Additional Characters [#additional-characters]

Other valid characters can be inserted into the format string by escaping them: `\A\B\C\9-#######` would result in a prefix of `"ABC9"` in generated numbers.

<Callout type="warn">
  The backslash `\` character in the format string must itself be escaped when embedding the string in JSON. So in a JSON file, the above format string would look like `"\\T.{policyNumber}-{termNumberPlusOne}"`. This double-escaping must be done for all escaped characters in format strings that are to be embedded in a JSON payload.
</Callout>

<Callout>
  Hyphens (`-`), periods (`.`)  and underscores ( `_` ) in the format string do not require escaping.
</Callout>

Term Numbers [#term-numbers]

Term numbers can be generated, but they are configured in a different way. They use the policy number as a starting point, and can be decorated with additional characters, or the product or region numbering strings.

To enable term numbers, set the `termNumberFormat` property in the numbering plan. You can use any of the following in this format:

* `{policyNumber}`
* `{termNumber}` (starts with zero for the initial issuance term)
* `{termNumberPlusOne}` (starts with one for the initial issuance term)
* Separators (periods, hyphens, and underscore characters)
* Escaped characters

For example, if policy number `ABC123Z` was created, and the term number format is specified as `\T.{policyNumber}-{termNumberPlusOne}`, then the first term number for that policy will be `T.ABC123Z-1`.

Setting Numbers [#setting-numbers]

Entity numbers can be manually set for any entity with automatic numbering disabled and no number present by calling the associated `PATCH` endpoint. These include:

* <ApiLink name="setAccountNumber" />
* <ApiLink name="setQuoteNumber" />
* <ApiLink name="setPolicyNumber" />
* <ApiLink name="setTermNumber" />
* <ApiLink name="setInvoiceNumber" />
* <ApiLink name="setDisbursementNumber" />
* <ApiLink name="setPaymentNumber" />
* <ApiLink name="setTaskNumber" />
* <ApiLink name="setFnolNumber" />

If a user-provided number is a duplicate for an entity of that type, the operation will fail.

These numbers cannot be changed once they have been set.

<Callout>
  Setting numbers is not supported for entities that have automatic numbering enabled.
</Callout>

Number Generation [#number-generation]

A number can be manually generated for any entity with automatic numbering enabled and no number present by calling the associated `POST` endpoint. These include:

* <ApiLink name="generateAccountNumber" />
* <ApiLink name="generateQuoteNumber" />
* <ApiLink name="generatePolicyNumber" />
* <ApiLink name="generateInvoiceNumber" />
* <ApiLink name="generateDisbursementNumber" />
* <ApiLink name="generatePaymentNumber" />
* <ApiLink name="generateTermNumber" />
* <ApiLink name="generateTaskNumber" />
* <ApiLink name="generateFnolNumber" />

The generated number will always adhere to the configured automatic numbering plan for that entity.

Fetch [#fetch]

Usually there will be at most one entity with a given number, but there can be more than one match if numbers have been set manually via the API, or duplicate numbers are used in migrated data. Each of these endpoints will return the matching entities as an array:

* <ApiLink name="fetchAccountsWithNumber" />
* <ApiLink name="fetchQuotesWithNumber" />
* <ApiLink name="fetchPoliciesWithNumber" />
* <ApiLink name="fetchTermsWithNumber" />
* <ApiLink name="fetchInvoiceWithNumber">
    Fetch Invoices with Number
  </ApiLink>
* <ApiLink name="fetchDisbursementsWithNumber" />
* <ApiLink name="fetchPaymentsWithNumber" />
* <ApiLink name="fetchTasksWithNumber" />
* <ApiLink name="getFnolByNumber" />

Error Handling [#error-handling]

If a number fails to generate, an event stream event will be generated and the number for that entity will remain empty unless it is manually generated via the API.

Limitations [#limitations]

* The `initialCoreNumber` must be at least one character long, and not more than 32 characters long. (Generally, core numbers should be much shorter than this.)
* The overall `format` string must be no more than 64 characters long.
* Generated numbers must be no more then 128 characters long.
* Numbering strings for products and regions can be no more than 12 characters long.
* Consecutive separators are not supported, for example, `.-` within a format string.

See Also [#see-also]

* [Accounts API](/api/accounts)
* [Quotes API](/api/quotes/quotes)
* [Policies API](/api/policy-management/policies)
* [Disbursements API](/api/billing/disbursements)
* [Invoices API](/api/billing/invoices)
* [Payments API](/api/billing/payments)
* [Work Management API](/api/work-management)
* [FNOL API](/api/claims)


# Event Definitions



{/* This file is auto-generated by scripts/generate-derived-docs.ts. Do not edit manually. */}

This topic lists the details about events returned from the [Events API](/api/events/events).

Account Events [#account-events]

* `policy.account.anonymize`: [AccountEventData](#AccountEventData)
* `policy.account.create`: [AccountEventData](#AccountEventData)
* `policy.account.discard`: [AccountEventData](#AccountEventData)
* `policy.account.update`: [AccountEventData](#AccountEventData)
* `policy.account.validate`: [AccountEventData](#AccountEventData)

Quote Events [#quote-events]

* `policy.quote.accept`: [QuoteEventData](#QuoteEventData)
* `policy.quote.anonymize`: [QuoteEventData](#QuoteEventData)
* `policy.quote.create`: [QuoteEventData](#QuoteEventData)
* `policy.quote.discard`: [QuoteEventData](#QuoteEventData)
* `policy.quote.issue`: [QuoteEventData](#QuoteEventData)
* `policy.quote.manualunderwrite`: [QuoteManuallyUnderwrittenEventData](#QuoteManuallyUnderwrittenEventData)
* `policy.quote.price`: [QuoteEventData](#QuoteEventData)
* `policy.quote.refuse`: [QuoteEventData](#QuoteEventData)
* `policy.quote.reset`: [QuoteEventData](#QuoteEventData)
* `policy.quote.staticdata.add`: [QuoteEventData](#QuoteEventData)
* `policy.quote.staticdata.anonymize`: [QuoteEventData](#QuoteEventData)
* `policy.quote.staticdata.replace`: [QuoteEventData](#QuoteEventData)
* `policy.quote.staticdata.update`: [QuoteEventData](#QuoteEventData)
* `policy.quote.underwrite`: [QuoteUnderwrittenEventData](#QuoteUnderwrittenEventData)
* `policy.quote.update`: [QuoteEventData](#QuoteEventData)
* `policy.quote.validate`: [QuoteEventData](#QuoteEventData)

Policy Status Events [#policy-status-events]

* `policy.status.update`: [PolicyStatusEventData](#PolicyStatusEventData)

Transaction Events [#transaction-events]

* `policy.cancellation.accept`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.create`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.discard`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.issue`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.manualUnderwrite`: [TransactionManualUnderwritingEventData](#TransactionManualUnderwritingEventData)
* `policy.cancellation.price`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.refuse`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.reset`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.underwrite`: [TransactionUnderwritingEventData](#TransactionUnderwritingEventData)
* `policy.cancellation.update`: [TransactionEventData](#TransactionEventData)
* `policy.cancellation.validate`: [TransactionEventData](#TransactionEventData)
* `policy.change.accept`: [TransactionEventData](#TransactionEventData)
* `policy.change.create`: [TransactionEventData](#TransactionEventData)
* `policy.change.discard`: [TransactionEventData](#TransactionEventData)
* `policy.change.issue`: [TransactionEventData](#TransactionEventData)
* `policy.change.manualUnderwrite`: [TransactionManualUnderwritingEventData](#TransactionManualUnderwritingEventData)
* `policy.change.price`: [TransactionEventData](#TransactionEventData)
* `policy.change.refuse`: [TransactionEventData](#TransactionEventData)
* `policy.change.reset`: [TransactionEventData](#TransactionEventData)
* `policy.change.underwrite`: [TransactionUnderwritingEventData](#TransactionUnderwritingEventData)
* `policy.change.validate`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.accept`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.create`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.discard`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.issue`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.manualUnderwrite`: [TransactionManualUnderwritingEventData](#TransactionManualUnderwritingEventData)
* `policy.reinstatement.price`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.refuse`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.reset`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.underwrite`: [TransactionUnderwritingEventData](#TransactionUnderwritingEventData)
* `policy.reinstatement.update`: [TransactionEventData](#TransactionEventData)
* `policy.reinstatement.validate`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.accept`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.create`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.discard`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.issue`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.manualUnderwrite`: [TransactionManualUnderwritingEventData](#TransactionManualUnderwritingEventData)
* `policy.renewal.price`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.refuse`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.reset`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.underwrite`: [TransactionUnderwritingEventData](#TransactionUnderwritingEventData)
* `policy.renewal.update`: [TransactionEventData](#TransactionEventData)
* `policy.renewal.validate`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.accept`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.create`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.discard`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.issue`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.manualUnderwrite`: [TransactionManualUnderwritingEventData](#TransactionManualUnderwritingEventData)
* `policy.reversal.price`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.refuse`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.reset`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.underwrite`: [TransactionUnderwritingEventData](#TransactionUnderwritingEventData)
* `policy.reversal.update`: [TransactionEventData](#TransactionEventData)
* `policy.reversal.validate`: [TransactionEventData](#TransactionEventData)

Policy Static Data Events [#policy-static-data-events]

* `policy.staticdata.add`: [PolicyLocatorData](#PolicyLocatorData)
* `policy.staticdata.anonymize`: [PolicyLocatorData](#PolicyLocatorData)
* `policy.staticdata.replace`: [PolicyLocatorData](#PolicyLocatorData)
* `policy.staticdata.update`: [PolicyLocatorData](#PolicyLocatorData)

Policy Events [#policy-events]

* `policy.anonymize`: [PolicyLocatorData](#PolicyLocatorData)
* `policy.migrateOnRenewal.disable`: [PolicyLocatorData](#PolicyLocatorData)
* `policy.migrateOnRenewal.enable`: [PolicyLocatorData](#PolicyLocatorData)

Numbering Events [#numbering-events]

* `task.numberAssignmentFailed`: [NumberingEventData](#NumberingEventData)

Config Migration Events [#config-migration-events]

* `account.config.migration.failed`: [ConfigMigrationEventPayload](#ConfigMigrationEventPayload)
* `policy.config.migration.failed`: [PolicyConfigMigrationEventPayload](#PolicyConfigMigrationEventPayload)
* `quote.config.migration.failed`: [ConfigMigrationEventPayload](#ConfigMigrationEventPayload)

Credit Distribution Events [#credit-distribution-events]

* `billing.creditdistribution.create`: [CreditDistributionEventData](#CreditDistributionEventData)
* `billing.creditdistribution.distribute`: [CreditDistributionEventData](#CreditDistributionEventData)
* `billing.creditdistribution.reverse`: [CreditDistributionEventData](#CreditDistributionEventData)

Delinquency Event Events [#delinquency-event-events]

* `billing.delinquency.delinquencyevent.activate`: [DelinquencyEventEventData](#DelinquencyEventEventData)
* `billing.delinquency.delinquencyevent.cancel`: [DelinquencyEventEventData](#DelinquencyEventEventData)
* `billing.delinquency.delinquencyevent.create`: [DelinquencyEventEventData](#DelinquencyEventEventData)
* `billing.delinquency.delinquencyevent.trigger`: [DelinquencyEventEventData](#DelinquencyEventEventData)

Delinquency Events [#delinquency-events]

* `billing.delinquency.create`: [DelinquencyEventData](#DelinquencyEventData)
* `billing.delinquency.lapse`: [DelinquencyEventData](#DelinquencyEventData)
* `billing.delinquency.settle`: [DelinquencyEventData](#DelinquencyEventData)

Disbursement Events [#disbursement-events]

* `billing.disbursement.anonymize`: [DisbursementEventData](#DisbursementEventData)
* `billing.disbursement.approve`: [DisbursementEventData](#DisbursementEventData)
* `billing.disbursement.create`: [DisbursementEventData](#DisbursementEventData)
* `billing.disbursement.execute`: [DisbursementEventData](#DisbursementEventData)
* `billing.disbursement.reject`: [DisbursementEventData](#DisbursementEventData)
* `billing.disbursement.reverse`: [DisbursementEventData](#DisbursementEventData)

Installment Events [#installment-events]

* `billing.installmentlattice.create`: [InstallmentLatticeCreateData](#InstallmentLatticeCreateData)

Invoice Events [#invoice-events]

* `billing.invoice.autopay`: [InvoiceAutopayData](#InvoiceAutopayData)
* `billing.invoice.autopayfailed`: [InvoiceAutopayData](#InvoiceAutopayData)
* `billing.invoice.discard`: [InvoiceDiscardData](#InvoiceDiscardData)
* `billing.invoice.generate`: [InvoiceGeneratedEventData](#InvoiceGeneratedEventData)
* `billing.invoice.settle`: [InvoiceSettledEventData](#InvoiceSettledEventData)
* `billing.invoice.unsettle`: [InvoiceSettledEventData](#InvoiceSettledEventData)

Billing Numbering Events [#billing-numbering-events]

* `disbursement.numberAssignmentFailed`: [NumberingEventData](#NumberingEventData)
* `invoice.numberAssignmentFailed`: [NumberingEventData](#NumberingEventData)
* `payment.numberAssignmentFailed`: [NumberingEventData](#NumberingEventData)

Payment Events [#payment-events]

* `billing.payment.anonymize`: [PaymentEventData](#PaymentEventData)
* `billing.payment.cancel`: [PaymentEventData](#PaymentEventData)
* `billing.payment.create`: [PaymentEventData](#PaymentEventData)
* `billing.payment.distribute`: [PaymentEventData](#PaymentEventData)
* `billing.payment.execute`: [PaymentEventData](#PaymentEventData)
* `billing.payment.fail`: [PaymentEventData](#PaymentEventData)
* `billing.payment.post`: [PaymentEventData](#PaymentEventData)
* `billing.payment.request`: [PaymentEventData](#PaymentEventData)
* `billing.payment.reverse`: [PaymentEventData](#PaymentEventData)
* `billing.payment.validationfailed`: [PaymentEventData](#PaymentEventData)

Shortfall Credit Events [#shortfall-credit-events]

* `billing.shortfallcredit.create`: [ShortfallEventData](#ShortfallEventData)
* `billing.shortfallcredit.distribute`: [ShortfallEventData](#ShortfallEventData)
* `billing.shortfallcredit.reverse`: [ShortfallEventData](#ShortfallEventData)

Write Off Events [#write-off-events]

* `billing.writeoff.create`: [WriteOffEventData](#WriteOffEventData)
* `billing.writeoff.distribute`: [WriteOffEventData](#WriteOffEventData)
* `billing.writeoff.reverse`: [WriteOffEventData](#WriteOffEventData)

Hold Events [#hold-events]

* `billing.hold.activate`: [HoldEventData](#HoldEventData)
* `billing.hold.create`: [HoldEventData](#HoldEventData)
* `billing.hold.discard`: [HoldEventData](#HoldEventData)
* `billing.hold.release`: [HoldEventData](#HoldEventData)
* `billing.hold.reset`: [HoldEventData](#HoldEventData)
* `billing.hold.validate`: [HoldEventData](#HoldEventData)

Document Events [#document-events]

* `document.copyOnIssue.ready`: [DocumentCopyOnIssueReadyPayload](#DocumentCopyOnIssueReadyPayload)
* `document.failed`: [DocumentGenerationEventsPayload](#DocumentGenerationEventsPayload)
* `document.ready`: [DocumentGenerationEventsPayload](#DocumentGenerationEventsPayload)

Migration Events [#migration-events]

* `migration.error`: [MigrationEventData](#MigrationEventData)
* `migration.fail`: [MigrationEventData](#MigrationEventData)
* `migration.finish`: [MigrationEventData](#MigrationEventData)
* `migration.patch`: [MigrationEventData](#MigrationEventData)
* `migration.pause`: [MigrationEventData](#MigrationEventData)
* `migration.recover`: [MigrationEventData](#MigrationEventData)
* `migration.resume`: [MigrationEventData](#MigrationEventData)
* `migration.start`: [MigrationEventData](#MigrationEventData)

Numbering Events [#numbering-events-1]

* `task.numberAssignmentFailed`: [NumberingEventData](#NumberingEventData)

Task Events [#task-events]

* `task.activate`: [TaskData](#TaskData)
* `task.assign`: [TaskData](#TaskData)
* `task.cancel`: [TaskData](#TaskData)
* `task.complete`: [TaskData](#TaskData)
* `task.create`: [TaskData](#TaskData)
* `task.unassign`: [TaskData](#TaskData)
* `task.update`: [TaskUpdateData](#TaskUpdateData)

User Association Events [#user-association-events]

* `userAssociation.associated`: [UserAssociationEventData](#UserAssociationEventData)
* `userAssociation.completed`: [UserAssociationEventData](#UserAssociationEventData)
* `userAssociation.disassociated`: [UserAssociationEventData](#UserAssociationEventData)
* `userAssociation.uncompleted`: [UserAssociationEventData](#UserAssociationEventData)

Workplan Events [#workplan-events]

* `workmanagement.workplan.executionerror`: [WorkplanPayload](#WorkplanPayload)
* `workmanagement.workplan.notfound`: [WorkplanNotFoundPayload](#WorkplanNotFoundPayload)

Moratorium Events [#moratorium-events]

* `moratorium.create`: [MoratoriumEventData](#MoratoriumEventData)
* `moratorium.effective`: [MoratoriumEventData](#MoratoriumEventData)
* `moratorium.end`: [MoratoriumEventData](#MoratoriumEventData)
* `moratorium.update`: [MoratoriumEventData](#MoratoriumEventData)

Fnol Events [#fnol-events]

* `claim.fnol.anonymize`: [FnolEventData](#FnolEventData)
* `claim.fnol.complete`: [FnolEventData](#FnolEventData)
* `claim.fnol.create`: [FnolEventData](#FnolEventData)
* `claim.fnol.discard`: [FnolEventData](#FnolEventData)
* `claim.fnol.onclaim`: [FnolClaimData](#FnolClaimData)
* `claim.fnol.reject`: [FnolEventData](#FnolEventData)
* `claim.fnol.update`: [FnolEventData](#FnolEventData)
* `claim.fnol.validate`: [FnolEventData](#FnolEventData)
* `fnol.numberAssignmentFailed`: [FnolEventData](#FnolEventData)

Contact Events [#contact-events]

* `contact.anonymized`: [ContactEventData](#ContactEventData)
* `contact.created`: [ContactEventData](#ContactEventData)
* `contact.merged`: [ContactMergeEventData](#ContactMergeEventData)
* `contact.validated`: [ContactEventData](#ContactEventData)

Producer Events [#producer-events]

* `producers.producer.create`: [ProducerEventData](#ProducerEventData)
* `producers.producer.discard`: [ProducerEventData](#ProducerEventData)
* `producers.producer.retire`: [ProducerEventData](#ProducerEventData)
* `producers.producer.suspend`: [ProducerEventData](#ProducerEventData)
* `producers.producer.unsuspend`: [ProducerEventData](#ProducerEventData)
* `producers.producer.update`: [ProducerEventData](#ProducerEventData)
* `producers.producer.validate`: [ProducerEventData](#ProducerEventData)

Producer Code Events [#producer-code-events]

* `producers.producercode.create`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.discard`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.numberAssignmentFailed`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.retire`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.suspend`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.unsuspend`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.update`: [ProducerCodeEventData](#ProducerCodeEventData)
* `producers.producercode.validate`: [ProducerCodeEventData](#ProducerCodeEventData)

Producer Appointment Events [#producer-appointment-events]

* `producers.producerappointment.create`: [ProducerAppointmentEventData](#ProducerAppointmentEventData)
* `producers.producerappointment.discard`: [ProducerAppointmentEventData](#ProducerAppointmentEventData)
* `producers.producerappointment.update`: [ProducerAppointmentEventData](#ProducerAppointmentEventData)
* `producers.producerappointment.validate`: [ProducerAppointmentEventData](#ProducerAppointmentEventData)

Producer License Events [#producer-license-events]

* `producers.producerlicense.create`: [ProducerLicenseEventData](#ProducerLicenseEventData)
* `producers.producerlicense.discard`: [ProducerLicenseEventData](#ProducerLicenseEventData)
* `producers.producerlicense.update`: [ProducerLicenseEventData](#ProducerLicenseEventData)
* `producers.producerlicense.validate`: [ProducerLicenseEventData](#ProducerLicenseEventData)

Event Payloads [#event-payloads]

<ApiSchema name="AccountEventData" />

<ApiSchema name="QuoteEventData" />

<ApiSchema name="QuoteUnderwrittenEventData" />

<ApiSchema name="QuoteManuallyUnderwrittenEventData" />

<ApiSchema name="TransactionEventData" />

<ApiSchema name="TransactionUnderwritingEventData" />

<ApiSchema name="TransactionManualUnderwritingEventData" />

<ApiSchema name="DelinquencyEventData" />

<ApiSchema name="DelinquencyEventEventData" />

<ApiSchema name="ShortfallEventData" />

<ApiSchema name="PaymentEventData" />

<ApiSchema name="DisbursementEventData" />

<ApiSchema name="InstallmentLatticeCreateData" />

<ApiSchema name="CreditDistributionEventData" />

<ApiSchema name="InvoiceGeneratedEventData" />

<ApiSchema name="InvoiceSettledEventData" />

<ApiSchema name="InvoiceAutopayData" />

<ApiSchema name="InvoiceEvents" />

<ApiSchema name="InvoiceDiscardData" />

<ApiSchema name="WriteOffEventData" />

<ApiSchema name="PolicyStatusEventData" />

<ApiSchema name="NumberingEventData" />

<ApiSchema name="MigrationEventData" />

<ApiSchema name="DocumentCopyOnIssueReadyPayload" />

<ApiSchema name="DocumentGenerationEventsPayload" />

<ApiSchema name="FnolEventData" />

<ApiSchema name="FnolClaimData" />

<ApiSchema name="HoldEventData" />

<ApiSchema name="UserAssociationEventData" />

<ApiSchema name="ContactEventData" />

<ApiSchema name="ContactMergeEventData" />

<ApiSchema name="MoratoriumEventData" />

<ApiSchema name="ProducerEventData" />

<ApiSchema name="ProducerCodeEventData" />

<ApiSchema name="ConfigMigrationEvents" />

<ApiSchema name="ConfigMigrationEventPayload" />

<ApiSchema name="PolicyConfigMigrationEventPayload" />

<ApiSchema name="QuotePolicyNumberData" />

<ApiSchema name="NumberingData" />

<ApiSchema name="PolicyLocatorData" />

<ApiSchema name="PolicyEvents" />

<ApiSchema name="PolicyStaticDataEvents" />

<ApiSchema name="ProducerLicenseEventData" />

<ApiSchema name="ProducerAppointmentEventData" />

<ApiSchema name="TaskData" />

<ApiSchema name="TaskUpdateData" />

<ApiSchema name="TaskEvents" />

<ApiSchema name="WorkplanEvents" />

<ApiSchema name="WorkplanNotFoundPayload" />

<ApiSchema name="WorkplanPayload" />

<ApiSchema name="ListPageResponseString" />

See Also [#see-also]

* [Events API](/api/events/events)
* [Events Configuration Guide](/configuration/general-topics/events)


## API Reference

AccountEventData
Properties:
  accountLocator (ulid, required)

QuoteEventData
Properties:
  quoteLocator (ulid, required)

QuoteUnderwrittenEventData
Properties:
  quoteLocator (ulid, required)
  underwritingStatus (Enum info | block | decline | reject | approve, required)

QuoteManuallyUnderwrittenEventData
Properties:
  quoteLocator (ulid, required)

TransactionEventData
Properties:
  policyLocator (ulid, required)
  transactionLocator (ulid, required)

TransactionUnderwritingEventData
Properties:
  policyLocator (ulid, required)
  transactionLocator (ulid, required)
  underwritingStatus (string, required)

TransactionManualUnderwritingEventData
Properties:
  policyLocator (ulid, required)
  transactionLocator (ulid, required)

DelinquencyEventData
Properties:
  delinquencyLocator (ulid, required)
  policyLocators (ListPageResponseULID, required)

DelinquencyEventEventData
Properties:
  delinquencyLocator (ulid, required)
  delinquencyEventLocator (ulid, required)
  policyLocators (ListPageResponseULID, required)

ShortfallEventData
Properties:
  shortfallCreditLocator (ulid, required)

PaymentEventData
Properties:
  paymentLocator (ulid, required)
  policyLocators (ListPageResponseULID, required)

DisbursementEventData
Properties:
  disbursementLocator (ulid, required)

InstallmentLatticeCreateData
Properties:
  installmentLatticeLocator (ulid, required)

CreditDistributionEventData
Properties:
  creditLocator (ulid, required)

InvoiceGeneratedEventData
Properties:
  invoiceLocator (ulid, required)
  accountLocator (ulid, required)
  invoiceType (Enum normal | aggregate, required)
  policyLocators (ListPageResponseULID, required)
  generateTime (datetime, required)

InvoiceSettledEventData
Properties:
  invoiceLocator (ulid, required)
  accountLocator (ulid, required)
  invoiceType (Enum normal | aggregate, required)
  policyLocators (ListPageResponseULID, required)

InvoiceAutopayData
Properties:
  invoiceLocator (ulid, required)
  accountLocator (ulid, required)
  invoiceType (Enum normal | aggregate, required)
  policyLocators (ListPageResponseULID, required)
  autopayTime (datetime, required)

InvoiceEvents
Properties:
  billing.invoice.autopayfailed (InvoiceAutopayData)
  billing.invoice.discard (InvoiceDiscardData)
  billing.invoice.generate (InvoiceGeneratedEventData)
  billing.invoice.settle (InvoiceSettledEventData)
  billing.invoice.autopay (InvoiceAutopayData)
  billing.invoice.unsettle (InvoiceSettledEventData)

InvoiceDiscardData
Properties:
  invoiceLocator (ulid, required)
  accountLocator (ulid, required)
  invoiceType (Enum normal | aggregate, required)

WriteOffEventData
Properties:
  writeOffLocator (ulid, required)
  policyLocators (ListPageResponseULID, required)

PolicyStatusEventData
Properties:
  policyLocator (ulid, required)
  newStatuses (ListPageResponsePolicyStatus, required)
  removedStatuses (ListPageResponsePolicyStatus, required)

NumberingEventData
Properties:
  entityLocator (ulid, required)

MigrationEventData
Properties:
  migrationLocator (ulid, required)

DocumentCopyOnIssueReadyPayload
Properties:
  quoteReferenceLocator (ulid, required)

DocumentGenerationEventsPayload
Properties:
  documentLocator (ulid, required)
  referenceType (Enum quote | policy | invoice | transaction | segment | term, required)
  referenceLocator (ulid, required)

FnolEventData
Properties:
  locator (ulid, required)

FnolClaimData
Properties:
  fnolLocator (ulid, required)
  claimLocator (ulid, required)

HoldEventData
Properties:
  holdLocator (ulid, required)

UserAssociationEventData
Properties:
  userAssociationLocator (ulid, required)
  referenceType (Enum account | quickQuote | quote | policy | transaction | invoice | underwritingFlag | payment | quoteGroup | inquiry, required)
  referenceLocator (ulid, required)

ContactEventData
Properties:
  locator (ulid, required)
  staticLocator (ulid, required)

ContactMergeEventData
Properties:
  oldStaticLocator (ulid, required)
  newStaticLocator (ulid, required)

MoratoriumEventData
Properties:
  name (string, required)
  effectiveTime (datetime, required)
  endTime (datetime, required)

ProducerEventData
Properties:
  producerLocator (ulid, required)

ProducerCodeEventData
Properties:
  producerCodeLocator (ulid, required)
  code (string)

ConfigMigrationEvents
Properties:
  quote.config.migration.failed (ConfigMigrationEventPayload)
  account.config.migration.failed (ConfigMigrationEventPayload)
  policy.config.migration.failed (PolicyConfigMigrationEventPayload)

ConfigMigrationEventPayload
Properties:
  locator (ulid, required)
  configVersion (ulid, required)

PolicyConfigMigrationEventPayload
Properties:
  policyLocator (ulid, required)
  transactionLocator (ulid, required)
  configVersion (ulid, required)

QuotePolicyNumberData
Properties:
  quoteLocator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)

NumberingData
Properties:
  entityLocator (ulid, required)

PolicyLocatorData
Properties:
  policyLocator (ulid, required)

PolicyEvents
Properties:
  policy.migrateOnRenewal.enable (PolicyLocatorData)
  policy.migrateOnRenewal.disable (PolicyLocatorData)
  policy.anonymize (PolicyLocatorData)

PolicyStaticDataEvents
Properties:
  policy.staticdata.add (PolicyLocatorData)
  policy.staticdata.update (PolicyLocatorData)
  policy.staticdata.anonymize (PolicyLocatorData)
  policy.staticdata.replace (PolicyLocatorData)

ProducerLicenseEventData
Properties:
  producerLicenseLocator (ulid, required)

ProducerAppointmentEventData
Properties:
  producerAppointmentLocator (ulid, required)

TaskData
Properties:
  taskLocator (ulid, required)
  taskState (Enum active | pastDeadline | completed | cancelled, required)

TaskUpdateData
Properties:
  taskLocator (ulid, required)
  taskState (Enum active | pastDeadline | completed | cancelled, required)
  newLabels (ListPageResponseString, required)
  removedLabels (ListPageResponseString, required)

TaskEvents
Properties:
  task.create (TaskData)
  task.unassign (TaskData)
  task.assign (TaskData)
  task.activate (TaskData)
  task.cancel (TaskData)
  task.complete (TaskData)
  task.update (TaskUpdateData)

WorkplanEvents
Properties:
  workmanagement.workplan.notfound (WorkplanNotFoundPayload)
  workmanagement.workplan.executionerror (WorkplanPayload)

WorkplanNotFoundPayload
Properties:
  workplanName (string, required)

WorkplanPayload
Properties:
  workplanLocator (ulid, required)

ListPageResponseString
Properties:
  listCompleted (boolean, required)
  items (string[], required)

# Events



The event stream presents a chronological feed of activity within Socotra Insurance Suite, designed to enhance operational efficiency and data management practices in your business ecosystem. It is a pivotal feature for use cases like these:

* Initiating integrated workflows triggered by key events such as invoice issuance.
* Enabling automated routines, such as activating a policy renewal procedure as the expiry date approaches.
* Capturing data changes for storage in a specialized database.

Event Stream Usage [#event-stream-usage]

The event stream offers:

* The ability to <ApiLink name="fetchEvent">fetch a single event</ApiLink>.
* The ability to <ApiLink name="fetchEventsForARequest">fetch all the events for a single API request</ApiLink>.
* <ApiLink name="fetchMultipleEvents">A paginated view of events</ApiLink> in
  the Socotra system, in ascending chronological order. You may include one or
  more options in your initial query, such as filter criteria, time range, and
  page size. You can then use the `pagingToken` to page through additional
  results.

<Callout>
  The `pagingToken` cannot be used in conjunction with any other optional arguments.
</Callout>

<span id="event-payloads" />

Payloads [#payloads]

Most Socotra events are kept deliberately sparse. A few have additional data attached, as described below.

Billing [#billing]

Billing-related events such as delinquency, payment, and invoice generation have a `policyLocators` property with this value:

<ApiSchema name="ListPageResponseULID" />

Relevant policy locators associated with the entity will be included in the `items` array. If the number of items is five or fewer, the `listCompleted` property will be `true`; else, `listCompleted: false` serves as an indicator to fetch comprehensive data from the API if the full set of policy locators is needed for your use case.

<span id="policyStatus" />

Policy Status [#policy-status]

The policy status event includes `newStatuses` and `removedStatuses` properties with the following value:

<ApiSchema name="ListPageResponsePolicyStatus" />

See the [Policy Status Guide](/features/policy-management/policy-status#policy-status-event-stream) for details.

<span id="custom-events" />

Custom Events [#custom-events]

You may configure custom events to emit from your plugin code.

Configuring Custom Events [#configuring-custom-events]

Add your event's definition (<ApiLink name="CustomEventRef" />) to the `customEvents` map in <ApiLink name="ConfigurationRef">your top-level configuration</ApiLink>. Here's an example of such a definition:

```json
{
	// ...,
	"customEvents": {
		"CustomEventTypeA": {
			"type": "custom.event.type.a"
		}
	}
	// ...,
}
```

Custom events must have a type beginning with `custom.`, followed by a sequence of `.`-delimited alphanumeric characters. All custom event `type` definitions must be unique; else, a deployment error will be thrown.

Emitting Custom Events [#emitting-custom-events]

In plugin code, use the `EventsService.getInstance().createEvent(type, data)` call to emit your custom event. The `type` will be `CustomEvent.<YourEventTypeName>`; in the example above, for instance, you would reference the event as `CustomEvent.CustomEventTypeA`.

`data` must be an JSON-serializable object. A simple approach is to pass a map as `data`, as in this example:

```java
// ...
EventsService.getInstance().createEvent(CustomEvent.CustomEventTypeA, Map.of("quote", quote.locator(), "info", "plugin called"));
// ...
```

See Also [#see-also]

* [Events API](/api/events/events): API details, including a list of supported events
* [Event Definitions](/configuration/general-topics/event-definitions): Details about event payloads
* [Webhooks](/configuration/general-topics/webhooks): Details about pushing events to external systems using webhooks
* [Diverted Events API](/api/events/diverted-events): Functionality to handle failed webhook event messages
* [Custom Scheduled Events](/configuration/general-topics/scheduled-events): Feature to create custom events that can be scheduled to run at specific times or intervals


## API Reference

ListPageResponseULID
Properties:
  listCompleted (boolean, required)
  items (ulid[], required)

ListPageResponsePolicyStatus
Properties:
  listCompleted (boolean, required)
  items (Enum[], required)

# External Numbering Support



The Socotra Insurance Suite provides a built-in [numbering system](/configuration/general-topics/entity-numbering) for quotes and policies. However, some businesses may prefer to implement their own numbering logic for a number of reasons, including:

* Numbering logic may depend on a large number of factors, such as policy data, account data, and producer data
* Numbering logic may need to be executed at a specific stage in the policy lifecycle
* The Socotra Insurance Suite may not currently support certain numbering requirements

In order to accommodate these possibilities, our platform provides the following functionality:

* Quotes have an optional `reservedPolicyNumber` field, which automatically becomes the `policyNumber` when the resulting policy is issued
* An API endpoint can be used to set the `reservedPolicyNumber` for a quote
* The `reservedPolicyNumberRequired` configuration field can be used to force quotes to have a `reservedPolicyNumber` set in order for a policy to be issued
* External systems can be automatically notified via system [events](/configuration/general-topics/events) and [webhooks](/configuration/general-topics/webhooks) when numbering is requested for a quote, and when the `reservedPolicyNumber` for a quote is modified
* Custom numbering logic can be implemented via the [Automation Plugin](/configuration/plugins/automation)

<Callout>
  Standard [numbering plans](/configuration/general-topics/entity-numbering) can be used in combination with external numbering plans, as they do not interfere with each other.
</Callout>

Configuration [#configuration]

A list of `externalNumberingPlans` can be defined within the top-level <ApiLink name="ConfigurationRef" /> object. Each list item contains a map from a numbering plan name to a `settings` object. Currently, `settings` objects only contain a `trigger` field, which instructs the system to trigger a `policy.quote.policyNumberRequested` event when quotes move to the specified state.

Here's a configuration example:

```json
{
	"externalNumberingPlans": {
		"examplePlan": {
			"trigger": "accepted"
		},
		"anotherPlan": {
			"trigger": "priced"
		}
	}
}
```

Events will only be triggered after a quote successfully moves to the specified lifecycle state.

The `trigger` value must be one of the following quote lifecycle states:

* `validated`
* `earlyUnderwritten`
* `priced`
* `underwritten`
* `accepted`
* `issued`

<Callout>
  The `trigger` value does not have a default value. It must be explicitly set by the user.
</Callout>

An external numbering plan can be added to a product by specifying the name of the plan in the `externalNumberingPlan` field within the corresponding <ApiLink name="ProductRef" /> configuration object.

For example:

```json
{
	"ExampleProduct": {
		"externalNumberingPlan": "examplePlan"
	}
}
```

The `reservedPolicyNumberRequired` field within ProductRef configuration objects can force quotes of the corresponding product type to have a `reservedPolicyNumber` set in order for a policy to be issued.

For example:

```json
{
	"ExampleProduct": {
		"externalNumberingPlan": "examplePlan",
		"reservedPolicyNumberRequired": true // Default is false
	}
}
```

The default value for `reservedPolicyNumberRequired` is `false`.

When `reservedPolicyNumberRequired` is set to `true`, attempts to issue quotes of the corresponding product type without a `reservedPolicyNumber` set will fail.

Set the Reserved Policy Number [#set-the-reserved-policy-number]

The `reservedPolicyNumber` can be set when creating a quote or through the <ApiLink name="setReservedPolicyNumber" /> API endpoint.

For example:

```json
{
	"reservedPolicyNumber": "4263716"
}
```

The `reservedPolicyNumber` field is not search-indexed, meaning quotes cannot be searched by `reservedPolicyNumber`. When a quote is issued, the `policyNumber` value will be automatically set to the current `reservedPolicyNumber` value, and the `reservedPolicyNumber` value will become searchable through the `policyNumber` field. You can manually set the `quoteNumber` value to the `reservedPolicyNumber` value or add the `reservedPolicyNumber` to a [static data](/configuration/data-extensions/static-data) field if you want to search quotes by `reservedPolicyNumber`.

Events [#events]

A `policy.quote.policyNumberRequested` event is triggered when a quote moves to the state specified in the `externalNumberingPlan` associated with its product type, and has the following payload:

<ApiSchema name="QuotePolicyNumberData" />

A `policy.quote.policyNumberAssigned` event is triggered when the `reservedPolicyNumber` for a quote is modified, and has the same payload as other numbering events:

<ApiSchema name="NumberingData" />

Event Handling [#event-handling]

Webhooks can be configured to call external API endpoints when the `policy.quote.policyNumberRequested` or `policy.quote.policyNumberAssigned` events are triggered.

Alternatively, the Automation Plugin can execute custom numbering logic in response to these events.

See the [Webhooks](/configuration/general-topics/webhooks) and [Automation Plugin](/configuration/plugins/automation) feature guides for more information.

See Also [#see-also]

* [Entity Numbering](/configuration/general-topics/entity-numbering)
* [Events](/configuration/general-topics/events)
* [Webhooks](/configuration/general-topics/webhooks)
* [Automation Plugin](/configuration/plugins/automation)


## API Reference

QuotePolicyNumberData
Properties:
  quoteLocator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)

NumberingData
Properties:
  entityLocator (ulid, required)

# Identifiers



Overview [#overview]

In Socotra, many configurable items require names, and the names for these must follow certain rules to be considered valid. The rules for valid identifiers are the same as for the [Java programming language ](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.8) .

Items with Identifier Names [#items-with-identifier-names]

The following items in a Socotra configuration must have names that are valid identifiers:

* Product names
* [Account](/features/accounts) type names
* [Policy elements](/features/policy-management/policy-elements)
* [Data extensions](/configuration/data-extensions/overview) property names
* [Coverage terms](/features/policy-management/coverage-terms) names and option names
* [Document](/configuration/resources/documents) names (static and dynamic, including names and static names)
* [Table](/configuration/resources/data-tables) names and static names
* [Charge](/features/financials/charges) names

Rules [#rules]

Each name is used to construct Java objects which use the property name as the variable name. This means each name must be a valid Java identifier:

* It must start with a letter or underscore.
* The first character may be followed by any number of letters, numbers, or underscores.
* The name must not be the same as a Java reserved word or boolean value.

See the [Configuration Deployment](/configuration/general-topics/deployment#configuration_element_name_length_limits) guide for more information on naming restrictions.

Letters may be any valid letter in the Unicode character set. For example, `firstName`, `имя`, and `όνομα` are all valid names.


# Single Sign-On (SSO)



Overview [#overview]

Setting up Single Sign-On (SSO) with Socotra involves a multi-step process that integrates your Identity Provider (IdP) with Socotra's user authentication service. This guide outlines the necessary steps to configure SAML-based SSO, ensuring a seamless and secure authentication experience for your users.

<span id="step-1-idp-registration" />

Step 1: Register Socotra as a New Application in Your Identity Provider [#step-1-register-socotra-as-a-new-application-in-your-identity-provider]

Begin by configuring your IdP to recognize Socotra as a trusted service provider. This setup allows your IdP to authenticate users attempting to access Socotra services.

* **Access Your IdP's Administration Console**: Log in to the administrative interface of your IdP (e.g., Azure AD, Auth0, Google SAML).
* **Add a New Application**: Initiate the process to register a new application. This option is typically labeled as "Add Application" or "Register App."
* **Capture the Single Sign-On Service URL**: Early in the app registration process, your IdP will create an SSO URL that needs to be registered with Socotra.

Step 2: Add your Identity Provider to Socotra [#step-2-add-your-identity-provider-to-socotra]

Next, you'll need to share your IdP's SAML metadata with Socotra to establish a trust relationship between the two systems.

To do so, use the <ApiLink name="addSAMLIdentityProvider">Add a SAML Identity Provider</ApiLink> endpoint, providing the following in the request body:

* `id`: A string that will uniquely identify the IdP in the context of your Socotra business account.
* `displayName`: (Optional) A string that will be used when viewing the IdP setup via the System Manager UI.
* `SSO URL`: The URL captured during the initial app registration process in [Step 1 above](#step-1-idp-registration).

Sample request [#sample-request]

```javascript
{
    "id": "my-test-idp",
    "displayName": "Google SAML Test",
    "singleSignOnServiceUrl": "https://accounts.google.com/o/saml2/idp?idpid=XXXXXXXX"
}
```

Step 3: Receive Service Provider (SP) Metadata from Socotra [#step-3-receive-service-provider-sp-metadata-from-socotra]

After processing your <ApiLink name="addSAMLIdentityProvider">Add a SAML Identity Provider</ApiLink> in the previous step, Socotra will generate and respond with its own Service Provider (SP) metadata, which you'll need to configure within your IdP. From this response, grab the following details:

* **Entity ID**: Socotra's unique identifier within your IdP.
* **Assertion Consumer Service (ACS) URL**: The endpoint on Socotra's side that will receive SAML assertions from your IdP.

Sample response [#sample-response]

```javascript
{
    "id": "my-test-idp",
    "displayName": "Google SAML Test",
    "type": "saml",
    "acsUrl": "https://kern-dev-idp.socotra.com/auth/realms/XXXX/broker/my-test-idp/endpoint",
    "entityId": "https://kern-dev-idp.socotra.com/auth/realms/XXXX",
    "singleSignOnServiceUrl": "https://accounts.google.com/o/saml2/idp?idpid=XXXXXXXX"
}
```

Step 4: Configure Your Identity Provider with Socotra's SP Metadata [#step-4-configure-your-identity-provider-with-socotras-sp-metadata]

Integrate Socotra's SP metadata into your IdP to finalize the SSO setup.

* **Access IdP's Application Settings**: Navigate to the application configuration section within your IdP's administrative console and update the following SAML settings:
  * **ACS URL**: Input Socotra's Assertion Consumer Service URL.
  * **Entity ID**: Enter Socotra's Entity ID as provided in their SP metadata.
  * **Single Logout URL**: If applicable, configure the Single Logout URL as specified by Socotra.

Step 5: Test the SSO Integration [#step-5-test-the-sso-integration]

Verify that the SSO configuration functions correctly before rolling it out to all users.

* **Initiate SSO Login**: When attempting to log in to Socotra using the SSO option, the login screen will present options to sign in via your IdP. Look for the `Or sign in with` section.
* **Verify Authentication**: Ensure that the authentication process redirects you to your IdP for login and subsequently grants access to Socotra upon successful authentication.

<Callout>
  IdP-initiated SAML login is not yet supported. To authenticate, users must start the login process from Socotra.
</Callout>

Key SSO Capability Clarifications [#key-sso-capability-clarifications]

* Once the IdP App Registration and setup is complete, you control Socotra access for users belonging to that authentication realm within the IdP itself.
* Depending on the IdP, the default may be that none, or all, of the users are initially granted access.
* The SSO process defers to the IdP for user authentication only. Roles, permission and tenant scope is still controlled within the Socotra [User Management Service](/api/business-accounts/user-management).

<Callout>
  Automated attribute mapping for user roles and permissions assignment is not yet supported.
</Callout>


# Quantifiers



Overview [#overview]

Socotra Insurance Suite has built-in structures for managing "quantification." For example, if a personal auto policy has vehicles and the perils represent coverages like comprehensive and collision, you may want to ensure that each vehicle has *exactly one each* of these coverages. *Quantifiers* are the mechanism that addresses this and other similar needs.

Structure [#structure]

Quantifiers are specified for an item in configuration with one of these suffixes:

* (no suffix): Exactly one of this type is required
* `!`: Like no suffix, except it will be created automatically if not already present
* `?`: Zero or one is required
* `*`: Any number of these are OK
* `+`: There must be one or more of these

Element Quantifiers [#element-quantifiers]

Each [element](/features/policy-management/policy-elements) within a product configuration may contain sub-elements based on the product's configuration. For example, a personal auto policy might be structured like this:

* Product `personalAuto`
  * exposure `vehicle+`
  * coverage `collision!`
  * coverage `comprehensive`
  * coverage `roadsideAssistance?`

In this example, the `+` suffix for the `vehicle` means the policy must have at least one vehicle to be validated. The `!` suffix for the `collision` coverage means that that element will be added automatically when the vehicle element is created, if it isn't included as part of the creation request. The lack of suffix on `comprehensive` means there must be exactly one comprehensive element per vehicle. And the `?` suffix on `roadsideAssistance` means that there must be either zero or one of those elements.

Coverage Term Quantifiers [#coverage-term-quantifiers]

[Coverage terms](/features/policy-management/coverage-terms) for an element can be declared with a `?` suffix, which means they are optional, or no suffix, which means there must be exactly one coverage term of that type for that element, or with a `!` suffix, which means it is automatic. The other quantifiers do not apply to coverage terms.

Default Coverage Term Options [#default-coverage-term-options]

In configuration, one allowed value for a coverage term may be prefixed with a `*` symbol, which means it is the default value if a value is not specified. See the [Default Coverage Term Options](/features/policy-management/coverage-terms#default_coverage_term_options) section of the [Coverage Terms Guide](/features/policy-management/coverage-terms) for details.

Data Extension Quantifiers [#data-extension-quantifiers]

The type declaration in configuration for data extensions for an element or account can have any of the quantifiers except for automatic (`!`).

Blank (i.e. no suffix) means that the property is required, and `?` means that it is optional.

The `+` quantifier signifies an array with one or more of the items, and `*` is for an array with any number of items.

Automatic Items [#automatic-items]

The `!` suffix means the item will be created automatically upon validation if it's not included in the creation request. The requirements for automatic items vary by the type.

<Callout>
  If a policy transaction attempts to remove an automatic element or other item, the system will add it back when the transaction is validated.
</Callout>

Automatic Elements [#automatic-elements]

For elements to be created automatically, they must have the following:

* There must be no fields on the element that do not have default values.
* There must be no coverage terms on the element that do not have default values.
* If the element has automatic subelements itself, then each of those subelements must meet the above criteria. This requirement can cascade down if the product graph contains multiple levels.

These requirements are all verifiable by examining the configuration, and any conflicts should cause the configuration deployment to fail.

Automatic Coverage Terms [#automatic-coverage-terms]

Coverage terms configured with an automatic `!` suffix must have a default option as one of their options.

Automatic Custom Data Types [#automatic-custom-data-types]

[Custom data types](/configuration/data-extensions/custom-data-types) configured with `!` must have defaults set on contained fields. As with automatic elements, this requirement recurses through nested definitions.


# Configuration Redeployment



Overview [#overview]

The first configuration for a tenant is deployed when the tenant is created. Any subsequent deployment is called a *redeployment*. The structure of a redeployed configuration is the same as for the first deployment, but there are rules about the changes to the configuration package that must be followed to ensure compatibility with existing data in the tenant.

<span id="redeployment_safety" />

The differences between a redeployed configuration and the existing active configuration fall into one of these categories:

* **Safe** changes are allowed without restriction.
* **Disallowed** changes will always cause re-deployment to fail.

If all changes between the new configuration and the active configuration are *Safe*, then the redeployment will overwrite the existing active configuration.

<Callout type="warn">
  Clients can force the redeployment of unsafe changes for test tenants in non-production environments by setting the `overwrite` flag to `true`. This will cause the latest configuration to be overwritten with the configuration in the payload. This could cause system instability and data incompatibility, so should only be done with thorough testing on a test tenant. After the migration features described in this topic are delivered, it will be discouraged to bypass redeployment safety checks.
</Callout>

Safe Changes [#safe-changes]

<Callout type="warn">
  The evaluation of a configuration change as `Safe` is based on the *system's* ability to anticipate and handle certain changes. Some changes may be defined as `Safe` but cause errors or exceptions in client-created plugin code or template definitions. You should always test prospective configuration changes in a test tenant before deploying them to production.
</Callout>

The following changes are defined as `Safe` and can be deployed without restriction:

* Adding new definitions for:
  * Accounts
  * Products
  * Elements (of any category)
  * Charges
  * Custom Data Types
  * Coverage Terms
  * Documents
  * Tables
  * Installment Plans
  * Regions
  * Jurisdictions

* Changing any of these properties, either globally or for a specific product:
  * `defaultDurationBasis`
  * `defaultTermLength`
  * `defaultTimeZone`
  * `defaultCurrency`
  * `defaultTimeZone`
  * `defaultInstallmentPlan`

* Omitting any top-level property (this will be interpreted as leaving that item or class of item unchanged.)

* Adding to a product's `eligibleAccountTypes` if the list is not empty (in other words, if the restrictions are being made more liberal.)

* Removing or changing the `displayName` or any other UI support values for any item

* Making any of these changes for products or elements:
  * Adding subelements to the `contents` using the `?` or `*` quantifier

  * Changing the quantifier of any item in `contents`:
    * From `+` to `*`
    * From `(blank)` to `?`
    * From `!` to `(blank)`
    * From `(blank)` to `!` if all the requirements for the automatic quantifier are met for that element definition

  * Adding coverage terms with quantifier `?`

  * Changing the quantifier of any coverage term from `(blank)` to `?`

  * Changing the `abstract` property of any entity from `true` to `false`

  * Moving properties to or from a base entity, or adding, removing, or changing the `extend` property such that the derived entity is unchanged or has safe changes only -- and if the base entity is not `abstract`, it too has only safe changes. This means that it is the final structure of the item that is being evaluated, irrespective of whether it has that structure because of inheritance or explicit declarations.

* Making any of these changes for coverage terms:
  * Changing the default coverage term option (as indicated by the `*` prefix)
  * Changing the `value` or `tag` of any coverage term option

* Making any of these changes to data extension properties:
  * Removing `min` or making it a smaller (or more negative) value
  * Removing `max` or making it a larger (or less negative) value
  * Removing `minLength` or making it a smaller value
  * Removing `maxLength` or making it a larger value
  * Removing `regex`
  * Adding to the `options` list for a property that already has at least one option
  * Removing the `options` list
  * Increasing the `precision` of a numeric property
  * Adding or changing the `defaultValue`
  * Removing a required (`(blank)` or `+`) data extension, or making them optional (`?` or `*`, respectively)
  * Adding a new required data extension, or changing it from optional to required, **with** a `defaultValue` (see <ApiLink name="PropertyRef" />). The default value will be used whenever a record is changed and no other value is provided, ensuring that the system is able to validate the record against the current configuration. Historical data will not be updated otherwise.

Disallowed Changes [#disallowed-changes]

Any change not specifically indicated as `Safe` is `Disallowed`. This includes, but is not limited to, these changes:

* Making any of these changes to a product or element definition:
  * Changing the quantifier of any of its `contents`:
    * From `*` or `?` to any other value
    * To `!` if the requirements are not met for automatic creation of the element

  * Removing an element from a product's or element's `contents` list

  * Changing the quantifier for a coverage term from `?` to `blank`, or removing a coverage term

* Removing a coverage term option from a coverage term

Future Functionality [#future-functionality]

Upcoming configuration versioning functionality will allow for the deployment of a subset of currently disallowed changes, which will then be classed as "migratable". Configuration versioning will allow for multiple configuration versions on a tenant, where each configuration is assigned an effective date. The feature will provide data migration capabilities to be used in conjunction with a customer-developed migration plugin.


# Regions



Overview [#overview]

In Socotra Insurance Suite, regions are used to lend organizational context to the work being done. While generally used to represent a geographic region or state (e.g. `"North East"`, `"South West"`, `"SW"`, `"CA"`, `"TX"`, `"VIC"`, `"NSW"` etc), implementers may define whatever collection of regions makes sense for their business use cases.

Regions are defined as a list of strings in configuration, and on the operational side can be assigned to draft quotes. The region value on a quote is automatically copied over to the policy upon issuance. Adding regions to the configuration is optional, as is utilizing them on any given quote or policy.

Once set on a quote and validated, the `region` property is fixed for the life of the policy. The property will appear at the top level of a <ApiLink name="QuoteResponse">quote</ApiLink> and <ApiLink name="PolicyResponse">policy</ApiLink>.

Use Cases [#use-cases]

There are currently three primary use cases for the `region` property, with more to follow.

1. **Reporting:** The `region` property is replicated into [Data Lake](/features/reporting/datalake) and can be leveraged to bring the intended context through to reporting.
2. **Data Access Control:** The `region` property can be leveraged as one of several values upon which implementers can control which users can access which quotes, policies, or their related entities via the [Data Access Controls](/features/security/data-access-controls) feature.
3. **Work Management:** In a work management context, regions will be used primarily as a container for users, groups, and business practice settings. An activity (a specific task or item of work to be done) can be assigned to someone in a given region. More details to follow as our forthcoming Work Management capabilities reach general availability.

Configuration [#configuration]

Like many other configurable entities, regions are defined in <ApiLink name="ConfigurationRef">configuration</ApiLink> as a map of <ApiLink name="RegionRef" />.

```javascript
{
  // other config entities
  "regions":{
      "NW": {
          "displayName" : "North West"
      },
      "NE": {
          "displayName" : "North East"
      }
  }
}
```

Quote and Policy Regions [#quote-and-policy-regions]

Assuming there have been regions configured for the tenant, a quote can be assigned a region while in draft state via a <ApiLink name="createQuote">create</ApiLink> or <ApiLink name="updateQuote">update</ApiLink> request.

<ApiEndpoint name="createQuote" title="Create a Quote" />

<ApiSchema name="QuoteCreateRequest" />

If set, the `region` property will appear in the top level of the response when fetching a <ApiLink name="fetchQuote">quote</ApiLink> or <ApiLink name="fetchPolicy">policy</ApiLink>.

<ApiEndpoint name="fetchQuote" title="Fetch a Quote" />

<ApiSchema name="QuoteResponse" />

<ApiEndpoint name="fetchPolicy" title="Fetch a Policy" />

<ApiSchema name="PolicyResponse" />


## API Reference

POST /policy/{tenantLocator}/quotes — createQuote
Permissions: write, create
Parameters:
  tenantLocator (uuid, path, required)
Request body (QuoteCreateRequest):
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/quotes/{locator} — fetchQuote
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 QuoteResponse — OK

GET /policy/{tenantLocator}/policies/{locator} — fetchPolicy
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 PolicyResponse — OK

QuoteCreateRequest
Properties:
  productName (string, required)
  accountLocator (ulid, required)
  startTime (datetime, required)
  endTime (datetime)
  expirationTime (datetime)
  currency (string)
  timezone (string)
  jurisdiction (string)
  coverageTerms (map<string, object>)
  data (map<string, object>, required)
  elements (ElementCreateRequest[])
  durationBasis (Enum years | months | weeks | days | hours)
  preferences (Preferences)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  billingLevel (Enum account | inherit | policy)
  region (string)
  quoteGroupLocator (ulid)
  static (map<string, object>)
  contacts (ContactRoles[], required)
  invoiceFeeAmount (number, required)
  termDuration (integer)
  producerCode (string)
  proxyPayerLocator (ulid)

QuoteResponse
Properties:
  locator (ulid, required)
  quoteState (Enum draft | validated | earlyUnderwritten | priced | underwritten | accepted | issued | underwrittenBlocked | declined | rejected | refused | discarded, required)
  productName (string, required)
  accountLocator (ulid, required)
  startTime (datetime)
  endTime (datetime)
  timezone (string)
  currency (string)
  underwritingStatus (string)
  expirationTime (datetime)
  element (ElementResponse, required) — The root element in the hierarchy
  preferences (Preferences) — Plan selections and setting overrides
  policyLocator (ulid)
  delinquencyPlanName (string)
  durationBasis (Enum years | months | weeks | days | hours)
  groupLocator (ulid)
  autoRenewalPlanName (string)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  quoteNumber (string)
  duration (number) — The duration of the prospective policy in units of durationBasis
  acceptedTime (datetime)
  issuedTime (datetime)
  validationResult (ValidationResult)
  quickQuoteLocator (ulid)
  contacts (ContactRoles[], required)
  anonymizedAt (datetime)
  invoiceFeeAmount (number)
  createdBy (uuid)
  createdAt (datetime)
  jurisdiction (string)
  producerCode (string)
  reservedPolicyNumber (string)
  proxyPayerLocator (ulid)
  static (map<string, object>)
  policyNumber (string)

PolicyResponse
Properties:
  locator (ulid, required)
  accountLocator (ulid, required)
  branchHeadTransactionLocators (ulid[]) — The locators of all the top-level transactions on the policy, one per branch
  issuedTransactionLocator (ulid, required) — The locator of the latest issued transaction for the policy.
  productName (string, required)
  timezone (string, required)
  currency (string, required)
  durationBasis (Enum years | months | weeks | days | hours, required)
  createdAt (datetime, required)
  createdBy (uuid, required)
  delinquencyPlanName (string)
  autoRenewalPlanName (string)
  startTime (datetime, required) — The start time, based on issued transactions only
  endTime (datetime, required) — The end time based on issued transactions only.
  latestTermLocator (ulid, required)
  billingLevel (Enum account | inherit | policy, required)
  region (string)
  policyNumber (string)
  latestSegmentLocator (ulid, required) — The last segment on the policy, based on issued transactions only
  contacts (ContactRoles[], required)
  statuses (Enum[], required)
  invoiceFeeAmount (number)
  anonymizedAt (datetime)
  coverageEndTime (datetime)
  moratoriumElections (map<string, string>, required)
  jurisdiction (string)
  producerCode (string)
  producerCodeOfRecord (string)
  proxyPayerLocator (ulid)
  static (map<string, object>, required)
  validationResult (ValidationResult)

# 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
Permissions: read
Parameters:
  tenantLocator (uuid, path, required)
  policyLocator (ulid, path, required)
Responses:
  200 ScheduledPolicyEvent[] — OK

GET /event/{tenantLocator}/events/schedules/tenant — fetchScheduledTenantEvents
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)

# Webhooks



Webhooks bring efficiency and responsiveness to solution architectures, facilitating event-based flows among applications and services. In Socotra Insurance Suite, they are customized callbacks that allow external services to receive real-time notifications when specific events occur. This functionality enables seamless integrations that can react to changes as quickly as possible.

Managing Webhooks [#managing-webhooks]

You create a webhook with a `POST` request to the <ApiLink name="CreateWebhookRequest">Create Webhook</ApiLink> endpoint, specifying the URL and event types that pertain to the webhook. The endpoint will then receive an <ApiLink name="EventResponse" /> payload whenever the relevant event occurs. Webhooks and the [Event Stream](/configuration/general-topics/events) share the same <ApiLink name="EventResponse" /> structure to describe an event.

Failure Handling [#failure-handling]

You can define a failure handling strategy for each webhook, ensuring that the system responds in a preferable way if it encounters a problem posting messages to the webhook endpoint. Strategies revolve around these questions:

1. For which errors should the failure handling strategy apply?
2. Should an endpoint (`alertEndpoint`) receive failure notices?
3. Should the platform automatically retry on message delivery failure? If so, how many attempts (`1` to `10`, default `3`), and what should the time interval and pattern be (`linear` or `exponential`)?
4. Should the platform persist messages that fail to be delivered? These can be retrieved later via the [Diverted Events API](/api/events/diverted-events).

If no `failureHandling` is specified, the default strategy will apply:

```json
"failureHandling": {
    "triggers": [
        "4xx",
        "5xx",
        "timeout"
    ],
    "divert": false,
    "suspend": false
}
```

The default specifies no <ApiLink name="RetryStrategyCreateRequest">retry strategy</ApiLink> or <ApiLink name="CreateEndpointRequest">alert endpoint</ApiLink> and does not automatically suspend the webhook, nor does it divert failed messages for later pickup via the [Diverted Events API](/api/events/diverted-events). It effectively means "behave with indifference as to whether message delivery succeeds".

The `triggers` array can be populated with specific 400- or 500-level HTTP codes, or all in those levels (`"4xx"`, `"5xx"`). The special keyword `"timeout"` is also recognized.

If `suspend` is set to `true`, it means that the webhook will be suspended automatically if it exhausts all retry attempts while trying to deliver a message. If no retry strategy is specified, no retry attempts will be made, and the webhook will be suspended following the first failure. Webhook suspension will result in an event being posted to the `alertEndpoint` if one has been configured, and subsequent messages diverted if the `divert` property is set to `true`. Webhooks can be unsuspended with the <ApiLink name="unsuspendWebhook">unsuspend endpoint</ApiLink> endpoint.

When defining a retry strategy, you may set the `type` to `linear` or `exponential`. While `linear` results in a request being made at a constant frequency specified by the `interval` (in milliseconds), `exponential` means that the wait period between retry attempts will grow as defined in the equation `{interval}} + {attempt}^4`.

<Callout>
  The timeout on a webhook is 10000 milliseconds.
</Callout>

<span id="webhooksSecurity" />

Security Features [#security-features]

`https://` <ApiLink name="CreateEndpointRequest">endpoints</ApiLink> can be configured with the following:

* A [secret`to be used in an HMAC signature (see`RFC 2104 - Keyed-Hashing for Message Authentication ](https://datatracker.ietf.org/doc/html/rfc2104)) that will be supplied in the `socotra-signature` header of messages sent to that endpoint.
* A `tag` to label which `secret` is currently in use. Must be between 2 and 32 characters, inclusive.
* An `hmacEnabled` flag that determines whether the `socotra-signature` should be derived and sent in message headers.
* A `secureSSL` flag that toggles TLS certificate verification. It is `true` by default.

`secret` can only contain alphanumeric characters and underscores, with a length between 8 and 64 characters.

The `tag` is optional, intended as a convenience that can facilitate secret rotations by ensuring that message recipients can easily identify which secret was used to generate the signature value. Even if there are in-flight messages using an old shared secret when you update the secret on the Socotra platform (with a new tag), your receiving code can identify those by the prior `tag` and use the corresponding prior secret value to verify the signature.

<Callout>
  The ability to disable TLS certificate verification is provided for testing and configuration purposes. It should not be left as `false` in production systems handling real customer data.
</Callout>

Signature Verification [#signature-verification]

The `socotra-signature` header takes the following form:

```
socotra-signature: t=<timestamp>,v1=<signature>,tag=<tag>
```

* `timestamp` is the UTC timestamp associated with the event transmission, in milliseconds.
* `signature` is the SHA-256 HMAC-hashed signature of the concatenated values `timestamp.JSONpayload.tag`. If there is no tag associated with the shared secret, then the value is derived from `timestamp.JSONpayload`.
* `tag` is the optional tag name supplied in `SecuritySpecification` as a label for the current shared secret.

For verification, the signature derivation can be performed with standard cryptographic library functions in all popular programming languages. Below is an example in JavaScript:

```javascript
const crypto = require('crypto');

const secret = 'abracadabraabracadabraabracadabraabracadabraabracadabra';

const timestamp = '1695835536124';
const jsonPayload =
	'{"id":"20012343863","transactionId":"254cb37e-43c4-4102-845a-fbfc5978537d","timestamp":1695835536078,"data":{"username":"alice.lee"},"type":"login.success","username":"alice.lee"}';
const tag = 'secret-1';

const algorithm = 'sha256';
const hmac = crypto.createHmac(algorithm, secret);

hmac.write(`${timestamp}.${jsonPayload}.${tag}`);
hmac.end();

const hash = hmac.read().toString('hex');
console.log('HMAC: ', hash);
```

See Also [#see-also]

* [Events](/configuration/general-topics/events): List of events and data structures
* [Webhook API reference](/api/configuration-and-development/webhooks): Details on creating, reading, listing, updating, and deleting webhooks


# Automation Plugin



import Image from 'next/image';

The Automation Plugin allows you to implement custom business logic, create your own Socotra API endpoints, define request and response objects, and send HTTP requests to both third-party and Socotra API endpoints. This allows implementing teams to address most automation, integration, and orchestration requirements directly within the core platform.

This plugin can be executed manually by calling the [Execute Automation Plugin](/api/configuration-and-development/automation-plugin) API endpoint. It can also be configured to execute in response to events that occur within the Socotra Insurance Suite.

The Automation Plugin must be implemented as a `Global` implementation, not a `Product` implementation. See the [Plugins Overview](/configuration/plugins/overview) guide for more information.

We recommend using the [Configuration SDK](/configuration/general-topics/configuration-sdk) for plugin development.

<Callout>
  The Automation Plugin currently supports API calls only via the [Java HttpClient ](https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/HttpClient.html). A Socotra API-specific client is planned for a future release to simplify the process of calling Socotra API endpoints.
</Callout>

Use Cases [#use-cases]

The Automation Plugin supports a wide variety of use cases. Some examples include:

* Generating and attaching documents such as certificates of insurance or delinquency notices
* Updating [static data](/configuration/data-extensions/static-data)
* Monitoring, reporting, and analytics

<Callout type="warn">
  The rest of this guide is based on the config-sdk-template project used in the [Configuration SDK](/configuration/general-topics/configuration-sdk) guide.
</Callout>

Configuring the Automation Plugin [#configuring-the-automation-plugin]

The Automation Plugin can be configured through <ApiLink name="AutomationPluginRef">AutomationPluginRef</ApiLink> configuration objects.

Here's an example of the folder structure:

<Image src="/images/automation_plugin/plugin_dir_structure.png" alt="Automation Plugin Directory Structure" width={200} height={1982} unoptimized />

In the example above, the `AttachDocument` and `PolicyRenewal` folders refer to the names of your Automation Plugin implementations. You can create as many implementations as you'd like. Each implementation can contain multiple actions, which correspond to method names in your Java implementation classes.

Here's an example of a `config.json` file for the `AttachDocument` implementation:

```json
{
	"actions": {
		"attachCertificateOfInsurance": {
			"timeout": 3,
			"request": {
				"contactName": {
					"displayName": "Contact Name",
					"type": "string"
				},
				"policyNumber": {
					"displayName": "Policy Number",
					"type": "string"
				}
			},
			"response": {
				"result": {
					"displayName": "Result",
					"type": "boolean",
					"defaultValue": "true"
				}
			}
		},
		"attachReport": {
			"timeout": 10,
			"request": {
				"reportType": {
					"displayName": "Report Type",
					"type": "string"
				},
				"reportName": {
					"displayName": "Report Name",
					"type": "string"
				}
			},
			"response": {
				"result": {
					"displayName": "Result",
					"type": "boolean",
					"defaultValue": "true"
				}
			}
		}
	}
}
```

In the example above, `attachCertificateOfInsurance` and `attachReport` are the names of actions available within the `AttachDocument` implementation, and each action specifies properties within the request and response objects.

Request and response objects can contain both [built-in data types](/configuration/data-extensions/data-extension-types) and [custom data types](/configuration/data-extensions/custom-data-types). The built-in `object` data type can accommodate more complex data models.

<Callout>
  Request and response objects used by Automation Plugin implementations do not currently support [data scopes](/configuration/data-extensions/overview#data-scopes).
</Callout>

Once you've finished making changes to your configuration, execute the `deployConfigToTenant` Gradle task to [deploy](/configuration/general-topics/deployment) your configuration.

Implementing the Automation Plugin [#implementing-the-automation-plugin]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder using the following naming convention for the class name: `PluginNameAutomationPluginImpl`. You can name your class whatever you'd like, but we suggest following this naming convention. Your Java implementation classes must be contained within this folder.

Here's an example of the `AttachDocumentAutomationPluginImpl` class for the `AttachDocument` implementation:

```java
public class AttachDocumentAutomationPluginImpl implements AttachDocumentAutomationPlugin {
    private static final Logger log = LoggerFactory.getLogger(AttachDocumentAutomationPluginImpl.class);

    @Override
    public AttachDocumentAttachCertificateOfInsuranceResponse attachCertificateOfInsurance(AttachDocumentAttachCertificateOfInsuranceRequest attachDocumentAttachCertificateOfInsuranceRequest) {
        PluginExecutionContext context = PluginExecutionContext.get();
        AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();
        log.info("In AttachDocumentAutomationPluginImpl.attachCertificateOfInsurance()");
        log.info("Request fields: {} {}", attachDocumentAttachCertificateOfInsuranceRequest.contactName(), attachDocumentAttachCertificateOfInsuranceRequest.policyNumber());
        log.info("Context: {} {} {} {}", context.getRequestId(), context.getTenantLocator(), context.getBusinessAccount(), automationContext.secret());
        return new AttachDocumentAttachCertificateOfInsuranceResponse().builder().result(true).build();
    }

    @Override
    public AttachDocumentAttachReportResponse attachReport(AttachDocumentAttachReportRequest attachDocumentAttachReportRequest) {
        PluginExecutionContext context = PluginExecutionContext.get();
        AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();
        log.info("In AttachDocumentAutomationPluginImpl.attachReport()");
        log.info("Request fields: {} {}", attachDocumentAttachReportRequest.reportType(), attachDocumentAttachReportRequest.reportName());
        log.info("Context: {} {} {} {}", context.getRequestId(), context.getTenantLocator(), context.getBusinessAccount(), automationContext.secret());
        return new AttachDocumentAttachReportResponse().builder().result(true).build();
    }
}
```

The request and response classes are generated automatically using the following naming conventions: `PluginNameActionNameRequest` and `PluginNameActionNameResponse`. Request data can be retrieved through the fields defined in the request object configuration for each action. The response object can be constructed using the builder pattern to set a value for each field defined in the response object configuration.

In addition to the `PluginExecutionContext` [methods](/configuration/plugins/overview#plugin-execution-context) available to all plugins, the `AutomationPluginContextData` class contains the following methods:

* accessToken()
* secret()
* apiUrl()
* eventData()

HTTP requests can be performed using the [Java HttpClient ](https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/HttpClient.html). Refer to the [Plugins Overview](/configuration/plugins/overview) for more information.

Once you've finished making changes to your implementations, execute the `deployConfigToTenant` Gradle task. This will generate an API endpoint for each action defined in your implementations.

Creating an Event-Driven Automation Plugin Implementation [#creating-an-event-driven-automation-plugin-implementation]

A maximum of one Automation Plugin implementation can be configured to execute in response to events that occur within the Socotra Insurance Suite.

To designate an implementation as event-driven, add the following field to your Automation Plugin configuration.

For example:

```json
{
	"enableWebhooks": true
}
```

Execute the `refreshReferenceDatamodel` Gradle task to update the interface for your implementation.

Override the `handleWebhookEvent` method in your implementation.

For example:

```java
@Override
 public void handleWebhookEvent() {
     PluginExecutionContext context = PluginExecutionContext.get();
     AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();
     log.info("In AttachDocumentAutomationPluginImpl.handleWebhookEvent()");
     log.info("context: {} {} {} {}", context.getRequestId(), context.getTenantLocator(), context.getBusinessAccount(), automationContext.secret());
     log.info("context: {}", automationContext.eventData());
 }
```

Event-driven actions cannot have request and response objects. Context data can be retrieved from the `PluginExecutionContext` and `AutomationPluginContextData` classes.

Lastly, call the <ApiLink name="createWebhook">Create Webhook</ApiLink> API endpoint to create a webhook for your event-driven action. The `useAutomationPlugin` flag must be set to `true`.

Here's an example request:

```json
{
	"name": "Attach Document Webhook",
	"useAutomationPlugin": true,
	"enabled": true,
	"eventTypes": [
		"policy.account.create",
		"policy.account.update",
		"policy.account.validate",
		"policy.quote.create",
		"policy.quote.update",
		"policy.quote.validate",
		"policy.quote.price",
		"policy.quote.underwrite",
		"policy.quote.accept",
		"policy.quote.refuse",
		"policy.quote.discard",
		"policy.quote.manualunderwrite",
		"policy.quote.reset",
		"policy.quote.issue"
	],
	"failureHandling": {
		"removeAlertEndpoint": false,
		"alertEndpoint": {
			"url": "https://webhook.develop.socotra.com/cf276a2e-f48d-449d-9279-a1faf24ba51a",
			"headers": {
				"single": 0
			}
		},
		"triggers": ["4xx", "5xx", "timeout"],
		"retryStrategy": {
			"type": "linear",
			"interval": 1000,
			"attempts": 3
		},
		"divert": false,
		"suspend": false
	}
}
```

Unlike a regular webhook, this webhook does not send a request to an external API endpoint. It executes the `handleWebhookEvent` action instead.

Executing the Automation Plugin [#executing-the-automation-plugin]

After deploying your implementation, execute your Automation Plugin action by sending a `GET` or `POST` request to the <ApiLink name="executeAutomationPlugin">API endpoint</ApiLink> that was automatically generated by the system, based on the following naming convention: `plugin/{tenantLocator}/automation/{pluginName}/{actionName}`.

The only difference between sending a `GET` request and sending a `POST` request is that a `GET` request requires a response object to be configured for the specified action.

Here's an example request for the `attachReport` action:

```json
{
	"reportType": "Regulatory",
	"reportName": "GDPR Compliance"
}
```

Configuring Secrets [#configuring-secrets]

By default, the token that was used to authenticate a request sent to an Automation Plugin API endpoint will be available in the `accessToken` field within the `AutomationPluginContextData` class.

Additional secrets can be included in the `AutomationPluginContextData` class by adding the following field to the top level of the configuration for your Automation Plugin implementation:

```json
{
	"secret": "ExternalService"
}
```

In the example above, `ExternalService` refers to the `staticName` of a <ApiLink name="SecretRef">SecretRef</ApiLink> configuration object that must be specified in the tenant configuration. Each Automation Plugin configuration can specify a distinct `SecretRef` object or the same `SecretRef` object if necessary.

Here's an example of a `SecretRef` configuration object named `ExternalService`:

```json
{
	"items": {
		"url": {
			"dataType": "string"
		},
		"apiToken": {
			"dataType": "string"
		},
		"timeOutSeconds": {
			"dataType": "int"
		}
	}
}
```

Execute the `deployConfigToTenant` Gradle task to [deploy](/configuration/general-topics/deployment) your configuration.

Once these configurations have been deployed, create your secret using the <ApiLink name="createSecret">Create a Secret</ApiLink> API endpoint.

For example:

```json
{
	"name": "ExampleSecret",
	"staticName": "ExternalService",
	"secret": {
		"url": "https://example.url.com",
		"apiToken": "Bearer EXAMPLE_TOKEN",
		"timeOutSeconds": 1000
	}
}
```

Secrets must be added to at least one [resource group](/api/resources/resource-service) before they can be accessed through the `AutomationPluginContextData` class by using the <ApiLink name="createResourceGroup">Create a Resource Group</ApiLink> or <ApiLink name="updateResourceGroup">Update a Resource Group</ApiLink> API endpoint.

Here's an example request for the <ApiLink name="createResourceGroup">Create a Resource Group</ApiLink> API endpoint:

```json
{
	"name": "ExampleResourceGroup",
	"selectionStartTime": "2023-12-22T19:09:27+0000",
	"resourceNames": ["ExampleSecret"]
}
```

Here's an example request for the <ApiLink name="updateResourceGroup">Update a Resource Group</ApiLink> API endpoint:

```json
{
	"name": "ExampleResourceGroup",
	"selectionStartTime": "2023-12-22T19:09:27+0000",
	"addResources": ["ExampleSecret"]
}
```

Once the secret has been added to a resource group, execute the `refreshReferenceDatamodel` Gradle task to generate the Java class containing your secrets.

Secret fields can now be accessed through the `AutomationPluginContextData` class.

For example:

```java
PluginExecutionContext context = PluginExecutionContext.get();
AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();

var mapper = AbstractDeploymentFactory.defaultMapper();
ExternalService externalService = mapper.convertValue(automationContext.secret().get(), ExternalService.class);

String url = externalService.url();
String apiToken = externalService.apiToken();
Integer timeOutSeconds = externalService.timeOutSeconds();
```

Custom Data Types [#custom-data-types]

Request and response objects can contain [custom data types](/configuration/data-extensions/custom-data-types) in addition to [built-in data types](/configuration/data-extensions/data-extension-types).

Here's an example of a configuration for a custom data type called `Driver`:

```json
{
	"dataTypes": {
		"Driver": {
			"data": {
				"firstName": {
					"type": "string"
				},
				"lastName": {
					"type": "string"
				}
			}
		}
	}
}
```

This custom data type can now be referenced through the `type` field when configuring a request or response property.

For example:

```json
{
	"actions": {
		"attachCertificateOfInsurance": {
			"timeout": 3,
			"request": {
				"primaryDriver": {
					"displayName": "Primary Driver",
					"type": "Driver+"
				}
			},
			"response": {
				"secondaryDriver": {
					"displayName": "Secondary Driver",
					"type": "Driver+"
				}
			}
		}
	}
}
```

Request and response property configurations can include [quantifiers and arrays](/configuration/data-extensions/overview#quantifiers-and-arrays), which can be used to store multiple values.

For example, the above configuration uses the `+` quantifier, which indicates that the property is an array that can store one or more `Driver` objects.

See the [Data Extensions](/configuration/data-extensions/overview) and [Custom Data Types](/configuration/data-extensions/custom-data-types) feature guides for more information.

Error Handling [#error-handling]

By default, if an exception is encountered while executing an Automation Plugin implementation, an HTTP status code of `500` will be returned. You can return specific HTTP status codes and error messages by throwing an `AutomationPluginException`:

```java
throw new AutomationPluginException(500, "Error Message");
```

Refer to the Webhooks guide for information on defining error-handling strategies for webhooks.

Logging [#logging]

The [Logging API](/api/configuration-and-development/logging) can be used to view the history of Automation Plugin executions and Java logging messages.

First, retrieve a list of plugin executions using the <ApiLink name="fetchLogsList">Fetch a List of Logs</ApiLink> API endpoint. Optional query parameters can be used to narrow down this list.

For example, use the `createdAtMin` query parameter to view plugin executions that occurred after a specified timestamp:

```
createdAtMin=2026-07-25T22:00:00.000Z
```

For executions triggered via API requests, the `pluginType` within the corresponding <ApiLink name="PluginLogsMetadata">PluginLogsMetadata</ApiLink> object will be set to `automationHttp`, and the <ApiLink name="ObjectReference">ObjectReference</ApiLink> `locator` will be set to the event locator of the event that triggered the plugin execution.

For event-driven executions, the `pluginType` within the corresponding <ApiLink name="PluginLogsMetadata">PluginLogsMetadata</ApiLink> object will be set to `automationWebhook`, and the <ApiLink name="ObjectReference">ObjectReference</ApiLink> `locator` will be set to the same value as the `requestId`.

Next, retrieve Java logging messages for a plugin execution by calling the <ApiLink name="fetchLogs">Fetch Logs for a Request</ApiLink> API endpoint and specifying the target <ApiLink name="PluginLogsMetadata">PluginLogsMetadata</ApiLink> `locator` as the `locator` for the request.

Next Steps [#next-steps]

* [Integrations Plugin](/configuration/plugins/integrations)

See Also [#see-also]

* [Automation Plugin API](/api/configuration-and-development/automation-plugin)
* [Plugins](/configuration/plugins/overview)
* [Configuration SDK](/configuration/general-topics/configuration-sdk)
* [Webhooks](/configuration/general-topics/webhooks)
* [Logging API](/api/configuration-and-development/logging)


# Autopay Plugin



import Image from 'next/image';

The Autopay Plugin allows you to define invoice autopay logic for policyholders. When the plugin is executed, a payment will be created if a `PaymentCreateRequest` is contained in the return object.

Configuration [#configuration]

Adding a value for `autopayLeadDays` to an <ApiLink name="InstallmentPlanRef" /> configuration tells the platform how many days before an invoice's `dueTime` the Autopay Plugin should be executed. The value must be greater than 0, and can be specified as a decimal value for more precise timing. The default value is 1.

An `autopayTime` will be calculated for your target invoices based on the `autopayLeadDays` value and the invoice `dueTime`. If an invoice has more than one [installment](/features/billing/installments-and-installment-lattices), the invoice `autopayTime` will be the earliest `autopayTime` of its installments.

Here's an example of an `InstallmentPlanRef` configuration called `Quarterly`:

```json
{
	"displayName": "Quarterly",
	"cadence": "quarterly",
	"anchorMode": "termStartDay",
	"generateLeadDays": 14,
	"dueLeadDays": 0,
	"maxInstallmentsPerTerm": 1000,
	"autopayLeadDays": 2
}
```

Make sure to update your [installment settings](/features/billing/installment-settings) to use your `InstallmentPlanRef` configuration.

For example, you could specify a `defaultInstallmentPlan` in the product configuration:

```json
{
	"defaultInstallmentPlan": "Quarterly"
}
```

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `AutopayPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `AutopayPlugin` interface and override the `autopay` method.

For example, this implementation pays the total remaining amount on an invoice:

```java
public class AutopayPluginImpl implements AutopayPlugin {
    private static final Logger log = LoggerFactory.getLogger(AutopayPluginImpl.class);

    // Pay the total remaining amount on an invoice

    @Override
    public AutopayPluginResponse autopay(AutopayRequest autopayRequest) {
        Invoice invoice = autopayRequest.invoice();

        log.info("Received autopay request for invoice: {}", invoice.locator());

        return AutopayPluginResponse.builder()
                .paymentRequest(
                        PaymentCreateRequest.builder()
                                .type("StandardPayment")
                                .amount(invoice.totalRemainingAmount().orElseThrow())
                                .currency(invoice.currency())
                                .paymentState(PaymentState.requested)
                                .targets(
                                        List.of(
                                                CreditItem.builder()
                                                        .containerLocator(invoice.locator())
                                                        .containerType(CreditContainerType.invoice)
                                                        .build()))
                                .data(
                                        Map.of(
                                                "note",
                                                "from AutopayPlugin",
                                                "payerFirstName",
                                                "John",
                                                "payerLastName",
                                                "Doe"))
                                .build())
                .nextRequestTime(Instant.now())
                .build();
    }
}
```

The method request object contains the invoice.

The method returns an `AutoPayPluginResponse` with `paymentRequest` and `nextRequestTime` properties.

The `PaymentCreateRequest` object contains the following fields:

* `type` - Refers to a <ApiLink name="PaymentRef" /> configuration
* `amount` - The payment amount
* `currency` - The payment currency
* `paymentState` - The state of the payment that will be created by the plugin
* `financialInstrumentLocator` - The locator of the financial instrument that will be used to make the payment
* `targets` - One or more invoices that will be paid
* `retryPlanName` - The name of the payment execution [retry plan](/features/billing/payment-execution-service#retry-plans)
* `data` - [Extension data](/configuration/data-extensions/overview) that will be associated with the payment

The `nextRequestTime` can be used to delay the execution of the [Payment Execution Service](/features/billing/payment-execution-service) after the Autopay Plugin is executed. In the example above, the Payment Execution Service will be executed immediately after the plugin is executed. If no value is provided for `nextRequestTime`, the Payment Execution Service will be executed immediately after the plugin is executed.

Execution [#execution]

The system will execute the Autopay Plugin when the `autopayTime` is reached for an invoice.

The following diagram illustrates autopay timing:

<Image src="/images/autopay/autopay-timing.png" alt="autopay timing" width={800} height={337} unoptimized />

For payments created in the `requested` state, the [Payment Execution Service](/features/billing/payment-execution-service) will be executed after the plugin is executed.

Accounts must specify a default financial instrument before the Payment Execution Service can process payments. To specify a default instrument, first call the <ApiLink name="createFinancialInstrument">Create a Financial Instrument</ApiLink> API endpoint, then call the <ApiLink name="setFinancialInstrumentAsDefault">Set the Default Financial Instrument for a Tenant</ApiLink> API endpoint, using the financial instrument locator returned from the first request as the `locator` for the second request.

Here's an example request for the <ApiLink name="createFinancialInstrument">Create a Financial Instrument</ApiLink> API endpoint:

```json
{
	"externalIdentifier": "ExampleIdentifier",
	"institutionName": "ExampleInstitution",
	"instrumentType": "checking",
	"defaultTransactionMethod": "ach",
	"externalAccountNumber": "abc12345",
	"accountLocator": "01K0FDV1SRW6N6T407JQ7XSAE1",
	"nickname": "ExampleNickname"
}
```

After the Payment Execution Service is executed, the [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing) will be executed.

Once a payment moves to the `posted` state, corresponding invoices will move to the `settled` state as long as the invoices have been paid in full. Otherwise, invoices will remain in the `open` state.

Payment States [#payment-states]

The Autopay Plugin can be used to create a payment in a specific state. Payment processing behavior differs based on the state of the payment created by the plugin:

* `requested` - The Payment Execution Service will immediately attempt to process the payment through a payment provider such as Stripe or Braintree. Once the payment has been successfully processed, it will move to the `posted` state.
* `posted` - The Payment Execution Service will not attempt to process the payment. Creating a payment this way assumes that the Autopay Plugin code has successfully processed the payment by calling an external API via the [Java HttpClient ](https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/HttpClient.html).
* `draft` - The Payment Execution Service will not attempt to process the payment. The [Payments API](/api/billing/payments) can be used to manually move the payment to a different state.

Payments can be created in other states in addition to the states listed above. Refer to the `paymentState` field in the <ApiLink name="PaymentResponse" /> object for a complete list of payment states.

Disabling Autopay [#disabling-autopay]

The Autopay Plugin can be disabled for an invoice by calling the <ApiLink name="updateInvoice" /> API endpoint and setting `suppressAutopay` to `true`.

Here's an example request:

```json
{
	"suppressAutopay": true
}
```

Updating Autopay Time [#updating-autopay-time]

The `autopayTime` can be manually updated for an invoice by calling the <ApiLink name="updateInvoice" /> API endpoint and specifying an `autopayTime`.

Here's an example request:

```json
{
	"autopayTime": "2025-07-10T05:00:00Z"
}
```

The `autopayTime` can be set to any time before the invoice `dueTime`. If the `autopayTime` is set to a time in the past, the Autopay Plugin will be executed immediately.

<Callout>
  If the <ApiLink name="updateInvoice" /> API endpoint is used to trigger the Autopay Plugin, and the target invoice is already in the `settled` state, the endpoint will return a `400` error.
</Callout>

Events [#events]

The Autopay Plugin can generate the following [events](/configuration/general-topics/events):

* `billing.invoice.autopay` - The Autopay Plugin executed successfully
* `billing.invoice.autopayfailed` - The Autopay Plugin failed
* `billing.payment.request` - Payment transitioned to the `requested` state
* `billing.payment.execute` - Payment transitioned to the `executing` state
* `billing.payment.cancel` - Payment transitioned to the `cancelled` state
* `billing.payment.fail` - Payment transitioned to the `failed` state
* `billing.payment.validationfailed` - Payment failed to transition from the `draft` state to the `validated` state

Example [#example]

The following example is based on the Prism configuration. Contact your Socotra representative for more information.

```java
// Pay the total remaining amount on an invoice if the invoice fee amount is close to 10

@Override
public AutopayPluginResponse autopay(AutopayRequest autopayRequest) {
    Invoice invoice = autopayRequest.invoice();

    log.info("Received autopay request for invoice: {}", invoice.locator());

    Optional<ULID> policyLocator = invoice.invoiceItems().iterator().next().policyLocator();

    if (policyLocator.isPresent()) {
        Policy policy = DataFetcher.getInstance().getPolicy(policyLocator.get());

        if (invoice.totalRemainingAmount().isPresent()
                && policy.invoiceFeeAmount().isPresent()
                && policy
                .invoiceFeeAmount()
                .get()
                .subtract(BigDecimal.TEN)
                .abs()
                .compareTo(new BigDecimal("0.01"))
                <= 0) {
            return AutopayPluginResponse.builder()
                    .paymentRequest(
                            PaymentCreateRequest.builder()
                                    .type("StandardPayment")
                                    .amount(invoice.totalRemainingAmount().orElseThrow())
                                    .currency(invoice.currency())
                                    .paymentState(PaymentState.requested)
                                    .targets(
                                            List.of(
                                                    CreditItem.builder()
                                                            .containerLocator(invoice.locator())
                                                            .containerType(CreditContainerType.invoice)
                                                            .build()))
                                    .data(
                                            Map.of(
                                                    "note",
                                                    "from AutopayPlugin",
                                                    "payerFirstName",
                                                    "John",
                                                    "payerLastName",
                                                    "Doe"))
                                    .build())
                    .nextRequestTime(Instant.now())
                    .build();

        } else {
            return AutopayPluginResponse.builder().build();
        }
    } else {
        return AutopayPluginResponse.builder().build();
    }
}
```

Next Steps [#next-steps]

* [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* <ApiLink name="InstallmentPlanRef" />
* [Installment Lattices](/features/billing/installments-and-installment-lattices)
* [Installment Settings](/features/billing/installment-settings)
* [Payment Execution Service](/features/billing/payment-execution-service)
* [Financial Instruments and External Cash Transactions API](/api/billing/financial-instruments)
* [Invoices API](/api/billing/invoices)


# Cancellation Plugin



The Cancellation Plugin allows you to add [retention charges](/features/billing/retention-charges) to invoices during the policy cancellation process.

Retention charges can be specified as positive or negative amounts, providing the flexibility needed to implement minimum earned premium plans, short-rate penalties, fees, or refunds when policies are cancelled.

The Cancellation Plugin is triggered by pricing requests for [policy transactions](/features/policy-management/policy-transactions) with a `transactionCategory` of `cancellation`, as long as certain criteria are met. See the [Execution](#CancellationExecution) section for more information.

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `CancellationPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `CancellationPlugin` interface, and override the method corresponding to your target product type.

For example, the following class contains a method that adds a retention charge to invoices when commercial auto policies are cancelled:

```java
public class CancellationPluginImpl implements CancellationPlugin {
    private static final Logger log = LoggerFactory.getLogger(CancellationPluginImpl.class);

    // Add a retention charge to invoices when commercial auto policies are cancelled

    @Override
    public CancellationPluginResponse cancel(CommercialAutoRequest commercialAutoRequest) {
        CommercialAutoSegment currentSegment = commercialAutoRequest.segment();

        return CancellationPluginResponse.builder()
                .retentionCharges(
                        RatingSet.builder()
                                .ok(true)
                                .ratingItems(List.of(
                                        RatingItem.builder()
                                                .elementLocator(currentSegment.element().locator())
                                                .chargeType(ChargeType.minimumPremium)
                                                .amount(BigDecimal.valueOf(50))
                                                .tag("Tag")
                                                .build()
                                ))
                                .build())
                .build();
    }
}
```

The method argument contains the following fields:

* `policy` - The policy
* `segment` - The current segment
* `transaction` - The policy transaction
* `charges` - A list of default prorated retention `charges` calculated by the system before the Cancellation Plugin was executed. See the [Execution](#CancellationExecution) section for more information.

The method returns a `CancellationPluginResponse` object, which contains a list of `RatingItem` objects. Each `RatingItem` object represents a retention charge and contains the following fields:

* `elementLocator` - The locator of the element related to the retention charge
* `chargeType` - The retention charge type
* `amount` - The retention charge amount
* `tag` - An optional tag value

Retention charge types refer to <ApiLink name="ChargeRef" /> configuration objects with a `handling` value of `retention` and an `invoicing` value of `next`. ChargeRef names must be included in the list of `charges` in the <ApiLink name="ProductRef" /> configuration object for your target policy.

Retention charges can be associated with any element within a policy. Only one charge per retention charge type can be associated with each element.

Here's an example of a ChargeRef configuration object called `MinimumPremium`:

```json
{
	"category": "premium",
	"handling": "retention",
	"invoicing": "next"
}
```

Here's an example of the `charges` field in a ProductRef configuration object called `CommercialAuto`:

```json
{
	"charges": ["MinimumPremium"]
}
```

Data Fetcher [#data-fetcher]

The [Data Fetcher](/configuration/plugins/overview#PluginDataFetcher) can provide additional data required to calculate retention charges. The following methods are especially useful for this purpose:

* `getTermCharges()` - Retrieves all non-zero charges for issued transactions within a term
* `getTermSubsegmentSummaries()` - Retrieves a summary of each segment in a term, including the effective duration, effective charges, and extension [data](/configuration/data-extensions/overview)

<span id="CancellationExecution" />

Execution [#execution]

The Cancellation Plugin is executed when charges are saved in the system during the policy cancellation pricing process, as long as the following criteria are met:

* The cancellation takes effect during a coverage segment rather than a gap segment, meaning it is not a re-cancellation that takes effect after an existing cancellation
* The cancellation is not the re-application of an existing reversed cancellation for another [out-of-sequence](/features/policy-management/out-of-sequence-transactions) aggregate transaction

Policies can be cancelled via the [Policy Transactions API](/api/policy-management/policy-transactions), or as a result of a [delinquency](/features/billing/delinquency) if the delinquency plan has been configured to create a policy transaction with a `transactionCategory` of `cancellation`.

The Cancellation Plugin is triggered when [stateless invoice previews](/features/preview-operations#StatelessPreview) are generated. This allows you to preview retention charges. You can also <ApiLink name="transactionPricePreview">preview pricing for a hypothetical cancellation transaction</ApiLink>, which will be executed statelessly after the stateless execution of the [Rating Plugin](/configuration/plugins/rating).

The system begins the cancellation pricing process by first calculating default prorated cancellation charges, then executing the Cancellation Plugin.

After the plugin has been executed successfully, the system calculates the final cancellation charges by adding up the default prorated cancellation charges and the cancellation charges added by the Cancellation Plugin.

Finally, the system persists the calculation results.

If plugin execution fails, or the plugin returns an `ok` value of `false`, the cancellation pricing process will stop, cancellation pricing data will not be persisted, and the policy transaction will remain in the `validated` state. The Cancellation Plugin must be triggered again to restart the cancellation pricing process.

Output Validation [#output-validation]

The system automatically performs the following validation checks on each `RatingItem` object returned by the Cancellation Plugin:

* `amount` is a required field and must be a positive or negative value
* An `amount` of `0` will not result in a retention charge
* `rate` and `rateDifference` will be ignored and overwritten by the system
* `chargeType` must be included in the list of `charges` in the <ApiLink name="ProductRef" /> configuration object for your target policy

Plugin Considerations [#plugin-considerations]

* Minimum earned premium and minimum premium are distinct concepts enforced by different plugins at different points in the [policy lifecycle](/features/policy-management/policy-transactions#Process). Minimum earned premiums are enforced via the Cancellation Plugin when policies are cancelled, ensuring that a minimum amount is retained for a policy. Minimum premiums are enforced via the [Rating Plugin](/configuration/plugins/rating) when policies are issued, ensuring the initial policy premium meets a minimum threshold.
* Using the Cancellation Plugin does not guarantee an effective minimum earned premium for a term. Depending on how transactions are issued, it is possible for the effective premium for a given term to be less than the minimum earned premium as enforced by the plugin. For example, a policy cancellation could take effect on the second day of a term and then get reinstated on the last day of the term.
* Any minimum earned premium determinations made at the time of plugin execution are subject to change before the cancellation effective date due to the potential creation of flat charges via API requests.

Example [#example]

The following example is based on the Prism configuration. Contact your Socotra representative for more information.

```java
// Enforce a minimum earned premium of $100 when a policy is cancelled

public class CancellationPluginImpl implements CancellationPlugin {
    private static final Logger log = LoggerFactory.getLogger(CancellationPluginImpl.class);

    @Override
    public CancellationPluginResponse cancel(CommercialAutoRequest commercialAutoRequest) {
        Transaction transaction = commercialAutoRequest.transaction();
        CommercialAutoSegment currentSegment = commercialAutoRequest.segment();
        Collection<Charge> cancellationCharges = commercialAutoRequest.charges();

        if (cancellationCharges == null) {
            cancellationCharges = List.of();
        }

        log.info("All cancellation charges: {}", cancellationCharges);

        Map<ULID, Collection<Charge>> termCharges = DataFetcher.getInstance().getTermCharges(commercialAutoRequest.policy().latestTermLocator());

        log.info("All term charges: {}", termCharges);

        BigDecimal totalPremium = termCharges.values().stream()
                .flatMap(Collection::stream)
                .map(Charge::amount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal totalCancellationPremium = cancellationCharges.stream()
                .map(Charge::amount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal earnedPremium = totalPremium.add(totalCancellationPremium);
        BigDecimal minimumEarnedPremium = BigDecimal.valueOf(100L);
        BigDecimal retentionCharge = minimumEarnedPremium.subtract(earnedPremium);

        log.info("Total premium: {}, cancellation premium: {}, earned: {}, retention: {}",
                totalPremium,
                totalCancellationPremium,
                earnedPremium,
                retentionCharge);

        if (retentionCharge.compareTo(BigDecimal.ZERO) > 0) {
            log.info("Adding minimum earned retention charge to transaction {}, segment {}, element {}",
                    transaction.locator(),
                    currentSegment.locator(),
                    currentSegment.element().locator()
            );

            return CancellationPluginResponse.builder()
                    .retentionCharges(
                            RatingSet.builder()
                                    .ok(true)
                                    .ratingItems(List.of(
                                            RatingItem.builder()
                                                    .elementLocator(currentSegment.element().locator())
                                                    .chargeType(ChargeType.minimumPremium)
                                                    .amount(retentionCharge)
                                                    .build()
                                    ))
                                    .build())
                    .build();
        } else {
            return createEmptyRatingSet();
        }
    }

    private static CancellationPluginResponse createEmptyRatingSet() {
        return CancellationPluginResponse.builder()
                .retentionCharges(
                        RatingSet.builder()
                                .ok(true)
                                .ratingItems(List.of())
                                .build())
                .build();
    }
}
```

Next Steps [#next-steps]

* [Automation Plugin](/configuration/plugins/automation)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Retention Charges](/features/billing/retention-charges)
* [Policy Transactions](/features/policy-management/policy-transactions)
* [Policy Transactions API](/api/policy-management/policy-transactions)
* [Policy Lifecycle](/features/policy-management/policy-transactions#Process)
* [Delinquency](/features/billing/delinquency)
* [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher)


# Document Data Snapshot Plugin



The Document Data Snapshot Plugin allows you to add metadata to static and dynamic [documents](/configuration/resources/documents). It can also be used to add data to [dynamic documents](/features/documents/dynamic-documents).

This plugin will be automatically executed as part of the [document generation workflow](/configuration/resources/documents#policy_document_workflow) for quotes and policies, and before [invoice rendering](/features/billing/invoicing#invoiceRendering). The Document Data Snapshot Plugin will be executed after the [Document Selection Plugin](/configuration/plugins/document-selection) has been successfully executed. Document generation workflows can be customized through the <ApiLink name="DocumentConfigRef" /> configuration object for each document.

This plugin will also be executed when manually rendering documents using the <ApiLink name="renderDocument">Render Document</ApiLink> API endpoint.

Once this plugin has been successfully executed and document data and metadata have been updated, the document will transition to a new state: Dynamic documents will move to the `dataReady` state, and static documents will move to the `ready` state. Dynamic documents will move to the `ready` state after rendering.

The Document Data Snapshot Plugin is executed asynchronously.

Supported Entity Types [#supported-entity-types]

The Document Data Snapshot Plugin supports the following entity types:

* Quotes
* Policy Transactions
* Invoices

Configuration [#configuration]

Document generation workflows can be customized through the <ApiLink name="DocumentConfigRef" /> configuration object for each document. `DocumentConfigRef` configuration objects include the following properties:

* `trigger` - Specifies the quote, policy transaction, or invoice lifecycle state that will trigger the document generation process, which will execute the [Document Selection Plugin](/configuration/plugins/document-selection) followed by the Document Data Snapshot Plugin
* `scope` - Specifies the [document scope](/configuration/resources/documents#document-scope)
* `rendering` - Specifies whether the document is a [static (pre-rendered) document](/configuration/resources/documents) or a [dynamic document](/features/documents/dynamic-documents)
* `format` - The document file format
* `selectionTimeBasis` - Specifies the [selection time basis](/configuration/resources/versioned-resource-selection#the-selection-time-basis) for the document

Here's an example of a <ApiLink name="DocumentConfigRef" /> configuration object:

```json
{
	"trigger": "issued",
	"scope": "term",
	"rendering": "prerendered",
	"format": "pdf",
	"selectionTimeBasis": "currentTime"
}
```

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `DocumentDataSnapshotPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `DocumentDataSnapshotPlugin` interface, and override the method corresponding to your target entity type.

For example, the following class adds data and metadata to documents for commercial auto quotes:

```java
public class DocumentDataSnapshotPluginImpl implements DocumentDataSnapshotPlugin {
    private static final Logger log = LoggerFactory.getLogger(DocumentDataSnapshotPluginImpl.class);

    // Add data and metadata to documents for commercial auto quotes

    @Override
    public DocumentDataSnapshot dataSnapshot(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        CommercialAutoQuote commercialAutoQuote = commercialAutoQuoteRequest.quote();

        HashMap<String, String> metadata = new HashMap<>();
        metadata.put("exampleKey", "exampleValue");

        HashMap<String, Object> renderingData = new HashMap<>();
        renderingData.put("quote", commercialAutoQuote);

        return DocumentDataSnapshot.builder().metadata(metadata).renderingData(renderingData).build();
    }
}
```

The method request object contains the following properties for quotes:

* `quote` - The quote
* `trigger` - The quote lifecycle state that triggered the document generation process
* `config` - The <ApiLink name="DocumentConfigRef" /> object

The method request object contains the following properties for policy transactions:

* `policy` - The policy
* `transaction` - The policy transaction
* `segment` - The policy segment
* `trigger` - The policy transaction lifecycle state that triggered the document generation process
* `config` - The <ApiLink name="DocumentConfigRef" /> object

The method request object contains the following properties for invoices:

* `invoiceDetails` - <ApiLink name="InvoiceDetailsResponse">Invoice details</ApiLink>
* `config` - The <ApiLink name="DocumentConfigRef" /> object

The method returns a `DocumentDataSnapshot` object, which contains the `metadata` and `renderingData` to be added to all documents for your target entity type. `metadata` will be added to both static documents and dynamic documents. `renderingData` contains data that can only be rendered by dynamic documents. Static documents do not have `renderingData`.

Data contained within the `renderingData` for a dynamic document can be retrieved from the `data` object in Velocity templates.

Here's an example of a Velocity template that displays the values for two fields contained within the document's `renderingData`, named `firstName` and `lastName`:

```
<!DOCTYPE html>
<html>
<body>
    <p>First Name: $data.firstName</p>
    <p>Last Name: $data.lastName</p>
</body>
```

See the [Dynamic Documents](/features/documents/dynamic-documents#velocity-example) feature guide for more information.

<span id="documentDataSnapshotExample" />

Examples [#examples]

All examples are based on the Prism configuration. Contact your Socotra representative for more information.

Quote [#quote]

```java
// Add data and metadata to documents for commercial auto quotes

@Override
public DocumentDataSnapshot dataSnapshot(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
    CommercialAutoQuote commercialAutoQuote = commercialAutoQuoteRequest.quote();
    QuotePricing pricing = DataFetcherFactory.get().getQuotePricing(commercialAutoQuote.locator());
    HashMap<String, Object> renderingData = new HashMap<>();

    DecimalFormat df = new DecimalFormat("0.00");

    BigDecimal premiumTotal = BigDecimal.ZERO;
    BigDecimal otherTotal = BigDecimal.ZERO;

    if (pricing != null && pricing.items() != null) {
        for (Charge item : pricing.items()) {
            if ("premium".equalsIgnoreCase(item.chargeCategory().toString())) {
                premiumTotal = premiumTotal.add(item.amount());
            } else if (!"nonFinancial".equalsIgnoreCase(item.chargeCategory().toString())) {
                otherTotal = otherTotal.add(item.amount());
            }
        }
    }

    BigDecimal totalBillable = premiumTotal.add(otherTotal);

    HashMap<String, Object> enhancedPricing = new HashMap<>();

    enhancedPricing.put("premiumTotal", df.format(premiumTotal));
    enhancedPricing.put("otherTotal", df.format(otherTotal));
    enhancedPricing.put("totalBillable", df.format(totalBillable));

    renderingData.put("quote", commercialAutoQuote);
    renderingData.put("pricing", enhancedPricing);
    renderingData.put("productType", "CommercialAuto");

    HashMap<String, String> metadata = new HashMap<>();
    metadata.put("accountLocator", commercialAutoQuote.accountLocator().toString());

    return DocumentDataSnapshot.builder()
            .metadata(metadata)
            .renderingData(renderingData)
            .build();
}
```

Policy Transaction [#policy-transaction]

```java
// Add data and metadata to documents for commercial auto policies

@Override
public DocumentDataSnapshot dataSnapshot(CommercialAutoRequest commercialAutoRequest) {
    Policy policy = commercialAutoRequest.policy();
    Transaction transaction = commercialAutoRequest.transaction();
    CommercialAutoSegment segment = commercialAutoRequest.segment().orElse(null);

    if (segment == null) {
        log.error("Segment is missing in the commercial auto request");
    }

    HashMap<String, Object> renderingData = new HashMap<>();

    String pattern = "MM/dd/yyyy";
    DateFormat dateFormatter = new SimpleDateFormat(pattern);
    Date today = Calendar.getInstance().getTime();

    String todayAsString = dateFormatter.format(today);

    renderingData.put("todayAsString", todayAsString);
    renderingData.put("policy", policy);
    renderingData.put("transaction", transaction);
    renderingData.put("segment", segment);
    renderingData.put("productType", "CommercialAuto");

    HashMap<String, String> metadata = new HashMap<>();
    metadata.put("productType", "CommercialAuto");
    metadata.put("scope", commercialAutoRequest.config().scope().toString());

    return DocumentDataSnapshot.builder()
            .metadata(metadata)
            .renderingData(renderingData)
            .build();

}
```

Invoice [#invoice]

```java
// Add data and metadata to invoices

@Override
public DocumentDataSnapshot dataSnapshot(InvoiceDetailsRequest invoiceDetailsRequest) {
    NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(Locale.US);
    InvoiceDetails invoiceDetails = invoiceDetailsRequest.invoiceDetails();

    Map<String, Object> renderingData = new HashMap<>();

    String formattedTotalAmount = currencyFormat.format(invoiceDetails.totalAmount());
    String formattedTotalRemainingAmount = currencyFormat.format(invoiceDetails.totalRemainingAmount());

    renderingData.put("startTime", invoiceDetails.startTime());
    renderingData.put("endTime", invoiceDetails.endTime());
    renderingData.put("totalAmount", formattedTotalAmount);
    renderingData.put("totalRemainingAmount", formattedTotalRemainingAmount);

    HashMap<String, String> metadata = new HashMap<>();
    metadata.put("totalRemainingAmount", formattedTotalRemainingAmount);

    return DocumentDataSnapshot.builder()
            .metadata(metadata)
            .renderingData(renderingData)
            .build();
}
```

Next Steps [#next-steps]

* [Document Selection Plugin](/configuration/plugins/document-selection)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Documents](/configuration/resources/documents)
* [Dynamic Documents](/features/documents/dynamic-documents)
* [Policy Document Workflow](/configuration/resources/documents#policy_document_workflow)
* [Invoice Rendering](/features/billing/invoicing#invoiceRendering)
* <ApiLink name="DocumentConfigRef" />
* <ApiLink name="renderDocument" />


# Document Selection Plugin



The Document Selection Plugin allows you to determine whether a document will be generated and attached to a quote or policy.

This plugin will be automatically executed as part of the [document generation workflow](/configuration/resources/documents#policy_document_workflow) for quotes and policies, and before [invoice rendering](/features/billing/invoicing#invoiceRendering). The [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot) will be executed after the Document Selection Plugin has been successfully executed. Document generation workflows can be customized through the <ApiLink name="DocumentConfigRef" /> configuration object for each document.

The Document Selection Plugin is executed asynchronously.

Supported Entity Types [#supported-entity-types]

The Document Selection Plugin supports the following entity types:

* Quotes
* Policy Transactions

Configuration [#configuration]

Document generation workflows can be customized through the <ApiLink name="DocumentConfigRef" /> configuration object for each document. `DocumentConfigRef` configuration objects include the following properties:

* `trigger` - Specifies the quote, policy transaction, or invoice lifecycle state that will trigger the document generation process, which will execute the Document Selection Plugin followed by the [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot)
* `scope` - Specifies the [document scope](/configuration/resources/documents#document-scope)
* `rendering` - Specifies whether the document is a [static (pre-rendered) document](/configuration/resources/documents) or a [dynamic document](/features/documents/dynamic-documents)
* `format` - The document file format
* `selectionTimeBasis` - Specifies the [selection time basis](/configuration/resources/versioned-resource-selection#the-selection-time-basis) for the document

Here's an example of a <ApiLink name="DocumentConfigRef" /> configuration object:

```json
{
	"trigger": "issued",
	"scope": "term",
	"rendering": "prerendered",
	"format": "pdf",
	"selectionTimeBasis": "currentTime"
}
```

<span id="document_selection_actions" />

Actions [#actions]

Actions determine how the Document Selection Plugin handles a given document. For each document, one of the following actions can be specified:

* `generate` - Generate and attach a new document instance, and replace any currently attached instances of the same document within the same document `scope`
* `noAction` - No new document instances will be generated and attached, and any existing instances of the same document within the same document `scope` will remain attached
* `generateIfAbsent` - Generate and attach a new document instance if no instances of the same document within the same document `scope` are currently attached
* `remove` - Remove any currently attached instances of the same document within the same document `scope`

<Callout>
  The `remove` action does not affect documents if their `scope` value is set to `transaction`, since documents with this scope are associated with a transaction rather than a quote or policy.
</Callout>

When executing actions, the plugin considers two document instances to be instances of the same document if both document instances have the same `staticName` and `scope`. For multiple [versions](/configuration/resources/versioned-resource-selection) of the same document, all versions are considered to be instances of the same document.

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `DocumentSelectionPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `DocumentSelectionPlugin` interface, and override the method corresponding to your target entity type.

For example, the following class contains a method that selects documents for commercial auto quotes:

```java
public class DocumentSelectionPluginImpl implements DocumentSelectionPlugin {
    private static final Logger log = LoggerFactory.getLogger(DocumentSelectionPluginImpl.class);

    // Select documents for commercial auto quotes

    @Override
    public Map<String, DocumentSelectionAction> selectDocuments(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        return Map.of("TermsAndConditions", DocumentSelectionAction.generate);
    }
}
```

The method request object contains the following properties for quotes:

* `quote` - The quote
* `trigger` - The quote lifecycle state that triggered the document generation process
* `documentConfigs` - A list of <ApiLink name="DocumentConfigRef" /> objects

The method request object contains the following properties for policy transactions:

* `policy` - The policy
* `transaction` - The policy transaction
* `segment` - The policy segment
* `trigger` - The policy transaction lifecycle state that triggered the document generation process
* `documentConfigs` - A list of <ApiLink name="DocumentConfigRef" /> objects

The method returns a map of document names to [actions](#document_selection_actions).

Examples [#examples]

All examples are based on the Prism configuration. Contact your Socotra representative for more information.

Quote [#quote]

```java
// Generate and attach documents listed in the document configuration for the commercial auto product if they’re not currently attached to commercial auto quotes

@Override
public Map<String, DocumentSelectionAction> selectDocuments(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
    Map<String, DocumentSelectionAction> response = new HashMap<>();

    commercialAutoQuoteRequest.documentConfigs()
            .forEach(config ->
                    response.put(config.name(), DocumentSelectionAction.generateIfAbsent)
            );

    return response;
}
```

Policy Transaction [#policy-transaction]

```java
// Generate and attach a document upon renewal of commercial auto policies

@Override
public Map<String, DocumentSelectionAction> selectDocuments(CommercialAutoRequest commercialAutoRequest) {
    Map<String, DocumentSelectionAction> response = new HashMap<>();

    if (commercialAutoRequest.transaction().transactionCategory().equals(TransactionCategory.renewal)) {
        response.put("TermsAndConditions", DocumentSelectionAction.generate);
    }

    return response;
}
```

Next Steps [#next-steps]

* [Installments Plugin](/configuration/plugins/installments)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Documents](/configuration/resources/documents)
* [Policy Document Workflow](/configuration/resources/documents#policy_document_workflow)
* <ApiLink name="DocumentConfigRef" />
* [Versioned Resource Selection](/configuration/resources/versioned-resource-selection)


# Installments Plugin



The Installments Plugin allows you to adjust the `generateTime`, `dueTime`, and `autopayTime` of installments generated from [installment lattices](/features/billing/installments-and-installment-lattices) to suit business needs.

For example, installment timing may vary based on product type, first-time payments on new policies, or disruptions to installment schedules.

The Installments Plugin is triggered after installments are generated. Installments are generated from installment lattices after a quote or policy transaction is issued.

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `InstallmentsPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `InstallmentsPlugin` interface, and override the method corresponding to your target product type.

For example, the following class contains a method that adjusts installments for commercial auto quotes and policy transactions.

```java
public class InstallmentsPluginImpl implements InstallmentsPlugin {
    private static final Logger log = LoggerFactory.getLogger(InstallmentsPluginImpl.class);

    // Adjusts installments for commercial auto quotes and policy transactions

    @Override
    public InstallmentsPluginResponse updateInstallments(CommercialAutoRequest commercialAutoRequest) {
        Map<String, InstallmentUpdate> installmentUpdates = new HashMap<>();
        return InstallmentsPluginResponse.builder().installmentUpdates(installmentUpdates).build();
    }
}
```

The method argument contains an `InstallmentLattice` object, `Installment` objects, and an `InstallmentsPluginContext` object. The `InstallmentsPluginContext` object contains the following fields:

* `accountLocator` - The account locator
* `quoteLocator` - The quote locator
* `policyLocator` - The policy locator
* `transactionLocator` - The policy transaction locator

The method returns an `InstallmentsPluginResponse` object, which contains a map between installment locators and `InstallmentUpdate` objects. Each `InstallmentUpdate` object contains the following fields:

* `generateTime` - When an invoice for the installment will be generated
* `dueTime` - When the invoice is due
* `autopayTime` - When autopay logic is executed, if the [Autopay Plugin](/configuration/plugins/autopay) has been implemented

For each of these fields, if no value is specified, the original value will be used, unless it needs to be adjusted based on the [adjustment rules](#AdjustmentRules).

Installments with the same `generateTime` and `dueTime` will be combined into the same invoice when the `generateTime` is reached.

Additional data can be retrieved using the [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher).

<span id="AdjustmentRules" />

Adjustment Rules [#adjustment-rules]

The values for the `generateTime`, `dueTime`, and `autopayTime` fields will be automatically adjusted after plugin execution is complete based on the following rules:

* If the `generateTime` is after the `dueTime`, the `generateTime` will be set to the `dueTime`.
* If the `autopayTime` is not between `generateTime` and `dueTime`, the `autopayTime` will be set to either the `generateTime` or one day before the `generateTime`, whichever is later.

Execution [#execution]

The Installments Plugin is triggered after installments are generated. Installments are generated from installment lattices after a quote or policy transaction is issued.

Example [#example]

The following example is based on the Prism configuration. Contact your Socotra representative for more information.

```java
// Adjusts the generate time to the beginning of the next month

@Override
public InstallmentsPluginResponse updateInstallments(CommercialAutoRequest commercialAutoRequest) {
    Map<String, InstallmentUpdate> installmentUpdates = movePastInstallmentsToNextMonth(commercialAutoRequest);
    return InstallmentsPluginResponse.builder().installmentUpdates(installmentUpdates).build();
}

private Map<String, InstallmentUpdate> movePastInstallmentsToNextMonth(CommercialAutoRequest commercialAutoRequest) {
    InstallmentsPluginContext context = commercialAutoRequest.context();
    Collection<Installment> installments = commercialAutoRequest.installments();
    InstallmentLattice installmentLattice = commercialAutoRequest.installmentLattice();

    log.info(
            "Received InstallmentsPlugin request for context: {}, installments: {} and installmentLattice: {}",
            context,
            installments,
            installmentLattice);

    DataFetcher dataFetcher = DataFetcher.getInstance();
    Policy policy = dataFetcher.getPolicy(context.policyLocator().orElseThrow());

    Instant now = Instant.now();
    ZoneId zoneId = ZoneId.of(policy.timezone());
    ZonedDateTime zonedDateTime = now.atZone(zoneId);
    ZonedDateTime nextMonthDayOne = zonedDateTime.plusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay(zoneId);
    Instant newGenerateTime = nextMonthDayOne.toInstant();

    Map<String, InstallmentUpdate> installmentUpdates = new HashMap<>();

    for (Installment installment : installments) {
        if (installment.generateTime().isBefore(newGenerateTime)) {
            InstallmentUpdate update =
                    InstallmentUpdate.builder()
                            .generateTime(newGenerateTime)
                            .dueTime(newGenerateTime.plusMillis(Duration.between(installment.generateTime(), installment.dueTime()).toMillis()))
                            .build();

            installmentUpdates.put(installment.locator().toString(), update);

            log.info(
                    "Updated installment {} to new generate time {} and due time {}",
                    installment.locator(),
                    newGenerateTime,
                    update.dueTime());
        } else {
            log.info(
                    "Installment {} was not updated because the old generate time {} is after the new generate time {}",
                    installment.locator(),
                    installment.generateTime(),
                    newGenerateTime);
        }
    }

    log.info("Returning installment updates: {}", installmentUpdates);

    return installmentUpdates;
}
```

Next Steps [#next-steps]

* [Autopay Plugin](/configuration/plugins/autopay)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Installment Lattices](/features/billing/installments-and-installment-lattices)
* [Installment Settings](/features/billing/installment-settings)
* [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher)


# Integrations Plugin



The Integrations Plugin allows you to customize email delivery logic used by the [Socotra Assistant](/ai-guide/assistant/overview). When the assistant sends an email, such as an email composed through the [email intake workflow](/ai-guide/assistant/email-intake), the plugin can deliver the email through your own email provider and return the delivery details to the platform.

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `IntegrationsPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `IntegrationsPlugin` interface and override the `sendEmail` method.

For example:

```java
public class IntegrationsPluginImpl implements IntegrationsPlugin {
    private static final Logger log = LoggerFactory.getLogger(IntegrationsPluginImpl.class);

    @Override
    public SendEmailPluginResponse sendEmail(SendEmailRequest request) {
        SendEmailPluginRequest email = request.email();

        log.info("Received send email request for email: {}", email.emailLocator());

        // Send the email using your email provider's API

        return SendEmailPluginResponse.builder()
                .externalId("provider-message-id")
                .from("underwriting@example.com")
                .to(email.to())
                .subject(email.subject())
                .body(email.body())
                .build();
    }
}
```

The method request object contains the email to be sent, which can be retrieved by calling the `email()` method. The email object contains the following fields:

* `emailLocator` - The locator of the email
* `to` - The email address of the recipient
* `subject` - The email subject
* `body` - The email body
* `replyTo` - An optional reply-to email address
* `inReplyTo` - An optional identifier of the original message to which the email is replying. This is used for email threads.
* `attachments` - A list of email attachments. Each attachment contains a `filename`, a `contentType`, and the attachment `content`.

The method returns a `SendEmailPluginResponse` object containing the delivery details. The `SendEmailPluginResponse` object contains the following optional fields:

* `externalId` - The identifier assigned to the email by your email provider
* `from` - The email address of the sender
* `to` - The email address of the recipient
* `subject` - The email subject
* `body` - The email body

HTTP requests can be performed using the [Java HttpClient ](https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/HttpClient.html). Refer to the [Plugins Overview](/configuration/plugins/overview) for more information.

Credentials for your email provider can be retrieved from a secret resource using the [Resource Selector](/configuration/plugins/overview#resource_selector).

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Socotra Assistant Configuration](/configuration/general-topics/assistant)
* [Email Intake Workflow](/ai-guide/assistant/email-intake)


# Plugins Overview



Plugins are software components within the Socotra Insurance Suite that allow you to implement custom business logic written in Java and modify system processes such as underwriting, rating, and payment execution.

Once plugin [implementations](/configuration/plugins/overview#implementation) have been [deployed](/configuration/general-topics/deployment), the system will automatically execute plugin code when entities move to a specific stage of their lifecycles, in response to system events, or when calling certain API endpoints. See the feature guide for each plugin for more information.

The following plugins are available in the Socotra Insurance Suite:

* [Precommit](/configuration/plugins/precommit) - Modify an entity before saving it in the system
* [Validation](/configuration/plugins/validation) - Check if an entity meets a set of requirements
* [Rating](/configuration/plugins/rating) - Calculate charges for quotes and policy transactions
* [Underwriting](/configuration/plugins/underwriting) - Assess risk and determine approval status
* [Document Selection](/configuration/plugins/document-selection) - Determine which [documents](/features/documents/document-management) should be attached to an entity
* [Document Data Snapshot](/configuration/plugins/document-data-snapshot) - Add data and metadata to [documents](/features/documents/document-management)
* [Installments](/configuration/plugins/installments) - Configure [installments](/features/billing/installments-and-installment-lattices)
* [Autopay](/configuration/plugins/autopay) - Configure [automatic payments](/features/billing/autopay)
* [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing) - Configure payment execution post-processing logic
* [Cancellation](/configuration/plugins/cancellation) - Configure retention charges when policies are cancelled
* [Automation](/configuration/plugins/automation) - Implement custom business logic using the Socotra API and third-party APIs
* [Integrations](/configuration/plugins/integrations) - Customize email delivery logic used by the [Socotra Assistant](/ai-guide/assistant/overview)

Implementation [#implementation]

Plugins are implemented as Java classes.

Implementations can be classified as either `Global` or `Product` implementations. `Global` implementations are located in the top-level `configuration-name/plugins/java` folder within the configuration folder structure, and `Product` implementations are located in product folders using the following folder structure: `configuration-name/productName/plugins/java`.

If both a `Global` and a `Product` implementation of a plugin are currently deployed, the system will only execute the `Product` implementation.

<Callout>
  [Automation Plugin](/configuration/plugins/automation) implementations must be `Global`.
</Callout>

Once an implementation has been deployed, `Global` implementations will be moved to the `src/main/java/com/socotra/deployment/customer` folder, and `Product` implementations will be moved to a subfolder using the following folder structure: `src/main/java/com/socotra/deployment/customer/productname`. Implementations can be created and modified directly within these folder structures instead of the configuration folder structures.

To implement a plugin, create a Java class in one of the above folders, implement the interface for the plugin, and override the method specific to your target entity type.

For example, the following class implements the [Validation Plugin](/configuration/plugins/validation) and validates commercial accounts, commercial auto quotes, and commercial policy transactions:

```java
// Validates commercial accounts, commercial auto quotes, and commercial policy transactions

public class ValidationPluginImpl implements ValidationPlugin {
    private static final Logger log = LoggerFactory.getLogger(ValidationPluginImpl.class);

    @Override
    public ValidationItem validate(CommercialAccountRequest commercialAccountRequest) {
        return ValidationItem.builder().build();
    }

    @Override
    public ValidationItem validate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        return ValidationItem.builder().build();
    }

    @Override
    public ValidationItem validate(CommercialAutoRequest commercialAutoRequest) {
        return ValidationItem.builder().build();
    }
}
```

The implementation defined above can only be deployed if two configuration objects are also deployed: An account configuration named `CommercialAccount` and a product configuration named `CommercialAuto`.

Execution [#execution]

Once plugin implementations have been [deployed](/configuration/general-topics/deployment), the system will automatically execute plugin code when entities move to a specific stage of their lifecycles, in response to system events, or when calling certain API endpoints. See the feature guide for each plugin for more information.

Certain plugins are triggered when quotes and policy transactions move to a specific lifecycle state:

| State        | Plugins               |
| ------------ | --------------------- |
| Draft        | N/A                   |
| Validation   | Precommit, Validation |
| Pricing      | Rating                |
| Underwriting | Underwriting          |
| Accept       | N/A                   |
| Issue        | N/A                   |

Plugin Execution Context [#plugin-execution-context]

The `PluginExecutionContext` class provides all plugins with a set of built-in methods for retrieving metadata related to the current plugin execution.

It can be used to access contextual information associated with the current plugin execution, such as the tenant locator or user locator.

The `PluginExecutionContext` class contains the following methods:

* getRequestId()
* getTenantLocator()
* getBusinessAccount()
* getUserLocator()
* getUserRoles()

For example, the following code retrieves the `requestId`:

```java
public class ValidationPluginImpl implements ValidationPlugin {

    @Override
    public ValidationItem validate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        PluginExecutionContext context = PluginExecutionContext.get();
        String requestId = context.getRequestId();

        return ValidationItem.builder().build();
    }
}
```

<span id="PluginDataFetcher" />

Data Fetcher [#data-fetcher]

All plugins have access to the `DataFetcher` class, which can be used to retrieve data from a wide variety of entities, including quotes, policies, and accounts.

For example, the following code retrieves an account using an account locator:

```java
// Retrieve an account using an account locator

@Override
public ValidationItem validate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
    CommercialAccount account = DataFetcherFactory.get().getAccount(commercialAutoQuoteRequest.quote().accountLocator());

    return ValidationItem.builder().build();
}
```

The following is a complete list of all methods available through the `DataFetcher` class:

| Method                              | Parameters                                             | Response                                                                                           |
| ----------------------------------- | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| getAccount()                        | `accountLocator`                                       | <ApiLink name="AccountResponse" />                                                                 |
| getQuickQuote()                     | `quickQuoteLocator`                                    | <ApiLink name="QuickQuoteResponse" />                                                              |
| getQuote()                          | `quoteLocator`                                         | <ApiLink name="QuoteResponse" />                                                                   |
| getQuoteUnderwritingFlags()         | `quoteLocator`                                         | <ApiLink name="QuoteUnderwritingFlagsResponse" />                                                  |
| getQuotePricing()                   | `quoteLocator`                                         | <ApiLink name="QuotePriceResponse" />                                                              |
| getQuoteDocuments()                 | `quoteLocator`                                         | <ApiLink name="DocumentListResponse" />                                                            |
| getQuoteStaticData()                | `locator`                                              | `static`                                                                                           |
| getTransaction()                    | `transactionLocator`                                   | <ApiLink name="PolicyTransactionResponse" />                                                       |
| getTransactionUnderwritingFlags()   | `transactionLocator`                                   | <ApiLink name="TransactionUnderwritingFlagsResponse" />                                            |
| getTransactionPricing()             | `transactionLocator`                                   | <ApiLink name="TransactionPriceResponse" />                                                        |
| getDocumentsAttachedToTransaction() | `transactionLocator`                                   | <ApiLink name="DocumentListResponse" />                                                            |
| getAffectedTransactions()           | `transactionLocator`                                   | <ApiLink name="AffectedTransaction">AffectedTransaction\[]</ApiLink>                               |
| getPolicy()                         | `policyLocator`                                        | <ApiLink name="PolicyResponse" />                                                                  |
| getPolicyStaticData()               | `locator`                                              | `static`                                                                                           |
| getTerm()                           | `termLocator`                                          | <ApiLink name="TermResponse" />                                                                    |
| getTermCharges()                    | `termLocator`                                          | map\<`transactionLocator`, <ApiLink name="PolicyChargeResponse">PolicyChargeResponse\[]</ApiLink>> |
| getTermSubsegmentSummaries()        | `termLocator`                                          | StreamingEntity\<<ApiLink name="SubsegmentSummary" />>, excluding `documentSummary`                |
| getSegment()                        | `segmentLocator`                                       | <ApiLink name="SegmentResponse" />                                                                 |
| getSegments() **Deprecated**        | `transactionLocator`                                   | <ApiLink name="SegmentResponse">SegmentResponse\[]</ApiLink>                                       |
| getSegmentByTransaction()           | `transactionLocator`                                   | <ApiLink name="SegmentResponse" />                                                                 |
| getSegmentDocuments()               | `segmentLocator`                                       | <ApiLink name="DocumentListResponse" />                                                            |
| getAuxData()                        | `locator`, `key`                                       | <ApiLink name="AuxDataResponse" />                                                                 |
| getAuxDataKeys()                    | `locator`, `offset`, `count`                           | <ApiLink name="AuxDataKeySetResponse" />                                                           |
| getUnderwritingFlag()               | `underwritingFlagLocator`                              | <ApiLink name="UnderwritingFlagResponse" />                                                        |
| getDiaries()                        | `referenceType`, `referenceLocator`, `offset`, `count` | <ApiLink name="DiaryEntryResponse">DiaryEntryResponse\[]</ApiLink>                                 |
| getPreferences()                    | `transactionLocator`                                   | <ApiLink name="Preferences" />                                                                     |
| getInstallmentLattice()             | `installmentLatticeLocator`                            | <ApiLink name="InstallmentLatticeResponse" />                                                      |
| getInstallment()                    | `installmentLocator`                                   | <ApiLink name="Installment" />                                                                     |
| getInvoice()                        | `invoiceLocator`                                       | <ApiLink name="InvoiceResponse" />                                                                 |
| getInvoiceDetails()                 | `invoiceLocator`                                       | <ApiLink name="InvoiceDetailsResponse" />                                                          |
| getPayment()                        | `paymentLocator`                                       | <ApiLink name="PaymentResponse" />                                                                 |
| getDelinquencyEvents()              | `delinquencyLocator`, `offset`, `count`                | <ApiLink name="DelinquencyEventsResponse" />                                                       |
| getTask()                           | `taskLocator`                                          | <ApiLink name="Task" />                                                                            |
| getUserAssociation()                | `userAssociationLocator`                               | <ApiLink name="UserAssociation" />                                                                 |
| getFnol()                           | `fnolLocator`                                          | <ApiLink name="FnolResponse" />                                                                    |
| getFnolLosses()                     | `fnolLocator`                                          | <ApiLink name="FnolLoss">FnolLoss\[]</ApiLink>                                                     |
| getFnolClaims()                     | `fnolLocator`                                          | `claims`                                                                                           |
| getContact()                        | `locator`                                              | <ApiLink name="ContactRoles" />                                                                    |
| getQuoteContacts()                  | `quoteLocator`                                         | <ApiLink name="ContactRoles">ContactRoles\[]</ApiLink>                                             |
| getPolicyContacts()                 | `policyLocator`                                        | <ApiLink name="ContactRoles">ContactRoles\[]</ApiLink>                                             |
| getAccountContacts()                | `accountLocator`                                       | <ApiLink name="ContactRoles">ContactRoles\[]</ApiLink>                                             |
| getFnolContacts()                   | `fnolLocator`                                          | <ApiLink name="ContactRoles">ContactRoles\[]</ApiLink>                                             |

<span id="resource_selector" />

Resource Selector [#resource-selector]

All plugins have access to the `ResourceSelector` class, which can be used to retrieve data from [resources](/configuration/resources/versioned-resource-selection) such as tables and secrets.

The `ResourceSelector` automatically selects resource instances based on resource selection rules. See the [Versioned Resource Selection](/configuration/resources/versioned-resource-selection) feature guide for more information, including details on the `LockingResourceSelector`.

Data Tables [#data-tables]

The `ResourceSelector` can be used to retrieve data from [data tables](/configuration/resources/data-tables).

Here's an example of retrieving a record from a data table named `VehicleTypeFactor`:

```java
public class RatingPluginImpl implements RatePlugin {
   private static final Logger log = LoggerFactory.getLogger(RatingPluginImpl.class);

    // Retrieve a record from the VehicleTypeFactor table

    @Override
    public RatingSet rate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        CommercialAutoQuote commercialAutoQuote = commercialAutoQuoteRequest.quote();
        List<RatingItem> ratingItems = new ArrayList<>();

        Vehicle vehicle = commercialAutoQuote.vehicleSchedule().vehicles().stream().findFirst().orElseThrow();

        Optional<VehicleTypeFactor> record = ResourceSelectorFactory.getInstance()
                .getSelector(commercialAutoQuote)
                .getTable(VehicleTypeFactor.class)
                .getRecord(VehicleTypeFactor.makeKey(vehicle.data().vehicleMake(), vehicle.data().vehicleModel(), vehicle.data().vehicleYear()));

        BigDecimal rate = record.orElseThrow().rate();

        ratingItems.add(RatingItem.builder()
                .elementLocator(vehicle.locator())
                .chargeType(ChargeType.premium)
                .rate(rate)
                .build());

        return RatingSet.builder().ok(true).ratingItems(ratingItems).build();
    }
}
```

Here's an example of the `VehicleTypeFactor` data table:

| makeSymbol | modelSymbol | modelYear | typeFactor | collFactor |
| ---------- | ----------- | --------- | ---------- | ---------- |
| key        | key         | key       | value      | value      |
| Toyota     | Camry       | 2023      | 0.84221    | 0.86764    |
| Ford       | Explorer    | 2022      | 0.87839    | 0.91023    |

In the previous code example, a `CommercialAutoQuote` functions as the reference point for resource selection logic. However, you can also specify a time as the reference point instead.

For example:

```java
Optional<VehicleTypeFactor> record = ResourceSelectorFactory.getInstance()
        .getSelector(Instant.now())
        .getTable(VehicleTypeFactor.class)
        .getRecord(VehicleTypeFactor.makeKey(vehicle.data().vehicleMake(), vehicle.data().vehicleModel(), vehicle.data().vehicleYear()));
```

Range Tables [#range-tables]

The `ResourceSelector` can be used to retrieve data from [range tables](/configuration/resources/range-tables).

Here's an example of retrieving a record from a range table named `AdjustedRate`:

```java
Optional<AdjustedRate> record = ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getRangeTable(AdjustedRate.class)
        .getRecord(AdjustedRate.makeKey(), BigDecimal.TEN);
```

Here's an example of range table extrapolation:

```java
ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getRangeTable(VehicleStateFactor.class)
        .extrapolate(TableUtils.makeKey("Toyota", "California"), BigDecimal.valueOf(2016),
                VehicleStateFactor::factor, Interpolation.linear)
        .ifPresent(factor -> log.info("Extrapolated VehicleStateFactor for year {}: {}", 2016, factor));
```

Here's an example of range table interpolation:

```java
ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getRangeTable(VehicleStateFactor.class)
        .interpolate(TableUtils.makeKey("Toyota", "California"), BigDecimal.valueOf(2016),
                VehicleStateFactor::factor, Interpolation.linear)
        .ifPresent(factor -> log.info("Interpolated VehicleStateFactor for year {}: {}", 2016, factor));
```

Here's an example of retrieving the range table record for a key and range selection start that is closest to but not greater than the specified value:

```java
ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getRangeTable(VehicleStateFactor.class)
        .getLowerAdjacentRecord("exampleKey".getBytes(), BigDecimal.valueOf(108))
        .ifPresent(record -> log.info("Lower adjacent record: {}", record));
```

If multiple ranges match, the range with the lowest range selection end is returned.

Here's an example of retrieving the range table record for a key and range selection start that is closest to but not less than the specified value.

```java
ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getRangeTable(VehicleStateFactor.class)
        .getUpperAdjacentRecord("exampleKey".getBytes(), BigDecimal.valueOf(108))
        .ifPresent(record -> log.info("Upper adjacent record: {}", record));
```

If multiple ranges match, the range with the lowest range selection end is returned.

Constraints [#constraints]

The `ResourceSelector` can be used to retrieve [constraints](/configuration/data-extensions/data-extension-constraints).

For example:

```java
ConstraintsFetcher constraintsFetcher = ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getConstraints(ClassCodes.class);

Collection<String> constraints = constraintsFetcher.get("exampleKey".getBytes());
```

Secrets [#secrets]

Lastly, the `ResourceSelector` can be used to retrieve secrets by referencing the `staticName` of the secret.

Here's an example of a <ApiLink name="SecretRef">SecretRef</ApiLink> configuration object named `ExternalService`:

```json
{
	"items": {
		"url": {
			"dataType": "string"
		},
		"apiToken": {
			"dataType": "string"
		},
		"timeOutSeconds": {
			"dataType": "int"
		}
	}
}
```

Execute the `deployConfigToTenant` Gradle task to [deploy](/configuration/general-topics/deployment) your configuration.

Once these configurations have been deployed, create your secret using the <ApiLink name="createSecret">Create a Secret</ApiLink> API endpoint.

For example:

```json
{
	"name": "ExampleSecret",
	"staticName": "ExternalService",
	"secret": {
		"url": "https://example.url.com",
		"apiToken": "Bearer EXAMPLE_TOKEN",
		"timeOutSeconds": 1000
	}
}
```

Secrets must be added to at least one [resource group](/api/resources/resource-service) before they can be accessed through the `AutomationPluginContextData` class by using the <ApiLink name="createResourceGroup">Create a Resource Group</ApiLink> or <ApiLink name="updateResourceGroup">Update a Resource Group</ApiLink> API endpoint.

Here's an example request for the <ApiLink name="createResourceGroup">Create a Resource Group</ApiLink> API endpoint:

```json
{
	"name": "ExampleResourceGroup",
	"selectionStartTime": "2023-12-22T19:09:27+0000",
	"resourceNames": ["ExampleSecret"]
}
```

Here's an example request for the <ApiLink name="updateResourceGroup">Update a Resource Group</ApiLink> API endpoint:

```json
{
	"name": "ExampleResourceGroup",
	"selectionStartTime": "2023-12-22T19:09:27+0000",
	"addResources": ["ExampleSecret"]
}
```

Once the secret has been added to a resource group, execute the `refreshReferenceDatamodel` Gradle task to generate the Java class containing your secrets.

Secret fields can now be accessed through the `ResourceSelector`.

For example:

```java
Optional<ExternalService> secret = ResourceSelectorFactory.getInstance()
        .getSelector(commercialAutoQuote)
        .getSecret(ExternalService.class);

String url = secret.url();
String apiToken = secret.apiToken();
Integer timeOutSeconds = secret.timeOutSeconds();
```

See the [Versioned Resource Selection](/configuration/resources/versioned-resource-selection) feature guide for more information on resource selection logic.

Aux Data [#aux-data]

Aux data refers to general-purpose key-value pairs stored within the Socotra Insurance Suite. All plugins have access to aux data via the [Data Fetcher](/configuration/plugins/overview#data-fetcher).

The following aux data methods are available to all plugins via the Data Fetcher:

* getAuxDataKeys()
* getAuxData()
* setAuxData()
* deleteAuxData()

Here's a demonstration of each aux data method:

```java
@Override
public ValidationItem validate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
    String quoteLocator = commercialAutoQuoteRequest.quote().locator().toString();

    // Parameters: getAuxDataKeys(locator, offsetValue, pageSize)
    AuxDataKeysSet keySet = DataFetcher.getInstance().getAuxDataKeys(quoteLocator, 0, 100);

    if (!keySet.auxDataKeys().isEmpty()) {
        String key = keySet.auxDataKeys().stream().findFirst().get().key();
        String value = DataFetcher.getInstance().getAuxData(quoteLocator, key).value();

        Collection<AuxDataSet> auxDataSets = new ArrayList<>();

        AuxDataSet createRequest = AuxDataSet.builder().key(key).value(value).build();

        auxDataSets.add(createRequest);

        createRequest = AuxDataSet.builder().uiType(UiType.normal).key("keyToDelete").value(value).build();

        auxDataSets.add(createRequest);

        AuxDataSetCreateRequest setCreateRequest = AuxDataSetCreateRequest.builder()
                .auxDataSettingsName("ShortExpire")
                .auxData(auxDataSets).build();

        AuxDataService.getInstance().setAuxData(quoteLocator, setCreateRequest);
        AuxDataService.getInstance().deleteAuxData(quoteLocator, "keyToDelete");
    }

    return ValidationItem.builder().build();
}
```

Events Service [#events-service]

The `EventsService` can be used to manually trigger [custom events](/configuration/general-topics/events#custom-events) within Socotra, allowing you to execute workflows via [webhooks](/configuration/general-topics/webhooks) or an event-driven implementation of the [Automation Plugin](/configuration/plugins/automation#creating-an-event-driven-automation-plugin-implementation).

For example:

```java
// Execute a custom event named ExampleEvent with payload data
EventsService.getInstance().createEvent(CustomEvent.ExampleEvent, Map.of("quote", quote.locator(), "info", "Plugin executed"));

// Execute a custom event named ExampleEvent without payload data
EventsService.getInstance().createEvent(CustomEvent.ExampleEvent);
```

Money Service [#money-service]

The `MoneyService` can be used to perform precise financial calculations based on a specified [currency code](https://www.iban.com/currency-codes).

Here's a demonstration of `MoneyService` functionality:

```java
// Create a MoneyService object for a specific currency such as US dollars
MoneyService moneyService = new MoneyService("USD");

BigDecimal amount = new BigDecimal("123.4567");

// Round the amount to the currency's default number of decimal places
BigDecimal roundedAmount = moneyService.toMoney(amount); // Result: 123.46

// Example of a rate calculation
BigDecimal totalAmount = new BigDecimal("1000.00");
BigDecimal duration = new BigDecimal("12.0");

// Calculate a rate for a target amount over a duration
BigDecimal rate = moneyService.getRateForTargetAmount(totalAmount, duration);
```

External API Calls [#external-api-calls]

All plugins can call external API endpoints via the [Java HttpClient](https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/HttpClient.html).

For example:

```java
try (HttpClient client = HttpClient.newHttpClient()) {
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://example.com/some-data"))
            .GET()
            .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

    log.info("Response: {}", response.toString());

} catch (Exception e) {
    log.error("Exception: {}", e.toString());
}
```

<Callout>
  The Java HttpClient is the only HTTP client currently supported by the platform. The [Automation Plugin](/configuration/plugins/automation) is the only plugin that can call Socotra API endpoints directly.
</Callout>

Logging [#logging]

The [Logging API](/api/configuration-and-development/logging) can be used to view the history of plugin executions and Java logging messages.

First, retrieve a list of plugin executions using the <ApiLink name="fetchLogsList">Fetch a List of Logs</ApiLink> API endpoint. Optional query parameters can be used to narrow down this list.

For example, use the `createdAtMin` query parameter to view plugin executions that occurred after a specified timestamp:

```
createdAtMin=2026-07-25T22:00:00.000Z
```

Next, retrieve Java logging messages for a plugin execution by calling the <ApiLink name="fetchLogs">Fetch Logs for a Request</ApiLink> API endpoint and specifying the target <ApiLink name="PluginLogsMetadata">PluginLogsMetadata</ApiLink> `locator` as the `locator` for the request.

<Callout>
  Plugin logs are only stored for 30 days.
</Callout>

Plugin Restrictions [#plugin-restrictions]

The following restrictions apply to all classes that implement a Socotra plugin interface:

* Classes cannot be declared `abstract` and must be instantiable.
* Classes cannot have a constructor with one or more arguments. A no-argument constructor is allowed and will be generated automatically if not provided.

The system will block the deployment of plugin classes that violate these rules.

Each plugin is executed in an isolated memory space. Accessing plugin fields or calling methods belonging to a different plugin is not supported and should not be attempted.

Next Steps [#next-steps]

* [Precommit Plugin](/configuration/plugins/precommit)

See Also [#see-also]

* [Configuration Deployment](/configuration/general-topics/deployment)
* [Versioned Resource Selection](/configuration/resources/versioned-resource-selection)
* [Java HttpClient](https://docs.oracle.com/en/java/javase/21/docs/api/java.net.http/java/net/http/HttpClient.html)


# Payment Post-Processing Plugin



The Payment Post-Processing Plugin allows you to update payment details after the [Payment Execution Service](/features/billing/payment-execution-service) attempts to process a payment. This plugin can also be used to specify when the Payment Execution Service will make another attempt to process a payment.

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `PaymentPostProcessingPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `PaymentPostProcessingPlugin` interface, and override the method corresponding to your target entity type.

For example, the following implementation moves a payment to the `cancelled` state, updates the payment amount, adds a note, and instructs the Payment Execution Service to make another attempt to process the payment in one minute.

```java
public class PaymentPostProcessingPluginImpl implements PaymentPostProcessingPlugin {
    private static final Logger log = LoggerFactory.getLogger(PaymentPostProcessingPluginImpl.class);

    // Move a payment to the cancelled state, update the payment amount, add a note, and instruct the Payment Execution Service to make another attempt to process the payment in one minute

    @Override
    public PaymentPostProcessingResponse postProcess(PaymentPostProcessingRequest paymentPostProcessingRequest) {
        log.info("Received payment post-processing request for payment: {}", paymentPostProcessingRequest.context().paymentLocator());

        return PaymentPostProcessingResponse.builder()
                .paymentState(PaymentState.cancelled)
                .amount(paymentPostProcessingRequest.context().amount().add(new BigDecimal("0.1")))
                .note("Note from the Payment Post-Processing Plugin")
                .nextRequestTime(Instant.now().plus(1, ChronoUnit.MINUTES))
                .build();
    }
}
```

The request object contains the following data:

* `paymentLocator` - The payment locator
* `paymentRequestState` - The current state of the payment
* `amount` - The payment amount
* `currency` - The payment currency
* `financialInstrumentLocator` - The financial instrument locator
* `externalTransactionId` - The external transaction ID (if it exists)
* `data` - [Extension data](/configuration/data-extensions/overview) associated with the payment

The response object returns the following data:

* `nextRequestTime` - When the Payment Execution Service will make another attempt to process a payment (This will override the `hoursBetweenAttempts` value in the current [retry plan](/features/billing/payment-execution-service#retry-plans))
* `amount` - The updated payment amount
* `paymentState` - The updated payment state
* `note` - A note to add to the payment

The Payment Post-Processing Plugin will not be called under certain circumstances, such as when the payment provider system is unavailable or if credentials are outdated. Plugin execution will fail if the payment moves to the `executing` state or the `reversed` state.

If the Payment Post-Processing Plugin returns a `nextRequestTime`, retry attempts will continue, even if the number of retry attempts has already exceeded the number of retry attempts specified in the current retry plan.

<Callout>
  If the Payment Post-Processing Plugin fails, the payment will move to the `failed` state, even if the payment provider successfully processed the payment. Failure details and the response from the payment provider can be retrieved by calling the <ApiLink name="fetchPayment">Fetch a Payment</ApiLink> API endpoint. If a payment provider fails to process a payment, you should process the payment manually, move the payment to the `posted` state by calling the <ApiLink name="postPayment">Post a Payment</ApiLink> API endpoint, and resolve the cause of the failure to prevent future issues.
</Callout>

Example [#example]

The following example is based on the Prism configuration. Contact your Socotra representative for more information.

```java
// If a payment is in the error state, or an error is included in the payment note, move the payment to the failed state, add a note, and instruct the Payment Execution Service to make another attempt to process the payment in one hour

@Override
public PaymentPostProcessingResponse postProcess(PaymentPostProcessingRequest paymentPostProcessingRequest) {
    log.info("Received payment post-processing request for payment: {}", paymentPostProcessingRequest.context().paymentLocator());

    if (paymentPostProcessingRequest.context().paymentRequestState() == PaymentRequestState.error ||
            paymentPostProcessingRequest.context().data().get("note").equals("Error encountered")) {
        return PaymentPostProcessingResponse.builder()
                .paymentState(PaymentState.failed)
                .note("Payment failed due to an error")
                .nextRequestTime(Instant.now().plus(1, ChronoUnit.HOURS))
                .build();
    } else {
        return PaymentPostProcessingResponse.builder()
                .note("No error detected")
                .build();
    }
}
```

Next Steps [#next-steps]

* [Cancellation Plugin](/configuration/plugins/cancellation)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Payment Execution Service](/features/billing/payment-execution-service)
* [Data Extensions](/configuration/data-extensions/overview)
* [Retry Plans](/features/billing/payment-execution-service#retry-plans)
* [Payments API](/api/billing/payments)


# Precommit Plugin



The Precommit Plugin allows you to modify an entity before committing it and saving it in the system. Validation requests trigger the Precommit Plugin, followed by the [Validation Plugin](/configuration/plugins/validation). Once the entity is successfully validated, all changes will be committed and saved.

The following entity types can be modified by the Precommit Plugin:

| Entity              | Plugin Definition Level |
| ------------------- | ----------------------- |
| Accounts            | Tenant or product       |
| Quotes              | Tenant or product       |
| Policy Transactions | Tenant or product       |
| Payments            | Tenant                  |
| Disbursements       | Tenant                  |
| Delinquencies       | Tenant                  |

Implementation [#implementation]

The Precommit Plugin can be implemented by overriding the method corresponding to the entity type you wish to modify.

The method input object contains two fields:

* The entity
* A `trigger`, which specifies the request type that triggered the method

<Callout>
  The `trigger` value will always be `validate` or `manual` since we currently only support automatic executions triggered by a validation request and manual executions.
</Callout>

The method returns the modified entity.

Automatic Execution [#automatic-execution]

The Precommit Plugin will be executed automatically before entity validation requests if an implementation exists for the target entity type.

Manual Execution [#manual-execution]

The Precommit Plugin can be executed manually for quotes in the `draft` state by calling the <ApiLink name="precommitQuote">Invoke the precommit plugin for a draft quote</ApiLink> API endpoint, and for transactions in the `draft` or `initialized` state by calling the <ApiLink name="precommitTransaction">Invoke the precommit plugin for a draft or initialized transaction</ApiLink> API endpoint.

Examples [#examples]

Account [#account]

```java
// Modify the company name

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public CommercialAccount preCommit(CommercialAccountRequest commercialAccountRequest) {
        log.info("Account locator: {}", commercialAccountRequest.account().locator());
        log.info("Trigger: {}", commercialAccountRequest.trigger());

        CommercialAccount account = commercialAccountRequest.account();

        if (account.data().companyName() == null || account.data().companyName().isBlank()) {
            return account.toBuilder()
                    .data(account.data().toBuilder().companyName("Example Company Name").build())
                    .build();
        } else {
            return account;
        }
    }
}
```

Quote [#quote]

```java
// Modify driver numbers

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public CommercialAutoQuote preCommit(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        log.info("Quote locator: {}", commercialAutoQuoteRequest.quote().locator());
        log.info("Trigger: {}", commercialAutoQuoteRequest.trigger());

        CommercialAutoQuote quote = commercialAutoQuoteRequest.quote();
        CommercialAutoQuote.CommercialAutoQuoteBuilder builder = quote.toBuilder();

        if (quote.driverSchedule() != null) {

            int driver_assignment_number = 1;
            Collection<DriverQuote> modified_driver_schedule_numbers = new ArrayList<>();

            for (DriverQuote driver : quote.driverSchedule().drivers()) {

                driver = driver.toBuilder()
                        .data(driver.data().toBuilder()
                                .driverNumber(Integer.toString(driver_assignment_number)).build())
                        .build();

                modified_driver_schedule_numbers.add(driver);
                driver_assignment_number++;
            }

            DriverScheduleQuote.DriverScheduleQuoteBuilder driverScheduleBuilder = quote.driverSchedule().toBuilder();
            driverScheduleBuilder.drivers(modified_driver_schedule_numbers);
            builder.driverSchedule(driverScheduleBuilder.build());

            return builder.build();

        } else {
            return quote;
        }
    }
}
```

Policy Transaction [#policy-transaction]

```java
// Modify change instructions for a transaction

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public PreCommitTransactionResponse preCommit(CommercialAutoTransactionRequest commercialAutoTransactionRequest) {
        log.info("Transaction locator: {}", commercialAutoTransactionRequest.transaction().locator());
        log.info("Trigger: {}", commercialAutoTransactionRequest.trigger());

        PreCommitTransactionResponse.PreCommitTransactionResponseBuilder builder = PreCommitTransactionResponse.builder();

        if (commercialAutoTransactionRequest.changeInstructions() != null) {
            builder.addChangeInstructions(commercialAutoTransactionRequest.changeInstructions());
        } else {
            ParamsChangeInstruction newParamsChangeInstruction = ParamsChangeInstruction.builder().effectiveTime(Instant.now()).build();
            ChangeInstructionHolder newChangeInstructionHolder = ChangeInstructionHolder.builder().paramsInstruction(newParamsChangeInstruction).build();

            builder.addChangeInstruction(newChangeInstructionHolder);
        }

        return builder.build();
    }
}
```

Payment [#payment]

```java
// Modify a payment note

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public StandardPayment preCommit(StandardPaymentRequest standardPaymentRequest) {
        log.info("Payment locator: {}", standardPaymentRequest.payment().locator());
        log.info("Trigger: {}", standardPaymentRequest.trigger());

        if (standardPaymentRequest.payment().data().note().equals("Change this payment note")) {

            StandardPayment payment = standardPaymentRequest.payment();

            return payment.toBuilder()
                    .data(payment.data().toBuilder().note("New payment note").build())
                    .build();
        } else {
            return standardPaymentRequest.payment();
        }
    }
}
```

Disbursement [#disbursement]

```java
// Modify a disbursement note

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public StandardDisbursement preCommit(StandardDisbursementRequest standardDisbursementRequest) {
        log.info("Disbursement locator: {}", standardDisbursementRequest.disbursement().locator());
        log.info("Trigger: {}", standardDisbursementRequest.trigger());

        if (standardDisbursementRequest.disbursement().data().note().equals("Change this disbursement note")) {

            StandardDisbursement disbursement = standardDisbursementRequest.disbursement();

            return disbursement.toBuilder()
                    .data(disbursement.data().toBuilder().note("New disbursement note").build())
                    .build();
        } else {
            return standardDisbursementRequest.disbursement();
        }
    }
}
```

Delinquency [#delinquency]

<Callout>
  Delinquency requests don't contain a `trigger` field, since the delinquency method is executed when a delinquency moves to the `inGrace` state.
</Callout>

```java
// Modify the grace period end date of a delinquency

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public PreCommitDelinquencyResponse preCommit(DelinquencyRequest delinquencyRequest) {
        log.info("Delinquency locator: {}", delinquencyRequest.delinquency().locator());

        return PreCommitDelinquencyResponse.builder()
                .graceEndAt(Instant.now().plus(30, ChronoUnit.DAYS))
                .settings(delinquencyRequest.delinquency().settings())
                .build();
    }
}
```

Next Steps [#next-steps]

* [Validation Plugin](/configuration/plugins/validation)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Quotes API](/api/quotes/quotes)
* [Policy Transactions API](/api/policy-management/policy-transactions)


# Rating Plugin



The Rating Plugin allows you to calculate charges for [quotes](/features/policy-quotation/quotes) and [policy transactions](/features/policy-management/policy-transactions). Pricing requests trigger the Rating Plugin. Once the plugin has been successfully executed and the pricing request has been processed, the quote or policy transaction will move to the `priced` state.

[Charges](/features/financials/charges) can be associated with any element within a quote or policy transaction. Only one charge per charge type can be associated with each element. Charge types must be defined in the <ApiLink name="ChargeRef" /> configuration object.

Supported Entity Types [#supported-entity-types]

The Rating Plugin supports the following entity types:

* Quotes
* Policy Transactions

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `RatingPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `RatePlugin` interface, and override the method corresponding to the entity type you wish to rate.

For example, the following class rates commercial auto quotes:

```java
public class RatingPluginImpl implements RatePlugin {
    private static final Logger log = LoggerFactory.getLogger(RatingPluginImpl.class);

    // Rate commercial auto quotes

    @Override
    public RatingSet rate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        CommercialAutoQuote commercialAutoQuote = commercialAutoQuoteRequest.quote();
        List<RatingItem> ratingItems = new ArrayList<>();

        ratingItems.add(RatingItem.builder()
                .elementLocator(commercialAutoQuote.locator())
                .chargeType(ChargeType.adminFee)
                .rate(BigDecimal.valueOf(50.0))
                .build());

        return RatingSet.builder().ok(true).ratingItems(ratingItems).build();
    }
}
```

The method argument contains the entity to be rated.

<span id="rating-set" />

The method returns a `RatingSet` object, which contains a list of `RatingItem` objects. Each `RatingItem` object contains the following fields:

* `elementLocator` - The locator of the element to be rated
* `chargeType` - The charge type
* `rate` - The rate

Examples [#examples]

All examples are based on the Prism configuration. Contact your Socotra representative for more information.

Quote [#quote]

```java
// Calculate a premium for a commercial auto quote

@Override
public RatingSet rate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
    CommercialAutoQuote commercialAutoQuote = commercialAutoQuoteRequest.quote();
    VehicleQuote vehicleQuote = commercialAutoQuote.vehicleSchedule().vehicles().stream().findFirst().orElseThrow();

    double rate = 0.003 * vehicleQuote.data().currentValue().doubleValue() + 50;

    List<RatingItem> ratingItems = new ArrayList<>();

    ratingItems.add(RatingItem.builder()
            .elementLocator(vehicleQuote.locator())
            .chargeType(ChargeType.premium)
            .rate(BigDecimal.valueOf(rate))
            .build());

    return RatingSet.builder().ok(true).ratingItems(ratingItems).build();
}
```

Policy Transaction [#policy-transaction]

```java
// Calculate a cargo charge for a commercial auto policy transaction

@Override
public RatingSet rate(CommercialAutoRequest commercialAutoRequest) {
    List<RatingItem> ratingItems = new ArrayList<>();

    if (commercialAutoRequest.segment().isPresent()) {
        CommercialAutoSegment localSegment = commercialAutoRequest.segment().get();

        if (localSegment.data().blanketCoverage()) {
            BigDecimal rate = BigDecimal.valueOf(150.0);
            int vehicleCount = localSegment.vehicleSchedule().vehicles().size();

            rate = rate.multiply(BigDecimal.valueOf(vehicleCount));

            RateModificationFactors rmfValues = localSegment.data().rateModificationFactors();

            BigDecimal rmfFactor = BigDecimal.valueOf(rmfValues.serviceRmf().doubleValue()).multiply(BigDecimal.valueOf(rmfValues.maintenanceRmf().doubleValue()))
                    .multiply(BigDecimal.valueOf(rmfValues.seasonalityRmf().doubleValue())).multiply(BigDecimal.valueOf(rmfValues.territoryRmf().doubleValue()))
                    .multiply(BigDecimal.valueOf(rmfValues.fleetMgtRmf().doubleValue())).multiply(BigDecimal.valueOf(rmfValues.lossControlRmf().doubleValue()));

            int driverCount = localSegment.driverSchedule().drivers().size();
            BigDecimal driverFactor = BigDecimal.valueOf(1).add(BigDecimal.valueOf(driverCount).multiply(BigDecimal.valueOf(0.1)));

            rate = rate.multiply(rmfFactor).multiply(driverFactor);

            ratingItems.add(RatingItem.builder()
                    .elementLocator(localSegment.locator())
                    .chargeType(ChargeType.cargo)
                    .rate(rate)
                    .build());
        }
    }

    return RatingSet.builder().ok(true).ratingItems(ratingItems).build();
}
```

Next Steps [#next-steps]

* [Underwriting Plugin](/configuration/plugins/underwriting)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Charges](/features/financials/charges)


# Underwriting Plugin



The Underwriting Plugin allows you to automatically add or remove [underwriting](/features/underwriting) flags to or from quotes or policy transactions.

The following API endpoints trigger the Underwriting Plugin:

* <ApiLink name="underwriteQuote">
    Underwrite a Quote
  </ApiLink>
* <ApiLink name="acceptQuote">
    Accept a Quote
  </ApiLink>
* <ApiLink name="issueQuote">
    Issue a Quote
  </ApiLink>
* <ApiLink name="underwriteTransaction">
    Underwrite a Policy Transaction
  </ApiLink>
* <ApiLink name="acceptTransaction">
    Accept a Policy Transaction
  </ApiLink>
* <ApiLink name="issueTransaction">
    Issue a Policy Transaction
  </ApiLink>

If the Underwriting Plugin is triggered, but the plugin has not been implemented, the system will automatically allow quotes and policy transactions to proceed to the `accepted` stage of the [policy lifecycle](/features/policy-management/policy-transactions#Process).

Underwriting Flags [#underwriting-flags]

The Underwriting Plugin can add or remove the following underwriting flags to or from quotes or policy transactions:

* `approve` - The system will approve the quote or policy transaction and allow it to proceed to the next stage of the [policy lifecycle](/features/policy-management/policy-transactions#Process), regardless of any other flags that have been added to it during the current execution of the Underwriting Plugin. Quotes and policy transactions cannot be approved if they have already been rejected as a result of a previous execution of the Underwriting Plugin.
* `block` - The system will block the quote or policy transaction from proceeding to the next stage of the policy lifecycle.
* `decline` - The system will block the quote or policy transaction from proceeding to the next stage of the policy lifecycle.
* `reject` - The system will **permanently** block the quote or policy transaction from proceeding to the next stage of the policy lifecycle.
* `info` - This flag can be used to provide underwriting information, but has no effect.

The `block` and `decline` flags both prevent quotes and policy transactions from proceeding to the next stage of the policy lifecycle until the flags have been removed or an `approve` flag is added. The `block` and `decline` flags function the same way, providing underwriters more flexibility to signal different types of denials.

If no flags have been added to a quote or policy transaction, the system will allow it to proceed to the `accepted` stage of the policy lifecycle.

<Callout type="warn">
  The `reject` flag permanently blocks a quote or policy transaction from proceeding to the next stage of the policy lifecycle. If this is not acceptable, we recommend using the `decline` or `block` flags as alternatives.
</Callout>

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `UnderwritingPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `UnderwritingPlugin` interface, and override the method corresponding to your target entity type.

For example, the following class contains a method that approves commercial auto quotes:

```java
public class UnderwritingPluginImpl implements UnderwritingPlugin {
    private static final Logger log = LoggerFactory.getLogger(UnderwritingPluginImpl.class);

    // Approves commercial auto quotes

    @Override
    public UnderwritingModification underwrite(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        return UnderwritingModification.builder()
                .flagsToCreate(List.of(UnderwritingFlagCore.builder()
                        .level(UnderwritingLevel.approve)
                        .elementLocator(Optional.of(commercialAutoQuoteRequest.quote().locator()))
                        .tag(Optional.of("EXAMPLE_UNIQUE_IDENTIFIER"))
                        .note(Optional.of("This is an underwriting note."))
                        .build()))
                .build();
    }
}
```

The method argument contains the quote or policy to be underwritten. In the example above, the argument contains a commercial auto quote. Change the method argument class to `CommercialAutoRequest` to underwrite commercial auto policy transactions instead.

The method returns an `UnderwritingModification` object, which contains a list of `UnderwritingFlagCore` objects that will be added to the quote or policy transaction. Each `UnderwritingFlagCore` object contains the following fields:

* `level` - The flag level
* `elementLocator` - An optional element locator associated with the flag
* `tag` - An optional unique identifier associated with the flag
* `note` - An optional note associated with the flag

Checking for Existing Flags [#checking-for-existing-flags]

Implementations must check for existing flags before adding new flags to avoid unintentionally adding previously cleared flags. The example below demonstrates the recommended approach to checking flags.

Example [#example]

The following example is based on the Prism configuration. Contact your Socotra representative for more information.

```java
// Blocks commercial auto quotes and policy transactions based on driver experience and vehicle value

public class UnderwritingPluginImpl implements UnderwritingPlugin {
    private static final Logger log = LoggerFactory.getLogger(UnderwritingPluginImpl.class);

    @Override
    public UnderwritingModification underwrite(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        return underwriteCommercialAuto(commercialAutoQuoteRequest.quote());
    }

    @Override
    public UnderwritingModification underwrite(CommercialAutoRequest commercialAutoRequest) {
        if (commercialAutoRequest.segment().isPresent()) {
            return underwriteCommercialAuto(commercialAutoRequest.segment().get());
        }

        return UnderwritingModification.builder().build();
    }

    private UnderwritingModification underwriteCommercialAuto(CommercialAuto commercialAuto) {
        // Check existing flags to avoid adding previously cleared flags

        DataFetcher dataFetcher = DataFetcher.getInstance();
        UnderwritingFlags flags = dataFetcher.getQuoteUnderwritingFlags(commercialAuto.locator());

        Set<String> existingRuleIds = new HashSet<>();

        existingRuleIds.addAll(flags.flags().stream()
                .map(flag -> flag.tag().orElse(""))
                .filter(tag -> !tag.isEmpty())
                .collect(Collectors.toSet()));

        existingRuleIds.addAll(flags.clearedFlags().stream()
                .map(flag -> flag.tag().orElse(""))
                .filter(tag -> !tag.isEmpty())
                .collect(Collectors.toSet()));

        List<UnderwritingFlagCore> newFlags = new ArrayList<>();

        // Evaluate driver experience

        for (Driver driver : commercialAuto.driverSchedule().drivers()) {
            if (driver.data().yearsOfExperience() < 5
                    && !existingRuleIds.contains("INEXPERIENCED_DRIVER" + driver.locator())) {
                newFlags.add(
                        createFlag(
                                UnderwritingLevel.block,
                                driver.locator(),
                                "INEXPERIENCED_DRIVER_" + driver.charges(),
                                "Driver has less than 5 years of experience."
                        )
                );
            }
        }

        // Evaluate vehicle value

        for (Vehicle vehicle : commercialAuto.vehicleSchedule().vehicles()) {
            if (vehicle.data().currentValue() != null
                    && vehicle.data().currentValue().compareTo(new BigDecimal("100000")) > 0
                    && !existingRuleIds.contains("HIGH_VALUE_VEHICLE")) {
                newFlags.add(
                        createFlag(
                                UnderwritingLevel.block,
                                vehicle.locator(),
                                "HIGH_VALUE_VEHICLE_" + vehicle.locator().toString(),
                                "Vehicle value exceeds underwriting guidelines."
                        )
                );
            }
        }

        // Add flags

        return UnderwritingModification.builder()
                .flagsToCreate(newFlags)
                .build();
    }

    private UnderwritingFlagCore createFlag(UnderwritingLevel level, ULID locator, String tag, String note) {
        return UnderwritingFlagCore.builder()
                .level(level)
                .elementLocator(Optional.of(locator))
                .tag(Optional.of(tag))
                .note(Optional.of(note))
                .build();
    }
}
```

Best Practices [#best-practices]

1. **Always Check Existing Flags First**
   * Use `DataFetcher.getInstance().getQuoteUnderwritingFlags()`

   * Check existing `tag` values to avoid unintentionally adding previously cleared flags

   * Make informed decisions about flag creation and updates

2. **Handle All Request Types**
   * Implement both quote and policy transaction methods

   * Check for segment presence in policy transaction requests

3. **Use Unique Rule Identifiers**
   * Set meaningful `tag` values for each flag type

   * Include element-specific identifiers when needed

4. **Provide Clear Flag Messages**
   * Write actionable notes that help underwriters understand the issue

   * Include relevant context and next steps

5. **Test Thoroughly**
   * Verify flag creation and duplicate prevention

   * Test both quote and policy transaction scenarios

   * Validate flag levels and their impact on policy progression

Next Steps [#next-steps]

* [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Underwriting](/features/underwriting)
* [Policy Lifecycle](/features/policy-management/policy-transactions#Process)
* [Quotes API](/api/quotes/quotes)
* [Policy Transactions API](/api/policy-management/policy-transactions)
* [Plugin Data Fetcher](/configuration/plugins/overview#PluginDataFetcher)


# Validation Plugin



The Validation Plugin allows you to execute custom validation logic on an entity. Validation requests trigger the [Precommit Plugin](/configuration/plugins/precommit), followed by the Validation Plugin.

When a validation request is processed, the system executes two validation steps in the following order:

1. Check if the entity adheres to the entity schema defined in the [configuration](/configuration/general-topics/deployment)
2. Check if the entity adheres to the custom validation logic defined in the Validation Plugin, if an implementation exists for the relevant entity type

If both of these steps determine that the entity is valid, the entity will move to the `validated` state. Once an entity moves to the `validated` state, it becomes immutable. If either of these steps determines that the entity is invalid, the entity will remain in its original state. The system will only execute the second step if the first step determines that the entity is valid.

Supported Entity Types [#supported-entity-types]

The Validation Plugin supports the following entity types:

* Accounts
* Quotes
* Policy Transactions
* Payments
* Disbursements

Implementation [#implementation]

Create a new Java class in the `src/main/java/com/socotra/deployment/customer` folder. All plugin code must be contained within this folder. We named our class `ValidationPluginImpl.java` in the example below, but you can name your class whatever you'd like.

Implement the `ValidationPlugin` interface, and override the method corresponding to the entity type you wish to validate.

For example, the following class contains a method that validates commercial accounts:

```java
public class ValidationPluginImpl implements ValidationPlugin {
    private static final Logger log = LoggerFactory.getLogger(ValidationPluginImpl.class);

    // Validate commercial accounts

    @Override
    public ValidationItem validate(CommercialAccountRequest commercialAccountRequest) {
        return ValidationItem.builder().build();
    }
}
```

The method argument contains the entity to be validated.

The method returns a `ValidationItem` object, which contains the following fields:

* `locator` - The entity locator
* `elementType` - The element type that caused the validation failure
* `addError` - An error message
* `addErrors` - Multiple error messages
* `errors` - Multiple error messages

A return object that does not contain any error messages, as shown in the example above, indicates that the entity is valid. A return object containing one or more error messages indicates that the entity is invalid.

Examples [#examples]

All examples are based on the Prism configuration. Contact your Socotra representative for more information.

Account [#account]

```java
// Check if the company name is blank

@Override
public ValidationItem validate(CommercialAccountRequest commercialAccountRequest) {
    log.info("Account locator: {}", commercialAccountRequest.account().locator());

    CommercialAccount commercialAccount = commercialAccountRequest.account();
    String companyName = commercialAccount.data().companyName();

    if (companyName == null || companyName.isEmpty()) {
        return ValidationItem.builder()
                .locator(commercialAccount.locator())
                .addError("Company name cannot be blank")
                .build();
    } else {
        return ValidationItem.builder().build();
    }
}
```

Quote [#quote]

```java
// Check for duplicate VINs

@Override
public ValidationItem validate(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {

    List<VehicleQuote> vehicleSchedule = commercialAutoQuoteRequest.quote().vehicleSchedule().vehicles().stream().toList();

    Map<String, List<String>> vinToVehicleNumbers = new HashMap<>();
    List<String> duplicateVins = new ArrayList<>();

    // Check for duplicate VINs
    for (VehicleQuote vehicle : vehicleSchedule) {
        String vin = vehicle.data().vin();
        String vehicleNumber = vehicle.data().vehicleNumber();

        log.info("Vehicle {} VIN: {}", vehicleNumber, vin);

        if (vin != null && !vin.isBlank()) {
            vinToVehicleNumbers.computeIfAbsent(vin, v -> new ArrayList<>()).add(vehicleNumber);

            // Track duplicate VINs
            if (vinToVehicleNumbers.get(vin).size() == 2) {
                duplicateVins.add(vin);
            }
        }
    }

    if (!duplicateVins.isEmpty()) {
        List<String> errorMessages = new ArrayList<>();

        for (String vin : duplicateVins) {
            List<String> vehicleNumbers = vinToVehicleNumbers.get(vin);

            log.warn("Duplicate VIN {} found: {}", vin, vehicleNumbers);

            errorMessages.add(String.format(
                    "VIN %s is duplicated for vehicles %s",
                    vin,
                    String.join(" & ", vehicleNumbers)
            ));
        }

        return ValidationItem.builder()
                .locator(commercialAutoQuoteRequest.quote().vehicleSchedule().locator())
                .elementType(commercialAutoQuoteRequest.quote().vehicleSchedule().type())
                .addErrors(errorMessages)
                .build();
    } else {
        return ValidationPlugin.super.validate(commercialAutoQuoteRequest);
    }
}
```

Policy Transaction [#policy-transaction]

```java
// Check if a policy transaction contains a blanket coverage selection

@Override
public ValidationItem validate(CommercialAutoRequest commercialAutoRequest) {
    List<String> errorMessages = new ArrayList<>();

    if (commercialAutoRequest.segment().isPresent()) {
        CommercialAuto.CommercialAutoData commercialAutoData = commercialAutoRequest.segment().get().data();

        if (!commercialAutoData.blanketCoverage() || commercialAutoData.blanketCoverageSelections() == null) {
            errorMessages.add("Commercial auto policy transaction must contain a blanket coverage selection");
        }
    }

    if (!errorMessages.isEmpty()) {
        return ValidationItem.builder()
                .locator(commercialAutoRequest.policy().locator())
                .elementType(commercialAutoRequest.segment().get().data().blanketCoverageSelections().type())
                .errors(errorMessages)
                .build();
    } else {
        return ValidationItem.builder().build();
    }
}
```

Payment [#payment]

```java
// Check if a payment note is blank

@Override
public ValidationItem validate(StandardPaymentRequest standardPaymentRequest) {
    log.info("Payment locator: {}", standardPaymentRequest.payment().locator());

    String note = standardPaymentRequest.payment().data().note();

    if (note == null || note.isEmpty()) {
        return ValidationItem.builder()
                .locator(standardPaymentRequest.payment().locator())
                .addError("Payment note cannot be blank")
                .build();
    } else {
        return ValidationItem.builder().build();
    }
}
```

Disbursement [#disbursement]

```java
// Check if a disbursement note is blank

@Override
public ValidationItem validate(StandardDisbursementRequest standardDisbursementRequest) {
    log.info("Disbursement locator: {}", standardDisbursementRequest.disbursement().locator());

    String note = standardDisbursementRequest.disbursement().data().note();

    if (note == null || note.isEmpty()) {
        return ValidationItem.builder()
                .locator(standardDisbursementRequest.disbursement().locator())
                .addError("Disbursement note cannot be blank")
                .build();
    } else {
        return ValidationItem.builder().build();
    }
}
```

Next Steps [#next-steps]

* [Rating Plugin](/configuration/plugins/rating)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Precommit Plugin](/configuration/plugins/precommit)


# Data Tables



Overview [#overview]

Data Tables are a mechanism for you to store and organize large volumes of data for reference from plugins. These can be referenced from any plugin and can be versioned based on effective dates using the [Versioned Resource Selection](/configuration/resources/versioned-resource-selection) feature.

Configuration [#configuration]

The structure of each table is established in configuration by declaring the name of the table along with the number and type of each column. A typical declaration looks like this:

```json
{
	// At the top level of the configuration
	"tables": {
		"PersonalAutoRates": {
			"selectionTimeBasis": "termStartTime",
			"columns": {
				"state": {
					"dataType": "string",
					"isKey": true
				},
				"baseRate": {
					"dataType": "decimal",
					"isKey": false
				},
				"taxRate": {
					"dataType": "decimal",
					"isKey": false
				},
				"rateCode": {
					"dataType": "string ",
					"isKey": false
				}
			}
		}
	}
}
```

This declaration declares a table with the static name `PersonalAutoRates`, with three columns: a key column called `state` and three value columns called `baseRate`, `taxRate`, and `rateCode`.

Limitations [#limitations]

Tables support up to one million rows each.


# Documents



import Image from 'next/image';

Overview [#overview]

The Document production and management system in Socotra provides controls to author and render documents that can be attached to quotes, policies, or invoices.

<span id="document_scope" />

Document Scope [#document-scope]

Each document has a `scope` setting for how it should be interpreted based on the transaction history. Like other policy data, each instance of a document may be considered to be "in-force" based on whether the transaction that has created it has been issued, or whether it has been superseded by another transaction. The scope options provide additional controls for this determination. The choices for scope are:

* `transaction`: The document is local to the transaction and is never considered to be "on the policy."
* `policy`: The document is considered on the policy when the transaction that creates it is issued, and will remain on the policy until a subsequent transaction removes it.
* `term`: The same as `policy`, except all previously-existing documents with this scope are automatically removed on renewals.
* `segment`: The document is local to a segment, and does not carry over to following segments.
* `invoice`: The document is specifically used for invoice documents.

<span id="policy_document_workflow" />

Policy Document Workflow [#policy-document-workflow]

Tenants can be configured to instruct the system to create documents when a quote or policy transaction reaches specific lifecycle states. These lifecycle states are called **triggers**.

Each document type can have one trigger, and each product can specify a different set of documents to be created. Document contents are generated based on quote or policy transaction data.

<Image src="/images/document-flow.png" alt="document flow" width={600} height={316} unoptimized />

The following normal lifecycle states can be configured as document triggers:

* `validated`
* `priced`
* `underwritten`
* `accepted`
* `issued`

The following inactive lifecycle states can be configured as document triggers:

* `declined`
* `rejected`
* `refused`

Invoice generation can also be configured as a document trigger.

Consolidated documents must abide by the following rules for triggers:

* Consolidated documents cannot be composed of a mix of documents with normal lifecycle triggers and documents with inactive lifecycle triggers.
* Consolidated documents composed of documents with inactive lifecycle triggers can only contain documents with the same inactive lifecycle trigger.

The *Document Selection Plugin* determines which of the documents available (based on configuration) should be produced. The *Data Snapshot Plugin* assembles all the data needed to render it and the metadata that should be maintained alongside it. The Socotra renderer then produces the actual .pdf, .html, or .txt file based on the template referenced in the document definition. If the selection plugin indicates that multiple documents are to be created, each one is handled in parallel with separate calls to the data snapshot plugin.

<Callout>
  Static documents do not have a rendering step, so there is no rendering data captured. The data snapshot plugin still is used to assemble any desired metadata.
</Callout>

Each transaction has properties related to documents:

* `transactionDocuments`: This is an array of locators of documents generated by the transaction that have `scope` equal to `transaction`.
* `newPolicyDocuments`: An array of locators of new documents generated by this transaction that have scope other than `transaction`.
* `carryForwardPolicyDocuments`: The locators of documents carried forward because they are on the transaction's `basedOn` transaction and haven't been removed based on scope logic.

For any document, the `carryForwardPolicyDocuments` property will be the transaction's `basedOn` transaction's `newPolicyDocuments` combined with its `carryForwardPolicyDocuments` that remain on the policy.

Quotation [#quotation]

Quotes work similarly to policy transactions, except that there is no transaction history and therefore no existing documents to consider. All `transaction`-scoped documents will remain attached to the quote and will not transfer to the policy on issuance. All other documents will be copied to the policy issuance transaction and attached to the policy. The [document.copyOnIssue.ready](/configuration/general-topics/event-definitions#document-events) [event](/configuration/general-topics/events) will be emitted when this process is complete. If any document fails to render for the quote, no documents will be copied to the policy.

Because there is no history for a quote, quotes will not have a `carryForwardPolicyDocuments` property, though they *will* have `transactionDocuments` and `newPolicyDocuments`.

<span id="static_and_dynamic_documents_configuration" />

Static and Dynamic Documents [#static-and-dynamic-documents]

Static documents are <ApiLink name="DocumentConfigRef">configured</ApiLink> with the `rendering` value `prerendered`. As the name implies, static documents do not have variable content. Dynamic documents, on the other hand, are indicated with `rendering` value `dynamic`, passing through an extra rendering step that takes the document as a template and fills out the final form according to logic specified in the template.

Dynamic document templates may use either the [Liquid ](https://shopify.github.io/liquid/) or [Velocity ](https://velocity.apache.org/engine/2.3/) templating languages. Socotra currently supports Liquid 5.5.0 and Velocity 2.3.

See the [Dynamic Documents Guide](/features/documents/dynamic-documents) for further details, including examples and guidance on inspecting rendering data and troubleshooting.

Document Consolidation [#document-consolidation]

You can configure the automatic consolidation of multiple documents into a single artifact with additional features such as a cover page, table of contents, and page numbering.

See the [Document Consolidation Guide](/features/documents/document-consolidation) for further details, including examples and guidance on capabilities and limitations.

Document Jobs [#document-jobs]

The status and details of a document rendering job can be retrieved via the [Jobs API](/api/configuration-and-development/jobs).

A list of document jobs can be fetched for a specific <ApiLink name="fetchMultipleDocumentsJobsForQuote">quote</ApiLink>, <ApiLink name="fetchMultipleDocumentsJobsForSegment">segment</ApiLink>, or <ApiLink name="fetchMultipleDocumentsJobsForTransaction">transaction</ApiLink>.

Individual job details can be retrieved using the provided `jobLocator`, and any document jobs that have timed out can be retriggered.

Plugins [#plugins]

Policy Document Selection Plugin [#policy-document-selection-plugin]

The *Document Selection Plugin* decides which documents will be attached to a quote or policy transaction, with eligibility determined by the product's configuration. For each potential document, the plugin will select one of:

* `generate`: Always creates a new document, which will replace that document (if any) in the document's scope.
* `noChange`: Leaves the existing document in place, if any.
* `generateIfAbsent`: Like `noChange` if the document already exists in the scope, or like `generate` if it does not yet exist.
* `remove`: Removes the document if it already exists.

When we say "the document" we mean any instance of the specific document declared in configuration, for the scope for that document. In other words, the basis for the equivalence check is the `staticName` of the document. The instance could change with [versioned resource selection](/configuration/resources/versioned-resource-selection). For example, if we have a document declared with static name `newJerseyDisclosures` with `term` scope, and that document has V1, V2, and V3 variations, the above choices would be based on comparing documents in the term by "newJerseyDisclosures" and NOT "newJerseyDisclosuresV1".

For documents configured with `scope` equal to `transaction` or `segment`, `generateIfAbsent` will always behave the same as `generate`, and `remove` will have no effect. This is because these documents are local to the transaction itself.

For the purposes of document scope handling, the definition of *"the document exists"* is that a document with that static name is contained within the *"previous segment"* and has `policy` scope, or has `term` scope and the new segment does not start at beginning of a term, so it will carry forward unless explicitly removed or re-generated. The *"previous segment"* is the pre-split segment for the transaction if there is one, or the first segment lower in the transaction stack that has `endTime` equal to the new segment's `startTime`.

Document Data Snapshot Plugin [#document-data-snapshot-plugin]

The *Document Data Snapshot Plugin* will assemble the metadata, and if dynamic, the rendering data for the document.

After the results of this plugin call are persisted, the document will have `dataReady` state if it is a dynamic document, or `ready` state if it is static. This plugin is executed asynchronously with any client request.

For dynamic documents, when they are rendered to PDF form, the state will change from `dataReady` to `ready`.

<Callout>
  The `dataReady` state is transient; generally documents will be first seen in `ready` state.
</Callout>

Document Consolidation Snapshot Plugin [#document-consolidation-snapshot-plugin]

The Document Consolidation Plugin allows for the assembly of rendering data and metadata, just like the Document Data Snapshot Plugin.

See Also [#see-also]

* [Documents API](/api/documents)
* [Document Resources API](/api/resources/document-resources)


# Range Tables



Range Tables provide advanced table lookup capabilities. Unlike conventional lookup tables, which are performance-optimized for single-key, exact-match lookups, Range Tables support both range-based and interpolated table lookups. Range Tables are configured and managed similarly to other table resources. They can be referenced from any plugin and can be versioned based on effective dates using the [Versioned Resource Selection](/configuration/resources/versioned-resource-selection) feature.

Use Cases [#use-cases]

Currently, Range Tables support two use cases:

1. Range-Based Lookups - A numeric input value is used to identify the appropriate row in the table by finding the row where the input value falls within the range defined by the `rangeStart` and `rangeEnd` columns. For example, a credit score factor table may define ranges of credit scores and associated factors to be applied to a premium calculation.
2. Interpolated Lookups - A numeric input value is used to identify two rows in the table, and the output value is calculated by interpolating between the output values of the two rows. For example, a vehicle value depreciation table may define vehicle values based on year, and for an input vehicle year that falls between two defined years, the output value is calculated by interpolating between the two defined values.

Configuration [#configuration]

The structure of each table is established in the configuration using the <ApiLink name="RangeTableRef">RangeTableRef</ApiLink> under the `rangeTables` property of the <ApiLink name="ConfigurationRef">ConfigurationRef</ApiLink>, by declaring the name of the table along with the number and type of each column. The `rangeStart` and `rangeEnd` properties are unique to Range Table configurations, which identify the columns that define the beginning and end of the lookup range.

A typical configuration looks like this:

```json
{
	// At the top level of the configuration
	"rangeTables": {
		"CreditScoreFactor": {
			"columns": {
				"minScore": {
					"dataType": "decimal",
					"isKey": false
				},
				"maxScore": {
					"dataType": "decimal",
					"isKey": false
				},
				"factor": {
					"dataType": "decimal",
					"isKey": false
				}
			},
			"selectionTimeBasis": "termStartTime",
			"rangeStart": "minScore",
			"rangeEnd": "maxScore"
		},
		"VehicleStateFactor": {
			"columns": {
				"make": {
					"dataType": "string",
					"isKey": true
				},
				"stateName": {
					"dataType": "string",
					"isKey": true
				},
				"year": {
					"dataType": "decimal",
					"isKey": false
				},
				"factor": {
					"dataType": "int",
					"isKey": false
				}
			},
			"selectionTimeBasis": "termStartTime",
			"rangeStart": "year",
			"rangeEnd": "year"
		}
	}
}
```

This configuration defines two tables.

The first table, `CreditScoreFactor`, has three columns: `minScore`, `maxScore`, and `factor`. The `minScore` and `maxScore` columns define the range for lookups, while the `factor` column provides the output value.

The second table, `VehicleStateFactor`, has four columns: `make`, `stateName`, `year`, and `factor`. The `make` and `stateName` columns are defined as key columns, while the `year` column is used for range lookups, and the `factor` column provides the output value.

<Callout>
  The system requires that the columns defined as `rangeStart` and `rangeEnd` be of numeric data types (`int`, `long`, `decimal`, etc.) to support range and interpolation calculations.
</Callout>

Examples [#examples]

1. Range-Based Lookup Example

   Given the `CreditScoreFactor` table defined above, consider the following records:

```json
[
	{ "minScore": 300, "maxScore": 579, "factor": 1.5 },
	{ "minScore": 580, "maxScore": 669, "factor": 1.2 },
	{ "minScore": 670, "maxScore": 739, "factor": 1.0 },
	{ "minScore": 740, "maxScore": 799, "factor": 0.9 },
	{ "minScore": 800, "maxScore": 850, "factor": 0.8 }
]
```

For an input credit score of `582`, the lookup would identify the record where `minScore` is `580` and `maxScore` is `669`, returning a factor of `1.2`.

For example:

```java
// Get the selector
ResourceSelector selector = ResourceSelectorFactory.getInstance().getSelector(request.quote());
RangeTableRecordFetcher<CreditScoreFactor> scoreFetcher = resourceSelector.getRangeTable(CreditScoreFactor.class);

BigDecimal lowerMidScore = BigDecimal.valueOf(582);

scoreFetcher.extrapolate(TableUtils.makeKey(), lowerMidScore, CreditScoreFactor::factor, Interpolation.stepUp).ifPresent(r -> log.info("1. Interpolated factor for lowerMidScore stepUp {}: {}", lowerMidScore, r));
scoreFetcher.extrapolate(TableUtils.makeKey(), lowerMidScore, CreditScoreFactor::factor, Interpolation.stepDown).ifPresent(r -> log.info("2. Interpolated factor for lowerMidScore stepDown {}: {}", lowerMidScore, r));
scoreFetcher.extrapolate(TableUtils.makeKey(), lowerMidScore, CreditScoreFactor::factor, Interpolation.linear).ifPresent(r -> log.info("3. Interpolated factor for lowerMidScore linear {}: {}", lowerMidScore, r));
```

Output:

```text
1. Interpolated factor for lowerMidScore stepUp 582: 1.0
2. Interpolated factor for lowerMidScore stepDown 582: 1.2
3. Interpolated factor for lowerMidScore linear 582: 1.2
```

2. Interpolated Lookup Example

   Given the `VehicleStateFactor` table defined above, consider the following records:

```json
[
	{ "make": "Toyota", "state": "CA", "year": 2030, "factor": 8800 },
	{ "make": "Toyota", "state": "CA", "year": 2025, "factor": 7700 },
	{ "make": "Toyota", "state": "CA", "year": 2020, "factor": 6600 },
	{ "make": "Toyota", "state": "CA", "year": 2015, "factor": 5300 },
	{ "make": "Toyota", "state": "CA", "year": 2010, "factor": 4300 },
	{ "make": "Toyota", "state": "CA", "year": 2002, "factor": 3300 },
	{ "make": "Toyota", "state": "CA", "year": 2001, "factor": 2200 },
	{ "make": "Toyota", "state": "CA", "year": 2000, "factor": 1100 }
]
```

For an input vehicle year of `2017`, the lookup would identify the years `2015` and `2020`, and linearly interpolate the factor between `5300` and `6600`, resulting in an output factor of `5820`. Range Table lookups also support lookups of the ceiling and floor values by leveraging the `stepUp` and `stepDown` methods.

For example:

```java
// Get the selector
ResourceSelector selector = ResourceSelectorFactory.getInstance().getSelector(request.quote());
RangeTableRecordFetcher<VehicleStateFactor> stateFetcher = resourceSelector.getRangeTable(VehicleStateFactor.class);

stateFetcher.interpolate(TableUtils.makeKey("Toyota", "CA"), BigDecimal.valueOf(2017), VehicleStateFactor::factor, Interpolation.linear).ifPresent(r -> log.info("1. Interpolate linear factor for 2017: {}", r));
stateFetcher.interpolate(TableUtils.makeKey("Toyota", "CA"), BigDecimal.valueOf(2017), VehicleStateFactor::factor, Interpolation.stepUp).ifPresent(r -> log.info("1. Interpolate stepUp factor for 2017: {}", r));
stateFetcher.interpolate(TableUtils.makeKey("Toyota", "CA"), BigDecimal.valueOf(2017), VehicleStateFactor::factor, Interpolation.stepDown).ifPresent(r -> log.info("1. Interpolate stepDown factor for 2017: {}", r));
```

Output:

```text
1. Interpolate linear factor for 2017: 5820
2. Interpolate stepUp factor for 2017: 6600
3. Interpolate stepDown factor for 2017: 5300
```

Limitations [#limitations]

Tables support up to one million rows each.


# Versioned Resource Selection



Overview [#overview]

Many aspects of your operations will involve processes and information that change over time. The contents of documents, prices, calculations, and other aspects of your processes will evolve. The Versioned Resource Selection feature makes it easier to organize, test, and control these changes so that the correct version of each resource is used based on the data and context of the operation.

This feature controls the selection of these resource types:

* Data Tables
* Dynamic Document Templates
* Static Documents

Each resource declaration corresponds to a set of instances of a specific resource. For example, a table can be defined with a static name (but not data) called `"MyData"`, and then refer to two instances of tables (with data) called `"MyData2023"` and `"MyData2024"`. The job of the Resource Selector is to allow your plugin code to simply ask information from `"MyData"` and have it respond with lookup results from the appropriate instance. When there are many resources that need to be managed as a group this greatly simplifies the logic in your plugins.

<span id="key_concepts" />

Key Concepts [#key-concepts]

These are the key conceptual aspects of versioned resource selection:

* The **SelectionTimeBasis** for a resource is the time property that is used when comparing the time to the availability time for the resource. For example, the criterion for selection in rating operations for a given table could be the `startTime` of the policy, or it could be the current system time. This setting is set in configuration as part of the resource declaration.
* **Resource Declarations** are part of the basic configuration. These include the *static* names for each of the different resources used, along with the `selectionTimeBasis` for those resources.
* **Resources** are instances based on resource declarations. These are created when the data for the resource is first uploaded through the API. For example, when the data for a new table is uploaded, it will be given a `name` and must also specify the `staticName` that ties it to a declaration.
* **Resource Groups** are sets of resources which specify the time that the those resources become available. (The resource becomes available based on the data parameters in the group that contains it.)
* The **Resource Selector** is an object available in plugins that will find the correct resource given only its static name, to simplify plugin logic and abstract away versioning considerations.

<Callout>
  It is possible to add the same resource to more than one resource group. This is most commonly used to prevent redundant instances of data, such as when the same large table might be duplicated several times across multiple groups even though the data is the same. In this case it is more efficient just to add that resource to multiple groups.
</Callout>

<Callout>
  Resource groups can contain resources that have different values for `selectionTimeBasis`. Likewise, resource selectors can manage selection for resources with different values for `selectionTimeBasis`. It is the job of the resource selector to use the appropriate time to determine which resource should be identified for a resource static name.
</Callout>

The Selection Time Basis [#the-selection-time-basis]

Since there is no single "time" associated with a policy, there are different choices for which time is used to decide which resource will be selected. Each resource declaration includes a `selectionTimeBasis` property, and it can have any of these values:

* `termStartTime` (the default for all resource types)
* `policyStartTime`
* `transactionEffectiveTime`
* `currentTime`

For quotes, the `termStartTime`, `policyStartTime`, and `transactionEffectiveTime` are always the same, but these values will vary for policy transactions.

<Callout>
  The selection time basis for invoice documents and delinquencies is limited to `currentTime`.
</Callout>

API and Entity Structure [#api-and-entity-structure]

<ApiSchema name="ResourceGroupResponse" />

<ApiSchema name="ResourceResponse" />

Runtime Behavior in Plugins [#runtime-behavior-in-plugins]

At runtime, for a given resource `staticName`, the system will find the resource with that static name that has the latest `selectionStartTime` on or before the relevant selection time criterion.

Plugins will have access to a *Resource Selector* which will know the relevant `policyStartTime`, `termStartTime`, `segmentStartTime`, and current time, and therefore when the plugin asks the resource selector to retrieve a resource using a `staticName`, it can retrieve the correct instance of the resource using the resource data.

<Callout>
  The protocol for providing the Resource Selector in cases where there is more than one term or segment is still being determined. The `segmentLocator` should be enough for the system to construct it, so it could be that the plugin does something like the following. More details will follow when the protocol is finalized:
</Callout>

```java
// Get the selector...
var theSelector = ResourceSelector.fromSegmentLocator(theSegment.locator);

// and use it to get a table...
var myTable = theSelector.getTable("my_table_static_name");

// or if we can have resource instances defined statically in the development context
// we could do it this way:
var myTable = theSelector.tables
                         .myTableStaticName;

// either way, we can then do lookups:
var someRatingFactor = 100.0 * myTable.lookup("my_key");
```

<Callout>
  For now, tables are the only resource type used in plugins. That may change in future releases.
</Callout>

Document Selection [#document-selection]

Documents, either static or dynamic, have the appropriate resource selected based on the governing term for the transaction that is triggering production of the document, so clients will not have to use the resource selector for documents.

The `transactionEffectiveTime` selection basis is only valid for documents.

Unmanaged Resources [#unmanaged-resources]

Resources that haven't been added to any group are called *unmanaged.* Resources do not have to be added to groups in order to be used in plugins. The resource selector will find resources by `name` if there is no matching resource with the given `staticName`. This is most commonly used for resources that aren't versioned over time.

For this reason, all resource names and all resource declaration static names must be unique in the tenant. Trying to create a resource in the API or update the configuration with a non-unique name will fail with an error.

<Callout>
  Even though unmanaged resources will have a `staticName`, they can't be referenced with this name because there is no date criterion to use for selection. This is true even if there is only one resource with that static name.
</Callout>

Locked Resources [#locked-resources]

The `LockingResourceSelector` forces specified managed resources to remain unchanged for a term or quote following initial selection. This selector contains all [Resource Selector](/configuration/plugins/overview#resource-selector) methods, in addition to a `lock()` method that forces the system to use specified resource instances for a term or quote.

Locking resources for a term or quote can be useful if you want to ensure that the first selection of a resource remains in effect throughout subsequent fetch transactions, even after resetting a quote or transaction, and if you have deployed other resources with start times that would cause the resource selector to select those resources instead. For example, consider this scenario:

* You deploy a rating table (`selectionTimeBasis: policyStartTime`) instance `A` and add it to a resource group with start date `2026-01-01`.
* You create a quote with start date `2026-03-01` and complete the rating process, using factors in `A` to determine pricing.
* You deploy a new rating table instance `B` to a new resource group with start date `2026-02-01`.
* You reset the quote and reprice.
* `B` will be selected by the resource selector when the system executes your [Rating Plugin](/configuration/plugins/rating) implementation.

If you would prefer `A` to be chosen after the reset in the scenario above, `LockingResourceSelector` accommodates this use case. The same applies to transactions. The `LockingResourceSelector` can also be useful if you want all policy changes within a term to use the same resources, even if the term is already using new resources.

Managing Locked Resources [#managing-locked-resources]

As mentioned above, `LockingResourceSelector` provides all the same fetching methods as the `ResourceSelector`. These methods fall back to the same selection logic as `ResourceSelector`, but only after attempting to return an appropriate resource instance already locked to the quote or term.

The `lock()` method accepts a `SelectableResource` class name and returns `true` if the resource selection and locking process was successful, and `false` if a resource with the given name is already bound to the quote or term. The method throws an exception if there is no resource instance to select and bind. If the method returns `false`, no change is made to the binding, which allows you to call `lock()` without needing to implement logic to avoid accidental overwrites (For example, during the rating process for a mid-term policy change).

Here's an example of [Rating Plugin](/configuration/plugins/rating) logic that accommodates the scenario described above:

```java
var selector = ResourceSelectorFactory.getInstance().getLockingSelector(quote);
selector.lock(SampleTable.class);

var rate = selector.getTable(SampleTable.class)
        .getRecord(SampleTable.makeKey("some_lookup_value"))
        .orElseThrow()
        .sampleColumn2();

```

Clearing Locked Resources [#clearing-locked-resources]

You can clear locked resources when <ApiLink name="resetQuote">resetting a quote</ApiLink> or <ApiLink name="resetTransaction">transaction</ApiLink> by setting the `resetLockedResources` flag to `true` in the <ApiLink name="ResetOptions" /> request object.

Resource Locking API Endpoints [#resource-locking-api-endpoints]

[Resource Locking](/api/resources/resource-service#resource-locking) API endpoints can be used to check which resource instances are currently in use for a quote or term, and to lock and unlock resource selections. See the [Resource Service API](/api/resources/resource-service#resource-locking) reference page for more information.

Usage Example [#usage-example]

Suppose you need to manage two sets of resources in your operations:

* Several tables and document templates that are selected based on the `startTime` of the policy *term* being processed, updated quarterly; and
* Other document templates that are selected based on the actual time they are rendered, updated annually.

To handle this case, you would create two series of resource groups. The first series would set the `selectionStartTime` to a quarterly cadence, such as `2023-01-01`, `2023-04-01`, ..., and each group would contain the resources (instances) of tables and templates for the quarter. The second series would set the `selectionStartTime` to a series of years, like `2023-01-01`, `2024-01-01`, ...\`\` and contain those template instances that were updated annually.

Then, plugins just ask the resource selector for resources using their static names, without having to worry about any of the versioning behavior.


## API Reference

ResourceGroupResponse
Properties:
  locator (ulid, required)
  name (string, required)
  retired (boolean, required)
  selectionStartTime (datetime, required)
  resourceNames (string[], required)
  createdBy (uuid, required)
  createdAt (datetime, required)

ResourceResponse
Properties:
  name (string, required)
  staticName (string)
  resourceType (Enum constraintTable | customFont | documentTemplate | documentTemplateSnippet | rangeTable | secret | staticDocument | table, required)
  lookupTableLocator (ulid)
  template (string)
  staticDocumentLocator (ulid)
  templateFormat (Enum liquid | velocity)
  createdBy (uuid, required)
  createdAt (datetime, required)
  scope (Enum transaction | policy | term | segment | invoice)
  trigger (Enum validated | priced | accepted | underwritten | issued | generated | declined | rejected | refused)
  format (Enum text | html | pdf | jpg | jpeg | doc | docx | xls | xlsx | csv | txt | zip)
  rendering (Enum dynamic | prerendered)
  jurisdictions (string[], required)

# FNOL Coverage Checks



Overview [#overview]

With a [First Notice of Loss](/features/claims/fnol), *Coverage Checks* can be automatically performed to validate whether coverage could apply to the loss. This is done by finding the segment of the policy that is active at the time of the loss (if any), and optionally checking the contents of that segment for coverage information.

Process [#process]

When an FNOL is created, the system will set the FNOL's `segmentLocator` automatically, based on the state of the policy as of the `incidentTime`, and excluding any segments created atfer the incident time. This ensures that policy changes made after the incident time are not considered for purposes of checking coverage.

<Callout>
  The `segmentLocator` will only be set for non-gap segments. If the segment found is a `gap` type, the locator will remain null.
</Callout>

After creating the FNOL, you may <ApiLink name="addLosses">add</ApiLink> *Losses*. The coverage check process will update the `fnolLossState` for each `pending` loss to either `valid` or `excluded` based on the coverage check.

The following steps are conducted in the coverage check process:

* First, the system will check whether, for the time of the incident time of the FNOL, that there is a non-null, non-gap segment on the policy, created before the incident time, that is not superseded by a gap segment. If there is no such segment, all losses with state `pending` will be updated to become `excluded`.
* Otherwise, for each loss that has `pending` state, the system will check whether a corresponding coverage element is available.

The coverage element check for a loss is as follows:

* If the loss's `coverageElementLocator` is not null, *and* the segment contains an element with that locator, the loss is `valid`.

* If the loss type is configured with an empty array of coverage types, the loss is `valid`.

* If the loss's `exposureElementLocator` is null:
  * If there is an element *anywhere* in the segment with `type` equal to *any* of the coverage types configured for the loss, the loss is `valid`.
  * Otherwise the loss is `excludded`.

* If the loss's `exposureElementLocator` is *not* null:
  * If the `coverageElementLocator` is null *and* there is an element that has that a type matching *any* of the configured coverage types for the loss which is a direct or indirect ancestor or descendant of the exposure element (that is, no horizontal traversals are needed to find the coverage element from the exposure element), the loss will be `valid`.
  * If such an element is identified, its locator will be used to set the `coverageElementLocator` for the loss.

* If *none* of the above scenarios apply, the loss will be `excluded`.

<Callout>
  You may manually override the coverage check determination with the <ApiLink name="includeLoss" /> and <ApiLink name="excludeLoss" /> endpoints.
</Callout>

See Also [#see-also]

* [First Notice of Loss](/features/claims/fnol)
* [FNOL API Guide](/api/claims)


# First Notice of Loss ("FNOL")



Overview [#overview]

The First Notice of Loss ("FNOL") process is intended to capture relevant data about a potential loss before the formal claims process starts. It accommodates information that is relatively unstructured, incomplete, potentially inaccurate, and subject to revision.

In Socotra, an FNOL is distinct from a claim, but can be associated with or used as the basis for a claim.

Configuration [#configuration]

FNOL and losses are configured at the top configuration level:

```javascript
{
    fnol: map<string, FnolRef>,
    losses: map<string, LossRef>,
    lossCategories: string[]
}
```

See the [Deployments API](/api/configuration-and-development/deployments) for details on `FnolRef` and `LossRef`.

When you define an FNOL, you specify the loss types appropriate for that FNOL. In turn, a loss type is defined as belonging to some category specified in `lossCategories`. Beyond that, as with other primary platform entities, you may define an inheritance hierarchy, associate data extensions, specify contact associations, fine-tune the search behavior, and assign a numbering plan.

State Flow and Validation [#state-flow-and-validation]

FNOLs can have the following states:

* `draft`
* `validated`
* `onClaim`
* `completed`
* `rejected`
* `discarded`

An FNOL starts in the `draft` state, where it remains until validated, either manually or by setting the `autoValidate` flag to `true` in the `FnolCreateRequest`.

An FNOL will proceed to `onClaim` state when at least one claim has been created with it. From there, it may proceed to `completed`, `rejected`, or `discarded`.

An FNOL in the `onClaim` state will revert to the `validated` state if any of its data is modified.

Losses [#losses]

You may <ApiLink name="addLosses">add</ApiLink> and <ApiLink name="deleteLosses">remove</ApiLink> *Losses* from the FNOL, and optionally tie each loss to a specific policy element for associating coverage and exposure information. The system can automatically check whether coverage is valid using [Coverage Checks](/features/claims/coverage-checks).

Versioning [#versioning]

FNOL versioning mirrors the same behavior as contacts. Versioning history is not kept for `draft` records.

Promotion [#promotion]

An FNOL can be promoted to a claim via the <ApiLink name="createClaim" /> endpoint.

See Also [#see-also]

* [FNOL API Guide](/api/claims)
* [Coverage Checks](/features/claims/coverage-checks)


# Auto Credit Application



Overview [#overview]

Auto Credit Application enables the automatic application of account credit balances to open invoices, reducing manual intervention and improving reconciliation.
When enabled, this feature ensures that available credits are automatically used to settle outstanding invoices, streamlining the billing process and reducing confusion for both carriers and customers.

Key Concepts [#key-concepts]

* **Dynamic Setting:** The feature is controlled by the `autoApplyExcessToInvoicesEnabled` flag that can be toggled on or off per plan that the account can refer.
* **No Backfilling:** The feature does not retroactively apply to past transactions; however, it will process existing tenants if the trigger conditions are met.
* **Automatic Triggers:** Once deployed, the process is triggered automatically by the system when certion events occur.

How It Works [#how-it-works]

Configuration [#configuration]

The feature is activated by setting `autoApplyExcessToInvoicesEnabled` flag to true in the relevant <ApiLink name="ExcessCreditPlanRef" />.

```json
"AutoCreditApplication": {
  // ...,
  "disburseExcess": false,
  "advanceDisbursementTo": "executed",
  "autoApplyExcessToInvoicesEnabled": true,
  // ...,
}
```

Create or update an account with this <ApiLink name="ExcessCreditPlanRef" />.

```json
{
	// ...,
	"type": "ConsumerAccount",
	"delinquencyPlanName": "Standard",
	"excessCreditPlanName": "AutoCreditApplication"
	// ...,
}
```

Since `autoApplyExcessToInvoicesEnabled` is enabled for this account, the system will automatically attempt to apply any positive account credit balance to open invoices associated with this account.

Processing Logic [#processing-logic]

* **Check Credit Balance:** The system checks if the account has a positive credit balance in the relevant currency.
* **Check for Open Invoices:** If there are open invoices, the system proceeds; otherwise, it exits.
* **Sort Invoices:** Invoices are sorted by their earliest due date, excluding any negative invoices that are found. Sorting priority is given to invoices with a billing period matching the credit invoice's billing period, followed by invoice due date, and lastly `generateTime`.
* **Apply Credits:** One or more credit distributions are created and executed, applying available credits to the sorted invoices until we don’t have open invoices left or the account credit balance has been exhausted.
* **Handle Remainder:** Any remaining credit that cannot be applied is left in the account for future use or disbursement.

Triggers [#triggers]

* **Credit Balance Increases:** When the account credit balance becomes positive.
  * **Example:** Create and post a payment whose amount is more than the targets can use. Below is a payment request of $500, targeting only $200.00 to a specific invoice. The remaining $300.00 becomes a credit and will trigger the auto application process.

```json
{
	"accountLocator": "{accountLocator}",
	"amount": 500.0,
	"data": {
		"payerFirstName": "first",
		"payerLastName": "last",
		"note": "payment"
	},
	"targets": [
		{
			"containerLocator": "{invoiceLocator}",
			"containerType": "invoice",
			"amount": 200.0
		}
	],
	"transactionNumber": "abc1234",
	"type": "StandardPayment"
}
```

* **New Invoices Generated:** When new invoices are created, regardless of credit balance changes.
  * **Example:**
    * Set up an account with a positive `accountCreditBalance` by posting a payment and follow one of the steps below;
      * Create and issue a new quote, which can result in an open invoice.
      * Create and issue a new transaction, which can result in an open invoice.
      * Do early invoicing for certain installments.
      * Add a new fee that can immediately be invoiced.

* **Automatic via the excess credit handling workflow**
  * Whenever the excess credit handling workflow runs, it will first run the auto credit application if eligible before any other logic.

Best Practices [#best-practices]

* **Enable Only When Needed:** Only enable auto credit application for accounts or products where automatic reconciliation is desired.
* **Monitor Credit Balances:** Regularly review accounts with frequent credits to ensure the feature is working as intended.
* **API Integration:** Use the provided API for on-demand processing or integration with external workflows.

Limitations [#limitations]

* **No Backfilling:** Past transactions are not automatically processed.
* **No Disbursement:** The feature does not trigger disbursements, only credit applications to invoices.
* **Payments Preview:** The feature is not triggered during payment previews.
* **Invoice Preview:** The feature is not triggered during invoice previews.


# Autopay



import Image from 'next/image';

Overview [#overview]

The *Autopay* feature enables insureds to set up a payment method and have regular payments executed automatically, so they don't have to worry about mailing a physical check or going online before the due date and possibly incurring late fees or policy lapses. This also leads to more predictability for payments and fewer mismatches between payments and amounts due.

The typical autopay process looks like this:

* Add an `autopayLeadDays` setting to your installment plans. This specifies the number of days before invoices become due that the autopay process will start.
* Installments and invoices will have their `autopayTime` value set using the lead days.
* When the `autopayTime` is reached for an invoice, the system will execute the Autopay Plugin.
* The plugin may be implemented to create a <ApiLink name="PaymentResponse">Payment</ApiLink> in `requested` state.
* The [Payment Execution Service](/features/billing/payment-execution-service) will attempt to execute the actual transaction with an external financial institution.
* If successful, the payment will advance to `posted` state and settle the invoice; otherwise retries may be attempted.

Installments and Invoices [#installments-and-invoices]

When [installments](/features/billing/installments-and-installment-lattices) are generated, the `autopayTime` will be set using the `autopayLeadDays` property on the installment plan. This time will be used to set the `autopayTime` on the invoice when it is generated.

If more than one installment is added to an invoice, the invoice's autopay time will be the *earliest* autopay time of its installments.

The autopay timing looks like this:

<Image src="/images/autopay/autopay-timing.png" alt="autopay timing" width={800} height={337} unoptimized />

<Callout>
  To suppress autopay for an invoice, you can set its `suppressAutopay` property to `true` using the <ApiLink name="updateInvoice" /> endpoint.
</Callout>

<span id="autopay-plugin" />

Autopay Plugin [#autopay-plugin]

When the `autopayTime` is reached for an invoice, the system will execute the Autopay Plugin. See the [Autopay Plugin](/configuration/plugins/autopay) feature guide for more information.

Payment Requests [#payment-requests]

After a payment is created in `requested` state the [payment execution service](/features/billing/payment-execution-service) will take over. The overall flow looks like this:

<Image src="/images/autopay/autopay-payment-request-flow.png" alt="autopay payment request flow" width={800} height={345} unoptimized />

See Also [#see-also]

* [Payments](/features/billing/payments)
* [Payment Execution Service](/features/billing/payment-execution-service)
* [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing)
* [Plugins Overview](/configuration/plugins/overview)
* [Payments API](/api/billing/payments)
* [Payments Execution API](/api/billing/payment-execution)


# Backloading Installments



import Image from 'next/image';

Overview [#overview]

When an installment plan changes from a longer cadence (such as full-pay) to a shorter cadence, this will shift installment dates to the future. This can cause a credit for the insured to be generated. This topic describes the default system behavior in such a situation.

We'll describe an example where:

* A policy is created with an annual term, effective January 1 to January 1
* There is $1200 annual premium charged
* When first issued, it is on a full-pay invoice, and the insured has paid the initial invoice in full
* Effective halfway through the term, on July 1, the insured requests to shift to a monthly installment cadence, in order to temporarily use the pre-paid premium amount

<Callout>
  There are many possibilities that work with this behavior, such as charging increased premium amounts or assessing fees along with the change, or making other changes to coverage. Those situations will work in a similar way to this simplified example
</Callout>

Initial State [#initial-state]

Initially the policy has a single Charge for the $1200 premium, along with an [installment lattice](/features/billing/installments-and-installment-lattices) and installment, and the invoice has been generated and paid:

<Image src="/images/backloading_installments_example/backloading_installments_example_01.png" alt="backloading installments example 01" width={700} height={315} unoptimized />

Lattice Creation [#lattice-creation]

When the installment cadence is changed effective July 1, the first thing that has to happen is creation of an updated installment lattice, which is the template for dividing charges into individual installments. The process starts with computing what the lattice would look like if the new monthly cadence were to be effective across the *entire* term:

<Image src="/images/backloading_installments_example/backloading_installments_example_02.png" alt="backloading installments example 02" width={700} height={96} unoptimized />

Then we consider the part of the original lattice before the effective time of the change, along with the part of the new lattice after the change effective time:

<Image src="/images/backloading_installments_example/backloading_installments_example_03.png" alt="backloading installments example 03" width={700} height={165} unoptimized />

These two halves are combined to create a new lattice:

<Image src="/images/backloading_installments_example/backloading_installments_example_04.png" alt="backloading installments example 04" width={700} height={105} unoptimized />

Charge Processing [#charge-processing]

Next we create an installment based on offsetting the original charge as it was scheduled with the old lattice, since the change's effective time occurs during that existing charge:

<Image src="/images/backloading_installments_example/backloading_installments_example_05.png" alt="backloading installments example 05" width={700} height={103} unoptimized />

And then we can apply the charge to the *new* lattice, which yields these installments:

<Image src="/images/backloading_installments_example/backloading_installments_example_06.png" alt="backloading installments example 06" width={700} height={110} unoptimized />

Invoicing [#invoicing]

Now with the new installments, invoicing going forward will look like this:

<Image src="/images/backloading_installments_example/backloading_installments_example_07.png" alt="backloading installments example 07" width={700} height={105} unoptimized />

Results [#results]

After all the changes, we have this:

* The original $1200 invoice remains as it was, fully paid.
* Immediately a new invoice for negative $600 is generated.
* The negative invoice settles automatically and the $600 is sent to the customer's credit balance.
* The credit balance may be disbursed when desired
* Six monthly invoices will be generated for $100 each, starting July 1, as adjusted for lead times as desired according to the installment plan settings.

<Callout>
  Upcoming features will support automatically handling the excess credit balance with automation based on configurable rules.
</Callout>


# Billing Holds



import Image from 'next/image';

Overview [#overview]

Billing Holds are available to prevent the system from initiating or continuing automatic invoicing and delinquency processes that should not be made for certain accounts in the system. These are implemented using <ApiLink name="HoldResponse">Hold</ApiLink> objects. These are created and managed as needed to reflect the onset and eventual conclusion of any desired hold states.

Lifecycle [#lifecycle]

The lifecycle of a hold looks like this:

<Image src="/images/billing_hold.png" alt="billing hold" width={600} height={293} unoptimized />

Holds can be created in `draft` state and then `validated`, but won't have an effect until you explicitly activate them.

When a hold should no longer be in effect, you can explicitly release or discard it.

Validation [#validation]

Unlike other entities where extension data is used, validation as it pertains to billing holds is focused on two basic checks:

* Does the target account of the hold exist?

* Are there any existing `active` or `validated` holds for the given target type (`invoicing` or `delinquency`) and target account?

Similar to other entities, if a hold is created in `draft` state, it can be advanced to later states as long as it passes validation.

Invoice Holds [#invoice-holds]

When a hold exists for an account with `targetType` equal to `invoicing`, then invoices will not be created for that account. The relevant installments will remain in uninvoiced state until the hold is released or discarded.

<Callout>
  Invoices that have already been generated will remain and can become past due. To prevent the delinquency from proceeding, create a delinquency hold in addition to the invoicing hold.
</Callout>

Delinquency Holds [#delinquency-holds]

If an account has a hold with `targetType` equal to `delinquency`, then:

* Any new delinquencies will be created in `preGrace` state, and they will not proceed, and the grace period will not commence.
* Existing delinquencies that are `inGrace` will revert to `pregrace` state and act as if the delinquency had not yet commenced.

When it comes time to release the delinquency hold, the grace period can be adjusted so that the policy will lapse at an appropriate time if it remains delinquent.

See Also [#see-also]

* [Billing Holds API](/api/billing/holds)


# Credit Balances



Overview [#overview]

*Credit Balances* are containers for accumulated credits which are owned by the insured. Credit balances can rise in circumstances like:

* Overpayments of invoices
* Cancellations
* Policy changes which reduce premiums
* Shifting from a front-loaded installment schedule such as `fullPay` or `annually` to a more even schedule such as `monthly`

Likewise, credit balances can decline when used to pay [invoices](/features/billing/invoicing) or when funding [disbursements](/features/billing/disbursements).

When a [payment](/features/billing/payments) is posted and applied to an invoice with a lesser unsettled amount, the remainder will automatically be credited to the account's credit balance.

Usage [#usage]

Amounts accrued in credit balances can be drawn down via <ApiLink name="DisbursementResponse">disbursements</ApiLink> (sending funds back to the insured) or applying them to outstanding invoices using a <ApiLink name="CreditDistributionResponse">credit distribution</ApiLink>.

In either case, a new disbursement or credit distribution entity is created explicitly, and the source or sources of credit are added to it. Then, once the entity proceeds through its lifecycle and reaches `executed` state, the funds are debited from the source and to the target.

The following table details which `containerType` <ApiLink name="CreditItem">values</ApiLink> are allowed for credit distributions, disbursements, and payments:

| Operation           | Allowed source `containerType` | Allowed target `containerType`       |
| ------------------- | ------------------------------ | ------------------------------------ |
| Credit Distribution | `account`, `invoice`           | `account`, `invoice`, `invoiceItem`  |
| Disbursement        | `account`                      | None - Disbursements have no targets |
| Payment             | `invoice`                      | `account`, `invoice`, `invoiceItem`  |

See Also [#see-also]

* [Disbursements](/features/billing/disbursements)
* [Excess Credits](/features/billing/excess-credits)
* [Invoicing](/features/billing/invoicing)
* [Payments](/features/billing/payments)
* [Account Balances API](/api/billing/account-balances)


# Credits from Policy Transactions and Billing Changes



Overview [#overview]

There are cases where a transaction results in a net credit for the insured, rather than the typical case where coverage is added and a debit results. For example:

* Policy cancellations
* Removing a coverage or exposure
* Choosing coverage terms which result in a premium rate reduction
* A change in risk profile resulting in lower premium rates

In each of these cases, the total premium and other charges for the policy will decline, resulting in a net credit for that transaction.

Also, sometimes a billing change will result in a shift in the profile of installments such that there is less due in the short term and more due in the longer term, effectively generating a short term credit. This could happen by shifting from a full-pay plan to a a monthly installment plan .

You can choose to leave some or all of the surplus credit amount in the account's [credit balance](/features/billing/credit-balances), and/or create a [disbursement](/features/billing/disbursements) to return excess to the insured.

Example 1: Standard Cancellation [#example-1-standard-cancellation]

In a simple case, consider a year-long policy billed on a full-pay basis, with premium of $1200 per year. If this policy is cancelled after the initial installment is paid, the situation will look like this:

* Invoice 1: $1200 (paid)
* Invoice 2: -$600

The net-credit invoice is settled automatically and then we have a $600 credit in the insureds' credit balance. This amount could be [disbursed](/features/billing/disbursements) to the insured or applied against other policies on the account, if there are any.

Example 2: Lapse [#example-2-lapse]

Consider the case where there is:

* A $1200 annual policy paid at $100/month
* The first two invoices are paid normally ($100 each)
* The third invoice becomes past due
* The fourth is generated and remains unpaid
* The policy lapses and is cancelled halfway through the fourth billing cycle, 3 1/2 months into the coverage period

In this case, a cancellation transaction is generated for reversal of 8 1/2 months' worth of premium, or an $850 credit. Unlike in the full-pay case, this amount is spread out over installments to align with the original, positive amounts.

This cancellation will be spread across the installment periods after the cancellation effective time, so $-50 for the fourth installment, and $-100 for the remaining 8 installments. This means that the fifth through twelfth invoices are each for $100 + $-100, or net zero. The only non-zero invoices remaining are the 3rd and 4th (from before, $100 each), and the portion of the cancellation invoice for the 4th installment, $-50. So in all we have:

* Invoice 3: $100
* Invoice 4: $100
* Invoice 4 Cancellation: $-50
* Invoice 5 onward: net zero

The cancellation invoice is settled immediately and the $50 is applied to the credit balance. This amount can then be applied to either (or both) of the other outstanding invoices, and the net that the insured still owes is $150.

See Also [#see-also]

* [Credit Balances Feature Guide](/features/billing/credit-balances)
* [Excess Credits Feature Guide](/features/billing/excess-credits)
* [Disbursements Feature Guide](/features/billing/disbursements)
* [Backloading Installments](/features/billing/backloading-installments)
* [Account Balances API](/api/billing/account-balances)
* [Disbursements API](/api/billing/disbursements)


# Delinquency Events



Overview [#overview]

In addition to the built-in delinquency lapse event, you can add any number of custom events for delinquencies. This is done by adding <ApiLink name="DelinquencyEventConfiguration">delinquency events</ApiLink> to the <ApiLink name="DelinquencyPlanRef">delinquency plan</ApiLink>.

Delinquency events are configurable events that are based on the delinquency workflow, based on offsets from either the start or end of the grace period for the delinquency.

Any number of named event types can be added to a delinquency configuration. Each event fires a plugin.

Delinquency events are useful for things like:

* Notifying affected parties on the policy, such as additional named insureds
* Notifying mortgagees
* Triggering external generation of documents, such as a Notice of Intent to Cancel or a billing dunning notice.
* Creating manual activities for review
* Adding additional custom logic

<Callout>
  Future releases will support built-in document generation and activity creation.
</Callout>

Configuration [#configuration]

Events are added to <ApiLink name="DelinquencyPlanRef">delinquency plans</ApiLink>, with a named set of <ApiLink name="DelinquencyEventConfiguration">event definitions</ApiLink>. Each event definition has an `offsetBasis` and an `offsetDays` property.

If the delinquency is still unsettled, then the event will fire using the offset basis (either the `gracePeriodStart` or `gracePeriodEnd`), and adding the offset days value. Negative offsets are possible, which cause the event to fire before the basis time. For example, to fire an event three days before the end of the grace period, use `gracePeriodEnd` for `offsetBasis` and `-3` for `offsetDays`.

<Callout type="warn">
  The `delinquencyCreation` offset basis will be removed; use `gracePeriodStart` instead.
</Callout>

When a delinquency is created, its `configuredDelinquencyEvents` property will contain information about how events are configured for that delinquency plan. These may differ from the actual `delinquencyEvents` if they are modified in the delinquency pre-commit plugin or by using the API.

Operation [#operation]

When the delinquency is created, usually the grace period will start immediately and delinquency events will be created at that time. If there is a [delinquency hold](/features/billing/billing-holds) on an account when it becomes past due, events will not be created because the delinquency will remain in `preGrace` state. When the hold is released, then grace will start and events will then be created.

If a hold is placed on a delinquent account, the delinquency will revert to `preGrace` state, but any existing events will remain in place and trigger as scheduled. These events can be adjusted as needed based on business requirements. The transition back to grace when the hold is released will not update events or create new ones.

When the delinquency event fires, the delinquency event plugin fires, and any needed custom logic can be added to that plugin.

To interact with events directly, including direct update of trigger times, use the <ApiLink name="fetchDelinquencyEvents" /> and <ApiLink name="updateDelinquencyEvent" /> endpoints.

<Callout>
  If the delinquency's `graceEndsAt` property is changed, this will not change the time when custom events based on lapse will fire. These can be updated manually with the <ApiLink name="updateDelinquencyEvent" /> endpoint.
</Callout>

See Also [#see-also]

* [Delinquency Feature Guide](/features/billing/delinquency)
* [Delinquency API](/api/billing/delinquency)


# Delinquency



Overview [#overview]

*Delinquency* is a process that includes a workflow to manage actions to be taken when the insured has one or more invoices that are past due, i.e. invoices that have a `dueTime` in the past and are not yet fully settled with [payments](/features/billing/payments) or applied [credits](/features/billing/credit-balances).

Delinquencies can be used to create policy *lapses*, which are policy cancellation transactions that are created and issued automatically based on configuration and plan settings.

Configuration [#configuration]

Delinquency is set up using configuration *Delinquency Plans*. When policy becomes delinquent, the system looks for the delinquency plan that governs that policy, and uses the settings on that plan to create and manage the delinquency. Each plan has the following settings:

* `gracePeriodDays`: An integer value that sets the timespan in days between the onset of the delinquency and the time at which the policy system will be signalled to cancel the policy.
* `lapseTransactionType`: The type of the transaction that will be created for the delinquency if it reaches the lapse time. This must be a policy transaction of category `cancellation`.
* `delinquencyLevel`: Either `policy` or `invoice`. If the setting is `policy`, then when other invoices for that policy become past due, they will be managed with the existing workflow. If the level is `invoice` then a new delinquency workflow will be spawned for each invoice.
* `advanceLapseTo`: The state to which the system should automatically advance the lapse transaction. If this is not `issued`, then the lapse will have to be manually issued for cancellation to be effective.
* `events`: A set of custom delinquency events that can be added to the delinquency workflow. See *Delinquency Events*, below.

Delinquency Onset [#delinquency-onset]

A policy becomes *Past Due* when any invoice which contains any invoice item for that policy reaches its `dueTime` without being fully settled. When that happens, the system will look for a delinquency plan, in this order:

* The `delinquencyPlanName` on the policy
* The `delinquencyPlanName` on the account
* The `defaultDelinquencyPlan` in configuration

If a delinquency plan is found, then a <ApiLink name="DelinquencyResponse">delinquency workflow</ApiLink> is created, and the delinquency workflow begins. Using the plan settings and past-due data, the delinquency will have the following settings established:

* The `accountLocator` for the involved insured account
* The `graceStartedAt` time, which is usually the time the delinquency is created
* The `graceEndsAt` time, when the policy will lapse, based on the `gracePeriodDays` setting
* `references`, which describe the policies and invoices that are involved in the delinquency.
* `settings` are stored for reference: `advanceLapseTo`, `gracePeriodDays`, `lapseTransactionType`, and `delinquencyLevel`

<Callout>
  Before a lapse occurs, you may change the lapse time using the <ApiLink name="updateDelinquency" /> endpoint.
</Callout>

Lapse [#lapse]

When the `graceEndsAt` time arrives for an unsettled delinquency, the system will create a cancellation transaction if the `lapseTransactionType` is set on the delinquency plan. This transaction will automatically advance to the state given on the `advanceLapseTo` setting, and after that the cancellation may be managed manually if it is not yet `issued`.

If not changed by the client, the lapse will become at the end of the day calculated using the `gracePeriodDays` setting.

<Callout>
  In addition to the lapse event, you can add custom events. See the [Delinquency Events Feature Guide](/features/billing/delinquency-events) for details.
</Callout>

See Also [#see-also]

* [Delinquency Events Feature Guide](/features/billing/delinquency-events)
* [Delinquency API](/api/billing/delinquency)


# Disbursements



import Image from 'next/image';

Overview [#overview]

*Disbursements* are a feature that provide a controlled way to return credit amounts to the insured. These credits may arise in circumstances such as:

* Overpayments of invoices
* Cancellations
* Policy changes that reduce premiums
* Shifting from a front-loaded installment schedule such as `fullPay` or `annually` to a more even schedule such as `monthly`

In cases like this, excess credits will accumulate in an account's [Credit Balance](/features/billing/credit-balances) and can then be drawn upon with a payable disbursement.

<Callout>
  An invoice with a negative balance (sometimes called a *Credit Memo*) will not result in an immediate refund to the insured, even though such invoices will be settled immediately upon generation. The purpose of the credit balance is to hold the credit amount so that the refund process can be managed. To automatically return these funds, see the [Excess Credits Feature Guide](/features/billing/excess-credits).
</Callout>

Lifecycle [#lifecycle]

<Image src="/images/disbursement-lifecycle.png" alt="disbursement lifecycle" width={600} height={628} unoptimized />

Disbursements start in `draft` state, and the normal progression is from there to `validated`, `approved`, and finally `executed`.

A disbursement that has become `validated` but hasn't been executed yet may be `reset`, which pulls it back to `draft` state where it can be modified. Only `draft` disbursements can have their `amount` or other data changed.

A disbursement that has been `validated` or `approved` can be explicitly `rejected`, to signify that the disbursement has been disallowed.

Disbursements in `draft` or `validated` state may be `discarded`.

An `executed` disbursement may be `reversed` to reflect that the outgoing payment has become invalid for some reason.

The states `reversed`, `rejected`, and `discarded` are terminal; the disbursement cannot be used after it reaches any of these states.

<Callout>
  Permissions can be used to ensure that proper separation between disbursement creation, modification, and approval is maintained.
</Callout>

Credit Sources [#credit-sources]

Disbursements are structured so that they may draw upon multiple sources. Currently only the Account's [credit balance](/features/billing/credit-balances) and individual invoice items that are credits may be used as a source. If the amounts to draw upon for each source are not specified, then the ones with larger credit amounts will be used first.

<Callout type="warn">
  Disbursements cannot use sources that belong to other customer accounts.
</Callout>

Financial Instruments [#financial-instruments]

The destination for the disbursement can be specified with a <ApiLink name="FinancialInstrumentResponse">financial instrument</ApiLink>, which will be reflected as an <ApiLink name="ExternalCashTransactionResponse">external cash transaction</ApiLink> in the <ApiLink name="DisbursementResponse" />.

<span id="disbursementConfig" />

Configuration and Data Extensions [#configuration-and-data-extensions]

Disbursements can be configured with <ApiLink name="DisbursementRef">different types</ApiLink> and each type can specify a unique structure for [data extensions](/configuration/data-extensions/overview). Disbursements are declared as top-level items in the <ApiLink name="ConfigurationRef">configuration file</ApiLink>.

Accounting [#accounting]

When a disbursement is `approved`, the source or sources of the disbursement will be drawn down (debited) to fund the disbursement (which is a credit). When the disbursement is `executed`, the disbursement will be debited, and the corresponding cash account will be credited. If the sources for the disbursement do not provide sufficient credits to reach the amount of the disbursement, the approval will fail, even if the authorized user has approved the transaction.

If an `approved` disbursement becomes `rejected`, an accounting transaction will revert its funds back to the original sources, and the disbursement will then have a zero balance.

On reversal, both the above transactions will be effectively reversed, such that the amounts drawn from the disbursement sources are restored, and the disbursement itself will remain having a zero balance.

See Also [#see-also]

* [Excess Credits Feature Guide](/features/billing/excess-credits)
* [Disbursements](/api/billing/disbursements)
* [Financial Instruments](/api/billing/financial-instruments)


# Early Invoicing



Overview [#overview]

Typically the invoicing system is triggered by the `generateTime` on [installments](/features/billing/installments-and-installment-lattices) are billable. Once this trigger is reached, the system will gather all installments for the account that have reached their generate time, and create one or more invoices from them.

"Early" invoicing involves issuing invoices for installments that haven't yet reached their generate time.

Invocation [#invocation]

Early invoicing starts with a request to the <ApiLink name="initiateEarlyInvoicing" /> endpoint. The <ApiLink name="EarlyInvoicingRequest" /> contains information used to determine which uninvoiced installments will be invoiced. This can be done either by:

* Specifying an `accountLocator` and the `invoiceThroughTime`, which will identify all installments that are uninvoiced and have a `generateTime` at or before the given time; or by
* Specifying a set of installments using the `installmentLocators` property.

In addition, you can include:

* An optional `invoiceDueTime`, which allows you to override the system-calculated due time.
* An optional `timezone`, which if provided will override the system-calculated timezone.
* The `ignoreHolds` flag, which if set to `true` will exclude all installments for accounts that have an invoicing hold set.

<Callout>
  If no installments are found based on the request, then no invoices will be created and no error will be generated.
</Callout>

Behavior [#behavior]

The system will gather all the installments to be invoiced (either explicitly, or based on the generate time) and then group them as needed based on billing level and currency. They will
*not* be grouped separately based on different due times, start or end times, timezones, etc.

For each installment group, one invoice will be created:

* The `dueTime` for the invoice will be either the `dueTime` specified in the request, or if that is not set, the *earliest* `dueTime` of all the installments in that group.
* The `startTime` will be the *earliest* `startTime` for all the installments in the group.
* The `endTime` will be the *latest* `endTime` for all the installments in the group.
* The `timezone` will be the timezone in the request, or if that is not set, the `timezone` of the installment with the earliest `startTime`.

Early invoicing is handled asynchronously from the request sent.

Error Conditions [#error-conditions]

An error will result in any of these cases:

* The `invoiceThroughTime` is given without also including the `accountLocator`
* The `invoiceThroughTime` and `installmentLocators` are both set, or neither set
* The `installmentLocators` contain installments belonging to more than one account

<Callout>
  If an installment locator is given that is already invoiced, it will be ignored. Also, if the `accountLocator` is set, it will be ignored if `invoiceThrough` is not set.
</Callout>

<Callout type="warn">
  Up to 1000 installments per request are supported.
</Callout>

See Also [#see-also]

* [Invoicing Feature Guide](/features/billing/invoicing)
* [Invoices API](/api/billing/invoices)
* [Jobs API](/api/configuration-and-development/jobs)


# Excess Credits



Overview [#overview]

Typically, funds flow in one direction only within an insured's billing account: inward. Customers accrue charges based on provided coverage, and they send payments to cover those charges. Occasionally the funds can move in the other direction, where the carrier must send a disbursement back to the insured. This can happen in situations like:

* Return premium from policy changes that reduce overall premium
* Cancellations
* Overpayments
* Erroneously sent or applied payments
* Reallocating payments such that greater amounts are allocated to credit balances
* Ad-hoc credits

To avoid accrual of too much credit for any particular account, you can use rules about when and how credits beyond a desired threshold are to be returned or otherwise used.

Configuration [#configuration]

Automatic handling of excess credits requires creating one or more *Excess Credit Plans*, each of which describe the rules for handling excess credits. Each insured account in the system can be assigned an excess credit plan, and then the rules for that plan will be activated for that account.

An excess credit plan looks like this:

<ApiSchema name="ExcessCreditPlanRef" />

The `disbursementType` property should be set to one of the [disbursement types](/features/billing/disbursements#disbursementConfig) configured in the system.

The `advanceDisbursementTo` property allows you to specify the state the system should advance automatic disbursements to, enabling a step for review or custom processes before the disbursement state is progressed further via API.
This property should be set to `draft`, `validated`, `approved`, or `executed`, and defaults to `executed` if not provided.

Process [#process]

If an excess credit plan is assigned to an account and that plan has `disburseExcess: true`, then each time that account's credit balance is increased, the system will do the following:

* Start with the new credit balance amount.
* Reduce it as indicated with the `excludeDebits` property.
* Create a disbursement to the insured as given by the `disbursementType` property on the plan.
* Advance the disbursement to the state indicated by the `advanceDisbursementTo` property. If not specified, the disbursement is executed and funds distributed.
* The details about the disbursement, including its credit balance source, will be available on the newly-created <ApiLink name="DisbursementResponse">disbursement entity</ApiLink>.

For example, if `excludeDebits` is `allInvoices`, the sum of the unsettled amount for all outstanding invoices should be deducted from the credit balance amount.
If the remainder is greater than zero, create a disbursement with amount equal to this remainder, and advance it to the state specified by `advanceDisbursementTo`.

For accounts with credit balances in multiple currencies, a separate disbursement will be created for each currency.

<Callout>
  It is possible in some cases for the excess amount (as it would be calculated above) to increase even if the credit balance itself does not increase, such as when payments are received while funds remain in a credit balance. Excess credits handling is not automatically triggered in those cases.
</Callout>

Automatic Disbursement Handling [#automatic-disbursement-handling]

Account credit balance amounts are only reserved when a disbursement transitions to an `approved` state.
When `advanceDisbursementTo` is set to `draft` or `validated`, the system-generated disbursement waits for API approval. During this waiting period, the credit balance may change due to payments, reversals, new invoices settled, or other activity.

To accommodate these changes, the following processing rules apply:

* The amount of a disbursement is updated to reflect the current credit balance of the account, with updates occurring at the same frequency as automatic disbursement creation.
* When a disbursement is `approved`, the approved amount is treated as an upper limit. Upon advancement to `executed`, the amount is recalculated and the lesser of the recalculated and approved amounts is distributed.
* If the recalculated amount for a disbursement becomes zero, the disbursement is discarded. A new disbursement will be created when additional funds become available for distribution.
* A disbursement in an `approved` or `executed` state is never modified. A new disbursement will be created when additional funds become available for distribution.
* A disbursement in a `validated` state is validated again each time it is updated.

<Callout>
  The `advanceDisbursementTo` property and its processing apply only to system-generated automatic disbursements and do not affect disbursements created via API.
</Callout>

<span id="NegativeInvoiceProcessing" />

Negative Invoice Processing [#negative-invoice-processing]

Credit amounts may originate from invoices with negative amounts that were generated for a coverage period. By default, these credit amounts are added to the `accountCreditBalance`. Each account can be configured to automatically settle open, unsettled invoices with non-negative amounts using these credit amounts or direct the system to leave such credit amounts in the original negative invoices.

Negative invoice processing logic is executed when invoices are generated.

Configuration [#configuration-1]

Negative invoice handling behavior can be configured through the <ApiLink name="NegativeInvoiceHandlingRef" /> configuration object within each <ApiLink name="ExcessCreditPlanRef" /> configuration object for an account.

The following configuration example highlights the default value for each property:

```json
{
	"excessCreditPlans": {
		"ExamplePlanName": {
			"negativeInvoiceHandling": {
				"automaticallySettleNegativeInvoices": "toCreditBalance", // toOpenInvoices | toCreditBalance | never
				"prioritizeOverlappingCoveragePeriods": true, // true | false
				"targetInvoices": "allOpenInvoices", // overlappingCoveragePeriodsOnly | overlappingCoverageAndEarlier | allOpenInvoices
				"targetInvoicePriority": "smallestFirst", // smallestFirst | earliestFirst | byAmount
				"processingMode": "accountLevel", // accountLevel | policyLevel
				"yieldExcessToCreditBalance": true // true | false
			}
		}
	}
}
```

The `automaticallySettleNegativeInvoices` property indicates whether negative invoice credits should be applied to open invoices, added to the `accountCreditBalance`, or if they should remain within the original negative invoices.

Currently, the system only supports account-level processing. If `processingMode` is set to `policyLevel` instead of `accountLevel`, configuration deployment will fail.

The remaining properties are used to adjust the following processing logic when `automaticallySettleNegativeInvoices` is set to `toOpenInvoices`.

Processing Logic [#processing-logic]

The system executes the following processing logic when `automaticallySettleNegativeInvoices` is set to `toOpenInvoices`.

The system will first fully settle the negative invoice if `yieldExcessToCreditBalance` is set to `true` or partially settle the negative invoice if `yieldExcessToCreditBalance` is set to `false`. Credits will be temporarily stored in an `invoiceCreditBalance`.

If the `invoiceCreditBalance` is `0.00`, processing will stop.

Otherwise, the system will then fetch all open invoices with non-negative amounts, and group them based on the following criteria:

* Group 1: If `prioritizeOverlappingCoveragePeriods` is set to `true`, or `targetInvoices` is set to `overlappingCoveragePeriodsOnly`, add invoices where the `startTime` and `endTime` exactly match the `startTime` and `endTime` of the negative invoice. Otherwise, the group will be empty.
* Group 2: If `targetInvoices` is set to `overlappingCoverageAndEarlier` or `allOpenInvoices`, add invoices where the `startTime` is before the `endTime` of the negative invoice, excluding invoices in group 1.
* Group 3: If `targetInvoices` is set to `allOpenInvoices`, add invoices where the `startTime` is later than or equal to the `endTime` of the negative invoice, excluding invoices in group 1 and group 2.

The system will then sort the invoices in each group based on the following criteria:

* If `targetInvoicePriority` is set to `byAmount`, add invoices where the absolute amount (not the `remainingAmount`) exactly matches the `remainingAmount` of the negative invoice, and sort by \[`remainingAmount`, `startTime`, `generateTime`, `locator`]. Then add the remaining invoices sorted by the same keys.
* If `targetInvoicePriority` is set to `smallestFirst`, sort invoices by \[`remainingAmount`, `startTime`, `generateTime`, `locator`].
* If `targetInvoicePriority` is set to `earliestFirst`, sort invoices by \[`startTime`, `generateTime`, `locator`].

The system will then examine each invoice in order, beginning with group 1, then group 2, then finally group 3, selecting invoices that can be fully or partially paid until the negative invoice amount is exhausted or the system runs out of invoices to process.

The system will then process [credit distributions](/api/billing/credit-distribution) based on the following logic:

* Create a draft `CreditDistribution` with an amount equal to the minimum of `invoiceCreditBalance` and the sum of the remaining amounts for the invoices. Only targets that can consume credit will be included in the distribution. If `yieldExcessToCreditBalance` is set to `true`, the full `invoiceCreditBalance` will be included in the distribution.
* Execute the distribution.
* Continue to create distributions until distribution is complete.

If credit remains, the system will execute the following logic:

* If `yieldExcessToCreditBalance` is set to `true`, keep the remaining credit in the `accountCreditBalance`.
* Otherwise, keep the remaining credit in the negative invoice. The negative invoice will be partially settled.

If no eligible open invoices are found, the full `invoiceCreditBalance` will be added to the `accountCreditBalance`.

<Callout>
  Credits can only be added to an `invoiceCreditBalance` as the result of two possible scenarios: Through automatic negative invoice processing when `automaticallySettleNegativeInvoices` is set to `toOpenInvoices`, or through the reversal of a credit distribution that originated from an `invoiceCreditBalance`.
</Callout>

Reversal [#reversal]

Any `CreditDistribution` that is created as a result of a negative invoice can be reversed, which will unsettle any non-negative `invoiceItems` and invoices. The amount will be added to the `invoiceCreditBalance`, which can be used later to target a different set of non-negative invoices using another `CreditDistribution`.

API Endpoints [#api-endpoints]

The <ApiLink name="settleNegativeOrZeroInvoice" /> API endpoint can be used to manually settle negative invoices. The invoice `state` cannot be `settled`, and the `remainingAmount` must be negative.

<Callout>
  The system does not currently support settling negative invoices by a specific amount. Settled negative invoices cannot be unsettled, but the associated `CreditDistribution` can be reversed.
</Callout>

The <ApiLink name="fetchDebitsForAnInvoice" /> API endpoint can be used to fetch all debits associated with a negative invoice.

API Endpoints [#api-endpoints-1]

See Also [#see-also]

* [Disbursements](/features/billing/disbursements)
* [Credit Balances](/features/billing/credit-balances)
* [Credits from Policy Transactions and Billing Changes](/features/billing/credits-from-policy-transactions)
* [Disbursements API](/api/billing/disbursements)
* [Invoices API](/api/billing/invoices)
* [Credit Distribution API](/api/billing/credit-distribution)


## API Reference

ExcessCreditPlanRef
Properties:
  disburseExcess (boolean, required) — Set to true to enable excess funds handling for the plan.
  disbursementType (string, required) — The type of the disbursement to be automatically created.
  excludeDebits (Enum allInvoices | invoicesAndUnbilledInstallments | none | pastDueInvoices, required) — Which pending debits should be considered for determining how much of the credit to retain
  disbursementThresholds (map<string, number>, required)
  advanceDisbursementTo (Enum draft | validated | approved | executed | reversed | rejected | discarded, required)
  autoApplyExcessToInvoicesEnabled (boolean, required)
  negativeInvoiceHandling (NegativeInvoiceHandlingRef, required)

# Flat Charges



import Image from 'next/image';

Overview [#overview]

Normal charges in Socotra are rate-based, proratable, and controlled by the policy system. For example, a typical "premium" charge can be expressed as a rate such as "$1000 per month", and is linked to an element with a duration, such as a year-long coverage. Consider a typical `RatingItem` construction in this rating plugin code excerpt:

```java
var ratingItem = RatingItem.builder()
    .elementLocator(vehicle.locator())
    .chargeType(ChargeType.Premium)
    .rate(BigDecimal.valueOf(rate))
    .build();
```

Here, the rating item is tied to a "vehicle" element -- in this case, an exposure -- with the amount given as a rate per unit of time. The unit of time is determined by the `durationBasis` (see ["Durations"](/features/financials/durations)), with the length of time determined by the duration of the segment to which the element belongs. Charges are then sent to the billing system for distribution across the invoice stream.

Socotra features "flat charges" to assess charges lacking such an inherent sense of duration. Flat charges are especially useful for various kinds of fees. They can be created through the billing system, placed on an upcoming invoice or on an immediate separate invoice, and reversed, all in isolation from the policy system.

Configuration [#configuration]

Flat charges are declared like other charges in <ApiLink name="ConfigurationRef" />, but are distinguished from "normal" charges with the `handling` property set to `flat`. This is the current charge definition specification:

<ApiSchema name="ChargeRef" />

Unless otherwise specified, charges have a default `handling` of `normal` and `invoicing` of `scheduled`. Flat fees are configured with `handling: flat` and should be specified with `invoicing` values `next` (the default), `immediate`, or `scheduled`. Here's a tabular depiction of the `handling` and `invoicing` combinations:

<Image src="/images/flat-charges-guide/invoicing-handling-combinations.png" alt="invoicing handling combinations" width={450} height={252} unoptimized />

The system will return an error if you attempt to deploy `normal` charges with `invoicing: immediate` or `invoicing: next`.

Flat charges with `invoicing: next` can be configured with `transactionBundlingEnabled: true` to enable [transaction charge bundling](#transaction_flat_charge_bundling) during invoicing. This property will be set to `false` for all charges by default.

A configuration with normal and flat charges might look like this:

```json
"charges": {
    "Premium": {
        "category": "premium"
    },
    "ServiceFee": {
        "category": "fee",
        "handling": "flat",
        "invoicing": "immediate"
    },
    "AdminFee": {
        "category": "fee",
        "handling": "flat",
        "invoicing": "next",
        "transactionBundlingEnabled": true
    }
}
```

Usage [#usage]

Flat charges can be created as part of the [rating plugin](/configuration/plugins/rating) response during transaction pricing, or created directly via the [Flat Charges API](/api/billing/flat-charges).

Flat Charges via Rating [#flat-charges-via-rating]

When you create flat charges through the rating plugin, you set the `amount` on the `RatingItem` instead of the `rate`. If you supply `rate` or `referenceRate`, these will be persisted for reference, but have no functional impact. Here's an example of a flat charge `RatingItem` being created in a rating method:

```java
var feeRatingItem = RatingItem.builder()
                        .elementLocator(quote.locator())
                        .chargeType(ChargeType.flatFeeNext)
                        .amount(new BigDecimal("2.00"))
                        .build();
```

When a transaction is reversed and reapplied, or a post-split segment is created, any flat charges will be stripped out of the new transaction. The original flat charge stands.

If a transaction is invalidated or refused, or is explicitly reversed through the issuance of a reversal transaction, the billing system will reverse the transaction's flat charges.

Flat charges are not affected by cancellation transactions, but can be offset if needed through the creation of new charges.

Flat Charges via API [#flat-charges-via-api]

The [Flat Charges API](/api/billing/flat-charges) can be used to manipulate and view charges, allowing for the creation and invoicing of flat charges independently of the policy system rating process. To inject flat charges into billing, use the <ApiLink name="addCharges" /> endpoint.

Flat charges created by API must have `immediate` or `next` invoicing.
If the flat charge has `invoicing: scheduled` defined within configuration, it will be created with `next` when issued through the API. Any attempt to explicitly set `invoicing: scheduled` within the API request will fail.

<span id="InvoicingBehavior" />

Invoicing Behavior [#invoicing-behavior]

If there are no applicable uninvoiced installments for a flat charge with `next` invoicing, then the charge will be billed as `immediate`.

When determining applicable installments for `next` invoicing, only installments matching the flat charge's currency are considered as candidates for assignment.

The following logic is applied to determine which uninvoiced installments are applicable:

1. If [transaction charge bundling](#transaction_flat_charge_bundling) is enabled and the charge is associated with an issued transaction, only installments originating from the bundled transaction are considered
2. Else, if the charge has a `policyLocator` set, only installments associated with the policy are considered
3. Else, only installments associated with the account are considered

For `immediate` billing, a single new invoice will be created with the following:

1. All flat charges created by the policy transaction or manual action; and
2. Any other flat charges with matching currency that are pending with `next` invoicing.

Every flat charge has a one-to-one association with an invoice item on its invoice unless it has `invoicing: scheduled`, in which case it can be spread across installments.

The billing of flat charges created as part of a policy transaction is not affected by the transaction's effective time when transaction charge bundling is disabled.

The platform uses relevant installment preferences to determine due dates for immediately invoiced flat charges.

Generated early invoices will include all flat charges scheduled for the next invoice when `invoiceThroughTime` is used.

The <ApiLink name="reverseCharges" /> API endpoint creates reversal charges that are invoiced the same way as regular flat charges. They cannot be reversed. When a reversal charge is created, all tags associated with the original charge will be copied and associated with the reversal charge.

<Callout>
  Flat charges that are billed `immediate` and therefore are on their own invoice will not trigger the [autopay process](/features/billing/autopay). These invoices will need to be handled separately. New payment requests can be created for these which can be handled by the [payment execution service](/features/billing/payment-execution-service).
</Callout>

<span id="transaction_flat_charge_bundling" />

Transaction Charge Bundling [#transaction-charge-bundling]

By default, flat charges with `next` invoicing are included on invoices regardless of which transactions the installments originate from. Transaction charge bundling provides the ability to configure charges so they are included only on invoices that bill installments originating from a specific transaction.

Charge bundling is enabled as part of charge type configuration via the <ApiLink name="ChargeRef" /> `transactionBundlingEnabled` attribute. When enabled, charges are bundled with applicable uninvoiced installments originating from the associated transaction. If there are no remaining uninvoiced installments for the transaction, charges are invoiced according to default `next` invoicing behavior, as if bundling were disabled.

Bundling applies during scheduled invoice generation and invoice previews.

For flat charges generated via API with a charge type that has bundling enabled, the transaction to bundle to is specified by the `transactionLocator` provided in the request. If `transactionLocator` is not specified or the provided transaction is in a non-issued state, the charge cannot be bundled and will follow default `next` invoicing behavior.

Flat charges generated by the Rating Plugin are already associated with the transaction that resulted in plugin execution and charge generation, and will be bundled with the associated transaction when bundling is enabled for the charge type.

Delinquency [#delinquency]

If invoices containing only flat charges become past due, and any of the charges reference a `policyLocator`, the corresponding policy (or policies) will enter delinquency.


## API Reference

ChargeRef
Properties:
  displayName (string) [deprecated]
  category (Enum none | premium | tax | fee | credit | invoiceFee | cededPremium | nonFinancial | surcharge, required)
  handling (Enum flat | normal | retention, required)
  invoicing (Enum scheduled | next | immediate, required)
  transactionBundlingEnabled (boolean, required)

# Installment Settings



Overview [#overview]

The billing system receives transactions from the policy system, and with each of these it divides the charges for the transaction into *installments* which are then used to construct invoices. The choices about how it does this are informed by a collection of *settings*, which are based on configuration data and overrides for the policy.

Settings List [#settings-list]

The following settings are supported on the <ApiLink name="InstallmentPlanRef">installment plan</ApiLink>:

* `cadence`: The frequency or pattern of installment creation, such as `fullPay`, `monthly`, `weekly`, etc.
* `maxInstallmentsPerTerm`: For each term, the installment count can be capped by this number. (Note: partial installments to start the term do not apply to this limit.)
* `installmentWeights`: An array of decimal values with the relative weighting for each term. If a weight is not provided, *1* is presumed. For example, if weights for a quarterly cadence are specified as `[3, 2]`, then the weights would be calculated as `[3, 2, 1, 1]`. This means that the first installment would have amounts 50% more than the second, which would have amounts twice the third and fourth.
* `generateLeadDays`: How many days in advance of the installment start time that the invoice for the installment will be automatically created.
* `dueLeadDays`: How many days in advance of the installment start time that the invoice for the installment will become due.
* `anchorMode`: When fixing a date to an anchor for installments (such as *the 5th of the month* or *the second Tuesday of the month*), this specifies whether it's the term or installment start, the invoice generate date, or the due date that is fixed to that anchor.

In addition to the *Plan* settings above, the following *Policy Specific* settings are supported on <ApiLink name="InstallmentPreferences">installment preferences</ApiLink>:

* `anchorTime`: A specific date that is used for alignment. For example, if the `cadence` is `quarterly`, then the anchor time could be March 22, 2024, and the date sequence for installments would be calculated from that; for example: `2024-03-22`, `2024-06-22`, and so on.
* `anchorType`: Aligns the cadence to a specific date, day of month, or day of week, or a combination like *the 3rd Thursday of each month*.
* `dayOfMonth`: For month-based cadences, such as monthly, quarterly, etc., this will anchor to a certain day of the month, and will use the `anchorMode` to determine which date (*generate*, *due*, etc.) is being fixed.
* `dayOfWeek`: For choosing the alignment for `weekly` or `everyOtherWeek` cadences.
* `weekOfMonth`: For use in defining anchoring like "the 3rd Thursday of the month", the `weekOfMonth` would be `3`, *and* the `dayOfWeek` would be `thursday`.
* Settings to override the plan-specific values, such as `maxInstallmentsPerTerm`, are also supported here.

<Callout>
  The `cadence` values of *none*, *thirtyDays*, and *everyNDays* are not currently supported.
</Callout>

Resolving Settings [#resolving-settings]

The system will combine *preferences* and *plans* to determine the actual *settings* used for the policy. The process looks like this:

* Start with the preferences for the quote or policy transaction. For those that aren't specified, fill them in with any preferences stored on the account.

* Then, determine which installment plan is to be used. This is the one on the quote or policy transaction if specified. Otherwise:
  * For quotes, look for a plan on the account, and if not found continue looking on the product, the tenant's default, or the system default in that order.
  * For policy transactions, use the plan that's already in use at transaction's effective time.

* Finally, use the plan's settings to resolve any missing preferences.

Quotes Process [#quotes-process]

Installment plans and individual preferences on quotes resolve to a collection of *installment settings* for the resulting policy.

When a quote becomes billable, the system will do the following:

* First, get the applicable *Installment Plan*:
  * Check the quote's <ApiLink name="InstallmentPreferences" /> and if the `installmentPlanName` is set there, then use that plan.
  * If not, check if the `defaultInstallmentPlan` is set on the <ApiLink name="AccountResponse">account</ApiLink>. If so, use <ApiLink name="InstallmentPlanRef">that</ApiLink>.
  * Then, check if the `defaultInstallmentPlan` is set on the <ApiLink name="ProductRef">product</ApiLink> in configuration. If so, use that.
  * If that's not set, check the tenant's `defaultInstallmentPlan`.
  * Finally, if none of the above are used, the system will default to the built-in `Standard` installment plan.

* Then, with the plan's settings, we update preferences by replacing any that are included in the quote's preferences. In this way, you can override what the plan specifies for that particular quote.

Each of these settings is then persisted on the <ApiLink name="InstallmentSettings" /> for the Installment Lattice.

Quotes Example [#quotes-example]

Presume a quote is created with preferences of:

* `anchorType`: `dayOfMonth`
* `dayOfMonth`: `20`
* `dueLeadDays`: `10`

And also suppose the quote's `product` has a `defaultInstallmentPlan` that looks like this:

* `anchorMode`: `dueDay`
* `dueLeadDays`: `7`
* `generateLeadDays`: `18`

Then the plan's values will be added to preferences for the quote, and the result will be:

* `anchorType`: `dayOfMonth`
* `anchorMode`: `dueDay`
* `dayOfMonth`: `20`
* `dueLeadDays`: `10`
* `generateLeadDays`: `18`

Policy Transactions Process [#policy-transactions-process]

Policy transactions have a different handling mechanism because for all these cases, there already exists a collection of settings that govern billing activity, and those are used as the baseline for additional changes.

To make billing changes, the transaction must have its `triggerBillingChange` property set to `true`. At that point, the `preferences.installmentPreferences` property can be used to specify new setting values that will become effective at the same time as any other changes for the transaction (that is, the changes apply to the policy from the transaction's `effectiveTime` and after, but before that time the settings will remain as they were.)

If `triggerBillingChange` is *not* `true`, any installment preferences on the transaction will be ignored.

Account Preferences [#account-preferences]

Preferences can be stored at the account level in the account's `preferences.installmentPreferences` property. This is useful for cases where the insured wants coordination for invoicing across all their policies. For example, to make all invoices due on the 10th of the month, the installment preferences could look like:

```json
{
	"anchorMode": "dueTime",
	"anchorType": "dayOfMonth",
	"dayOfMonth": 10
}
```

<Callout>
  An upcoming feature for Account-Level Billing will extend this logic to combine installments across policies onto a single stream of invoicing, so that the insured will only be responsible for a single invoice per billing period.
</Callout>

Validation [#validation]

Not all installment settings are compatible with one another. Incompatible settings will cause an error when trying to deploy the configuration.

The rules for the `anchorType` are:

* **dayOfMonth**
  * The `cadence` must be month-based, such as `monthly`, `quarterly`, `semiannually`, or `annually`.
  * `dayOfMonth` is required.
  * `dayOfWeek`, `weekOfMonth`, and `anchorTime` must be *absent*.

* **weekOfMonth**
  * The `cadence` must be month-based, such as `monthly`, `quarterly`, etc.
  * `weekOfMonth` and `dayOfWeek` must have valid non-null values. `weekOfMonth` may *not* be `none`.
  * `dayOfMonth` and `anchorTime` *must* be absent.

* **dayOfWeek**
  * The `cadence` must be week-based, either `weekly` or `everyOtherWeek`.
  * `dayOfWeek` must be specified.
  * `dayOfMonth`, `weekOfMonth`, and `anchorTime` must be *absent*.

* **anchorTime**
  * The `anchorTime` must be a valid `datetime`
  * `dayOfMonth`, `dayOfWeek`, and `weekOfMonth` must be *absent*.

* **none**
  * `dayOfMonth`, `dayOfWeek`, `weekOfMonth` and `anchorTime` must be *absent*.

In addition to the `anchorType` rules, the system will also verify the following:

* `generateLeadDays` must be an integer between `0` and `60` inclusive.
* `dueLeadDays` must be an integer between `0` and `generateLeadDays` inclusive.
* For each value of `installmentWeights`, it must be between `0.1` and `12.0` with a maximum precision of five places after the decimal. Absent weights will be inferred to be `1`.
* `maxInstallmentsPerTerm` must be absent or an integer equal to or greater than `1`.
* `dayOfMonth` must be absent or an integer from `1` to `31` inclusive.
* `dayOfWeek` must be absent or one of `sunday`, `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, or `saturday`.
* `weekOfMonth` must be absent or an integer from `1` to `5` inclusive.

Persistence [#persistence]

After the value for each relevant setting is determined, all the settings are <ApiLink name="fetchInstallmentLatticeSettings">persisted on the installment lattice</ApiLink>.

<Callout>
  Some settings may remain `null`. For example, if `maxInstallmentsPerTerm` is null then the total number of installments will be uncapped.
</Callout>

Default Settings [#default-settings]

The default values for settings are:

* A `fullPay` cadence
* `anchorMode` of `termStartDay`
* `14` for invoice `generateLeadDays`
* `0` for `dueLeadDays`.
* Even `installmentWeights` (all weights are `1`)
* Unlimited `maxInstallmentsPerTerm`.

The `Standard` installment plan is built-in to the system, and uses the above default values. This plan can be configured to override the above defaults if desired.

See Also [#see-also]

* [Installments API](/api/billing/installments)
* [Configuration Deployments API](/api/configuration-and-development/deployments)


# Installment Lattices



Overview [#overview]

The general billing flow is that the policy system will send <ApiLink name="PolicyTransactionResponse">Policy Transactions</ApiLink> to the billing system. The billing system will process the <ApiLink name="ChargeResponse">charges</ApiLink> for the transaction, and divide each into a set of <ApiLink name="InstallmentItem">installment items</ApiLink>, distributed across <ApiLink name="Installment">installments</ApiLink>. These installments are then used to construct invoices.

The *Installment Lattice* is a template that is used determine exactly how to distribute the charges, both in terms of amounts for each installment item (which sum to the amount of the charge), and the timing, as determined by the installments that are created.

Key points to remember are:

* *Installment Lattices* are each contained in a single policy term. On renewal, a new lattice will be created for the new term.
* A single lattice will be used for each term unless it needs to change based on installment plan changes, or changes to the policy start or end time (which would affect the start or end time of one or more terms in the policy.)
* The lattice has *Frames* which are then used to create *Installments* for a transaction.
* Each installment is created by a transaction and is then immutable. When the installment reaches its `generateTime`, it is used to construct an *invoice*. The invoice is the receivable that the insured is then responsible for paying.
* Multiple installments may be used to construct a single invoice.
* The installment sequence may be regular (such as Jan 1 -> Feb 1, Feb 1 -> Mar 1, etc..) or irregular based on the options for installment weighting, caps on the number of installments in a term, and date anchoring which may shift the installment boundaries earlier or later.
* There is a distinction between the *nominal* time range of an installment, which is often tied to a month, like "January 2025," and the *coverage* time range. For example, if the first installment in the term is weighted at 2x compared to following installments, its *coverage duration* will be twice the coverage duration of those following terms, even if the nominal time range is identical.

<Callout>
  The reason for having a separate coverage time slice is so that subsequent transactions that are effective after the term start have installment distribution that is intuitive, with no stray amounts landing on the wrong installment. This can be particularly frustraing and confusing in the case of cancellation, where slight mismatches result in non-zero invoice amounts well past the cancellation time.
</Callout>

Structure [#structure]

A typical installment lattice for a quarterly cadence, billing 14 days in advance, and due dates 2 days in advance, might look like this:

**Installment Lattice - Typical**

|                    | Frame 1 | Frame 2 | Frame 3 | Frame 4 |
| ------------------ | ------- | ------- | ------- | ------- |
| Nominal Start      | Jan 1   | Apr 1   | Jul 1   | Oct 1   |
| Nominal End        | Apr 1   | Jul 1   | Oct 1   | Jan 1   |
| Coverage Start     | Jan 1   | Apr 1   | Jul 1   | Oct 1   |
| Coverage End       | Apr 1   | Jul 1   | Oct 1   | Jan 1   |
| Invoice Generation | Dec 18  | Mar 18  | Jun 17  | Sep 17  |
| Invoice Due        | Dec 30  | Mar 30  | Jun 29  | Sep 29  |

Here, the nominal and coverage time ranges are identical because there are no installment settings that cause coverage to diverge from billing.

If we decided to limit the number of installments in the term to 3, and overweight the first installment by 2x, align the due date to the 15th of the month, and anchor so that the installments fall on the 2nd month of each quarter, we'd get this:

**Installment Lattice - Effect of Multiple Settings**

|                    | Frame 1 | Frame 2 | Frame 3 | Frame 4 |
| ------------------ | ------- | ------- | ------- | ------- |
| Nominal Start      | Jan 1   | Feb 15  | May 15  | Aug 15  |
| Nominal End        | Feb 15  | May 15  | Aug 15  | Jan 1   |
| Coverage Start     | Jan 1   | Mar 20  | Jul 21  | Oct 11  |
| Coverage End       | Mar 20  | Jul 21  | Oct 11  | Jan 1   |
| Invoice Generation | Dec 18  | Feb 1   | May 1   | Aug 1   |
| Invoice Due        | Dec 30  | Feb 13  | May 13  | Aug 13  |

In this case there are only 3 full installments (the first one is shorter and so doesn't count,) and the first installment duration is overweighted which pushes the coverage end out past the nominal end.

Process [#process]

When a new transaction is being processed for billing, the system will do the following for each affected policy term:

* Create a new installment lattice if needed
* Overlay each charge against the lattices' coverage time segments
* Compute the *amount* for each installment item based on the coverage duration in the overlap between charge start/end and frame start/end
* Combine the installment items created by each frame into a single installment
* Set the installment's nominal and coverage start and end times, along with the invoice generate and due times to be the same as the corresponding frame in the lattice.

After this, these new installments are eligible to be invoiced when their respective `generateTime` is reached.

<span id="retrying_failed_billing_jobs" />

Retrying Failed Billing Jobs [#retrying-failed-billing-jobs]

Failed billing jobs can be retried using the <ApiLink name="retryFailedTransactions">Retry Failed Transactions</ApiLink> API endpoint. The system will automatically execute the correct transaction sequence for each retry attempt. The response will only include the first 100 job responses.

If the policy associated with a billing job lacks sufficient information to retry the job, the system will return an exception.

<Callout>
  Jobs are executed asynchronously and may take some time to complete. Avoid excessive retry attempts, and do not retry jobs with a status of `queued` or `running`.
</Callout>

See Also [#see-also]

* [Installment Lattices API](/api/billing/installment-lattices)
* [Jobs API](/api/configuration-and-development/jobs)


# Invoicing



Invoicing is the process of generating invoices from [installments](/features/billing/installments-and-installment-lattices). The invoicing process generates <ApiLink name="InvoiceItemResponse">invoice items</ApiLink> for each invoice based on the <ApiLink name="InstallmentItem">installment items</ApiLink> contained within each installment in an invoice group.

Invoices are generated when the `generateTime` is reached for an installment. Once invoices are generated, they can be paid through standard [payments](/features/billing/payments) or from a [credit balance](/features/billing/credit-balances).

Invoicing Process [#invoicing-process]

Generating Installments [#generating-installments]

When a quote or policy transaction is issued, the system generates a set of installments that sum to the full amount of the billable charges for that transaction. Each installment is specific to that transaction. Installments never contain installment items that relate to more than one transaction.

Grouping Installments [#grouping-installments]

When the `generateTime` is reached for an installment, the system will create one or more invoice groups and add a set of installments to each invoice group based on installment grouping logic and the <ApiLink name="InstallmentGroupingDetails" /> for each <ApiLink name="InvoicingPlanRef" /> configuration object. Each invoice group will be used to generate a corresponding invoice. In most cases, this process will result in only one invoice group and therefore one invoice.

The <ApiLink name="InstallmentGroupingDetails" /> configuration object allows customers to control the following installment grouping logic:

1. Add the installment to a new invoice group. This is the reference installment.
2. Identify eligible installments. Eligible installments are installments that meet all of the following criteria:
   * Installments must be uninvoiced.
   * Installments must have a `generateTime` equal to or earlier than the current time.
   * Installments must relate to the same policy.
   * If account-level billing applies to the policy associated with the installments, all installments associated with other policies with account-level billing are also eligible, as long as they meet all of the previous criteria.
3. If `window = start` or `window = startAndEnd`, add all eligible installments to the invoice group based on the following rules:
   * If `matching = generateTime`:
     * If `window = start`, the `generateTime` must match the `generateTime` of the reference installment.
     * If `window = startAndEnd`, the `generateTime` and `dueTime` must match the `generateTime` and `dueTime` of the reference installment.
   * If `matching = startTime`:
     * If `window = start`, the `startTime` must match the `startTime` of the reference installment.
     * If `window = startAndEnd`, the `startTime` and `endTime` must match the `startTime` and `endTime` of the reference installment.
   * If `matching = all`:
     * If `window = start`, the `generateTime` and `startTime` must match the `generateTime` and `startTime` of the reference installment.
     * If `window = startAndEnd`, the `generateTime`, `dueTime`, `startTime`, and `endTime` must match the `generateTime`, `dueTime`, `startTime`, and `endTime` of the reference installment.
   * If `window = catchup`:
     * Given all eligible installments, identify the new reference installment based on the following rules:
       * If `matching = startTime`, identify the installment with the latest `startTime`. This is the new reference installment.
       * If `matching = generateTime` or `matching = all`, identify the installment with the latest `generateTime`. This is the new reference installment.
     * Add all eligible installments to the invoice group based on the following rules:
       * If `matching = generateTime`, the `generateTime` must be equal to or earlier than the `generateTime` of the new reference installment.
       * If `matching = startTime`, the `startTime` must be equal to or earlier than the `startTime` of the new reference installment.
       * If `matching = all`, the `generateTime` must be equal to or earlier than the `generateTime` of the new reference installment, and the `startTime` must be equal to or earlier than the `startTime` of the reference installment.

<Callout>
  The default value for `matching` is `generateTime`, and the default value for `window` is `startAndEnd`.
</Callout>

Generating Invoice Items [#generating-invoice-items]

The system will then combine all installment items contained within each installment in the invoice group that are associated with the same policy element and with the same charge type into invoice items. For example, there may be three installments, with each containing an installment item for a premium on a vehicle. These three items are combined into a single invoice item that has an amount equal to the sum of the amounts of those items. The `generateTime` will be adjusted, if necessary, to the beginning of the day.

Each invoice item will reflect the `timezone` of its associated policy. Any invoice item generated for an <ApiLink name="addCharges">ad-hoc flat charge</ApiLink> with no `policyLocator` provided in the charge creation request will be set to the tenant's `defaultTimezone`. If all invoice items share the same timezone, the invoice `timezone` will be set to that timezone. Otherwise, the invoice `timezone` will be set to UTC.

Updating Installments [#updating-installments]

The installments are updated so that their `invoiceLocator` refers to the locator of the newly generated invoice. Each installment item is updated so that its `invoiceItemLocator` refers to the locator of the newly generated invoice item that contains its billable amount. This allows users to trace each invoice item back to its corresponding installments, transactions, and charges.

Due Times [#due-times]

Invoices each have a `dueTime` property, which reflects the time that the invoice is expected to be fully settled, usually by having payments applied. If the invoice remains unsettled after this time, then it is past due, and will invoke [delinquency](/features/billing/delinquency), either by being added to an existing delinquency process or by spawning a new delinquency.

The due time will always be adjusted as needed so that invoices are due at the end of the day for the timezone of the invoice. This is calculated by subtracting 1 millisecond from midnight at the end of the day.

If the <ApiLink name="ConfigurationRef">configuration</ApiLink> property `defaultBackdatedInstallmentsBilling` is set to `deferDueDate` and the invoice's `generateTime` is in the past, then the `dueTime` will be advanced by the difference between the `generateTime` and the current time, so that the expected duration between invoice presentation and its due time is preserved.

Invoices can become settled, and then *unsettled* due to a payment becoming reversed. In this case, if the `dueTime` is in the past, the system will behave as if the invoice had become past due in the usual way.

<span id="installmentTiming" />

Updating Installment Timing [#updating-installment-timing]

The <ApiLink name="updateInstallments" /> API endpoint can be used to modify the `generateTime`, `dueTime`, and `autopayTime` of uninvoiced installments. This endpoint does not modify installments that have already been used to generate an invoice.

Here's an example request:

```json
{
	"installmentLocators": [
		"01J5R7B8K3A8WVRNE0G2W7H1ZP",
		"01J5R7B8K3A8WVRNE0G2W7H1ZQ"
	],
	"generateTime": "2026-06-15T00:00:00Z",
	"dueTime": "2026-07-01T00:00:00Z",
	"autopayTime": "2026-06-29T00:00:00Z"
}
```

This endpoint can be used to modify one or more of the specified timing fields for up to 100 installments per request. All installments specified in the request must belong to the same [account](/features/accounts). The `dueTime` and `autopayTime` values, if specified, must be equal to or later than the `generateTime`.

If the request fails for any of the specified installments, no installments will be modified.

<span id="invoiceRendering" />

Invoice Rendering [#invoice-rendering]

Invoice rendering (the creation of a document that reflects the contents of the invoice) can be done by configuring a document to be rendered for the account. This includes both document rendering data and metadata, similar to how [policy documents](/configuration/resources/documents) are managed.

To generate invoice documents:

* Create one or more document resources (either with a template or pre-rendered document) using [resources configuration](/configuration/resources/documents).
* Upload template or rendered document instances for those resources.
* Set the `defaultInvoiceDocument` property in configuration either at the <ApiLink name="ConfigurationRef">global (tenant) level</ApiLink>, or for <ApiLink name="AccountRef">specific account types</ApiLink>.

From this point forward, invoices generated for the specific accounts will be retrievable via the <ApiLink name="fetchInvoiceDocument" /> endpoint.

<span id="invoice-fees" />

Invoice Fees [#invoice-fees]

Socotra provides a convenient way to automatically add [flat fees](/features/billing/flat-charges) to invoices. Such fees can be added to a quote or policy with no prior configuration via the <ApiLink name="updateQuoteInvoiceFeeAmount" /> and <ApiLink name="updatePolicyInvoiceFeeAmount" /> endpoints, respectively.

<Callout>
  Updating a quote invoice fee after quote issuance will have no effect.
</Callout>

You can also designate automatic additions of such fees to invoices. First, configure an invoice fee in <ApiLink name="ConfigurationRef">top-level configuration</ApiLink> by adding an <ApiLink name="InvoicingPlanRef" /> entry to `invoicingPlans`. After that, you may designate a `defaultInvoicingPlan` to take effect for all policies across all accounts. You can also set the `invoicingPlanName` on accounts, which would override the tenant-level `defaultInvoicingPlan`.

Only one such invoice fee may be added to a given invoice, with the following order of precedence:

* The invoice fee set explicitly on the quote or policy via dedicated API endpoints
* The `invoicingPlanName` set on the account
* The tenant-level `defaultInvoicingPlan`

If an invoice consists of charges from two or more policies with conflicting invoice fees, the account's `invoiceFeeHandling` setting will be used to determine the actual invoice fee amount. If `invoiceFeeHandling` is set to `waive`, then no invoice fees will be added to that account's invoices.

When an invoice is generated, an invoice fee will be added with `chargeType: InvoiceFee` and `chargeCategory: invoiceFee`. These charges will not appear in installment listings, but will be visible on invoice previews.

There are two special cases in which an invoice fee will not be added to an invoice, even if all other conditions are met:

1. An invoice of flat charges exclusively
2. A net-zero invoice

Example [#example]

Suppose you would like a $5.00 invoice fee added to all typical invoices. In your top-level configuration, define an invoicing plan and set the default:

```json
{
    // ...,
    "invoicingPlans": {
        "CustomerFee": {
        "displayName": "Customer Fee",
        "invoiceFeeHandling": "max",
        "invoiceFeeAmounts": {
            "USD": 5.00
        }
    },
    "defaultInvoicingPlan": "CustomerFee",
    // ...,
}
```

If you were to deploy this configuration update and issue a policy, you would see the fee amount reflected in invoice summaries, and listed as a distinct <ApiLink name="InvoiceItemResponse" /> in the <ApiLink name="InvoiceResponse" /> like this:

```json
{
	"locator": "01JTNK29A2X5TDZ3Q0W2MYBQ4Z",
	"chargeType": "InvoiceFee",
	"chargeCategory": "invoiceFee",
	"amount": 5.0
}
```

As mentioned above, you could override the default invoice fee plan for an account by setting the `invoicingPlanName` on <ApiLink name="AccountCreateRequest" /> or <ApiLink name="AccountUpdateRequest" />. You can also set an arbitrary invoice fee amount for quotes or policies via the two dedicated endpoints <ApiLink name="updateQuoteInvoiceFeeAmount" /> and <ApiLink name="updatePolicyInvoiceFeeAmount" />.

<span id="InvoiceConsolidation" />

Invoice Consolidation on Cancellation [#invoice-consolidation-on-cancellation]

When a cancellation [transaction](/features/policy-management/policy-transactions) is issued, the system can be configured to consolidate all remaining uninvoiced installments for the cancelled period into the next eligible invoice for that period. If enabled in the configuration, this consolidation logic will also be reflected in invoice [previews](/features/preview-operations). In past versions of the platform, when a cancellation transaction was issued, the system could continue to generate installments with small amounts, such as 1 cent, after cancellation.

All remaining uninvoiced installments for the cancelled period will be included in the consolidated invoice, with the following exceptions:

* Installments covered by a moratorium will not be included.
* If a reinstatement transaction is issued after a policy is cancelled, only installments prior to the reinstatement effective date will be included.

Configuration [#configuration]

This functionality can be configured through the `consolidateInvoicesOnCancellation` field in each <ApiLink name="InvoicingPlanRef" /> tenant [configuration](/configuration/general-topics/deployment) object.

The `consolidateInvoicesOnCancellation` field accepts the following values:

* `all` - All uninvoiced installments for the cancelled period are added to the consolidated invoice when a cancellation transaction is issued. This is the default value.
* `none` - No uninvoiced installments are consolidated when a cancellation transaction is issued. The cancellation invoice only contains the installment that results from the cancellation. All remaining uninvoiced installments will continue to be scheduled as expected based on the configured [installment settings](/features/billing/installment-settings). This effectively disables invoice consolidation on cancellation behavior.
* `future` - Only uninvoiced installments with a `generateTime` equal to or after the time the cancellation transaction issuance is processed are added to the consolidated invoice when a cancellation transaction is issued. All uninvoiced installments with a `generateTime` prior to this time will continue to be scheduled as expected based on the configured [installment settings](/features/billing/installment-settings).

Here's an example configuration featuring 3 separate `invoicingPlans` with different `consolidateInvoicesOnCancellation` values:

```json
{
	"invoicingPlans": {
		"ConsolidateAll": {
			"displayName": "Consolidate all uninvoiced installments on cancellation",
			"consolidateInvoicesOnCancellation": "all"
		},
		"NoConsolidation": {
			"displayName": "No invoice consolidation on cancellation",
			"consolidateInvoicesOnCancellation": "none"
		},
		"ConsolidateFuture": {
			"displayName": "Consolidate future uninvoiced installments only",
			"consolidateInvoicesOnCancellation": "future"
		}
	}
}
```

See Also [#see-also]

* [Installments and Installment Lattices](/features/billing/installments-and-installment-lattices)
* [Invoices API](/api/billing/invoices)
* [Installments API](/api/billing/installments)
* [Payments](/features/billing/payments)
* [Credit Balances](/features/billing/credit-balances)
* [Delinquency](/features/billing/delinquency)
* [Documents Configuration Guide](/configuration/resources/documents)


# Payment Execution Service



import Image from 'next/image';

The payment execution service processes invoice payments through payment providers such as Stripe and Braintree. Payments can be executed automatically using the [Autopay plugin](/configuration/plugins/autopay) or manually using the [Payments API](/api/billing/payments).

<Callout type="warn">
  The payment execution service currently supports [Braintree ](https://www.paypal.com/us/braintree) and [Stripe ](https://stripe.com). Contact your Socotra account representative to request support for additional payment providers.
</Callout>

Payment Lifecycle [#payment-lifecycle]

Payments typically begin in the `draft` state before moving to the `validated` state. However, the Autopay plugin can be configured to create payments that begin in one of the following states: `draft`, `validated`, `requested`, or `posted`.

Once a payment is in the `requested` state, the payment execution service will attempt to execute the payment through a payment provider and [financial instrument](/features/billing/payments#financial-instrument) associated with the [account](/features/accounts) to be charged, and the payment will move to the `executing` state.

If the payment provider successfully executes the payment request, the payment will be moved to the `posted` state, and payments will be distributed according to the targets specified in the payment request. An <ApiLink name="ExternalCashTransactionResponse">external cash transaction</ApiLink> record will also be generated for the payment.

If the payment provider fails to execute the payment request, and a [retry plan](#retry-plan) has been defined, the retry plan will be executed, and the payment will revert to the `requested` state. If the retry plan fails or a retry plan has not been defined, the payment will move to the `failed` state.

Refer to the diagram below for more information on the payment lifecycle.

<Image src="/images/payments/payment-state-flow.png" alt="payment state flow" width={800} height={356} unoptimized />

Setup [#setup]

Follow the instructions below to begin processing payments through the payment execution service.

Create a Default Financial Instrument [#create-a-default-financial-instrument]

The payment execution service requires a default [financial instrument](/features/billing/payments#financial-instrument) associated with the [account](/features/accounts) to be charged.

First, call the <ApiLink name="createFinancialInstrument">Create a Financial Instrument</ApiLink> API endpoint.

Here's an example request:

```json
{
	"externalIdentifier": "example_identifier",
	"institutionName": "Example Bank",
	"instrumentType": "checking",
	"defaultTransactionMethod": "ach",
	"externalAccountNumber": "1234567890",
	"accountLocator": "01JAB5N9X2M7QFZ4YWT8K3HV6R",
	"nickname": "Example Nickname"
}
```

Then call the <ApiLink name="setFinancialInstrumentAsDefault">Set the Default Financial Instrument for a Tenant</ApiLink> API endpoint using the financial instrument that was created in the previous step.

Here's an example URL for this endpoint, since the request body will be empty:

```
POST billing/01JAB5N9X2M7QFZ4YWT8K3HV6R/financialInstruments/01HZX9Y4P6D2W8TBK3F7QJM9RV/setAsDefault?value=true
```

Before payments are posted, they may be in `requested` state. This indicates that the payment should be processed with a transaction with an external financial institution and then distributed according to the payment request's targets. Payments in `requested` state are typically called *Payment Requests*.

Payments can be created in `requested` state either using the [Autopay](/features/billing/autopay) feature, or directly using the <ApiLink name="createPayment" /> API. They will be processed by the payment execution service in the same way.

Add a Payment Provider Configuration [#add-a-payment-provider-configuration]

Call the <ApiLink name="addPaymentProviderConfiguration">Add Payment Provider Configuration</ApiLink> API endpoint. The request details differ based on the payment provider the policyholder is using to make payments.

Braintree [#braintree]

For Braintree, the `paymentServiceProvider`, `merchantId`, `publicKey`, and `privateKey` fields are required. The `paymentServiceProvider` value should be set to "braintreeSandbox" for sandbox environments and "braintree" for production environments.

The `merchantId`, `publicKey`, and `privateKey` values can be found by navigating to the account icon in the upper right corner of the [Braintree dashboard ](https://sandbox.braintreegateway.com), clicking *My User*, then clicking *View Authorizations* under the *API Keys, Tokenization Keys, Encryption Keys* section.

Here's an example request for the <ApiLink name="addPaymentProviderConfiguration">Add Payment Provider Configuration</ApiLink> API endpoint using a Braintree sandbox account:

```json
{
	"paymentServiceProvider": "braintreeSandbox",
	"merchantId": "hfa37hqzhf",
	"publicKey": "3c8zEmhfshd",
	"privateKey": "ZzFe7v7vcd"
}
```

Stripe [#stripe]

For Stripe, the `paymentServiceProvider` and `secretKey` fields are required. The `paymentServiceProvider` value should be set to "stripeTest" for sandbox environments and "stripe" for production environments.

The `secretKey` value can be found by navigating to the *Developer* tab in the lower left corner of the [Stripe dashboard ](https://dashboard.stripe.com) and clicking *API keys*.

Socotra will automatically create a webhook configuration in Stripe after validating payment provider credentials. To view webhook configurations in Stripe, navigate to the *Developer* tab, then click *Webhooks*.

<Callout type="warn">
  Do not edit or delete webhook configurations in Stripe.
</Callout>

Here's an example request for the <ApiLink name="addPaymentProviderConfiguration">Add Payment Provider Configuration</ApiLink> API endpoint using a Stripe sandbox account:

```json
{
	"paymentServiceProvider": "stripeTest",
	"secretKey": "3c8zEmhfshd"
}
```

Add Payment Execution Configuration for Financial Instrument [#add-payment-execution-configuration-for-financial-instrument]

Call the <ApiLink name="addPaymentExecutionConfigurationForFinancialInstrument">Add Payment Execution Configuration for Financial Instrument</ApiLink> API endpoint using the `paymentProviderLocator` from the payment provider configuration that was created in the previous step.
Payment execution configurations contain payment method tokens required to execute payment requests on behalf of policyholders.

The `offlinePaymentToken` refers to the *Payment Method Token* in Braintree and the *Payment Method ID* in Stripe.

The *Payment Method Token* can be found in Braintree by navigating to the *Transactions* tab, searching for a transaction, clicking the transaction ID, and then locating the *Payment Method Token* field under the *Payment Information* section.

The *Payment Method ID* can be found in Stripe by navigating to the *Transactions* tab, clicking a transaction, then looking for the *ID* field under the *Payment Method* section.

Here's an example request for the <ApiLink name="addPaymentExecutionConfigurationForFinancialInstrument">Add Payment Execution Configuration for Financial Instrument</ApiLink> API endpoint:

```json
{
	"paymentProviderLocator": "01M4QZ7X2Y8P5K9B0R3F6T1VJS",
	"offlinePaymentToken": "j2fd9fhHyeNHe32"
}
```

<Callout>
  The details of the payment providers and tokens are managed in a separate service in order to facilitate [PCI-Compliance ](https://listings.pcisecuritystandards.org/assessors_and_solutions/vpa_agreement). Please review Socotra's [PCI Compliance Statement](/features/security/pci-compliance-statement) for more information.
</Callout>

<span id="retry-plan" />

Retry Plans [#retry-plans]

Retry plans contain the following properties:

* `attempts`: The maximum number of attempts to execute a payment request
* `hoursBetweenAttempts`: How long to wait between attempts

The retry plan can be set in any of the following places, and the system will go through this list in order until it finds a plan:

* The payment
* The <ApiLink name="FinancialInstrumentResponse">financial instrument</ApiLink>
* The account
* The default retry plan defined in the tenant <ApiLink name="ConfigurationRef">configuration</ApiLink>

While the payment is awaiting a retry, you can manually override the process using the following API endpoints:

* Use the <ApiLink name="executePayment" /> API endpoint to execute a payment manually
* Use the <ApiLink name="postPayment" /> API endpoint to update the payment state to `posted`
* Use the <ApiLink name="failPayment" /> API endpoint to indicate that the payment cannot be processed
* Use the <ApiLink name="cancelPayment" /> API endpoint to indicate that the payment is no longer needed
* Use the <ApiLink name="updatePayment" /> API endpoint to manually change the `nextRequestTime` to retry sooner or later than scheduled

<Callout>
  The <ApiLink name="executePayment" /> API endpoint can also be used to move a payment from the `requested` state to the `validated` state without waiting for the `autopayTime`.
</Callout>

Refer to the diagram below for more information on the retry process.

<Image src="/images/autopay/autopay-payment-request-flow.png" alt="autopay payment request flow" width={800} height={345} unoptimized />

<span id="payment-execution-post-processing-plugin" />

Payment Post-Processing Plugin [#payment-post-processing-plugin]

After a payment execution is attempted, the system will execute the Payment Post-Processing Plugin. See the [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing) feature guide for more information.

Execution Log [#execution-log]

The history of execution attempts is maintained in the `executionLog` property for each <ApiLink name="PaymentResponse">payment</ApiLink>.

Here's an example of a log entry:

<ApiSchema name="PaymentRequestExecutionLogItem" />

See Also [#see-also]

* [Payments](/features/billing/payments)
* [Autopay](/features/billing/autopay)
* [Payments API](/api/billing/payments)
* [Payment Execution API](/api/billing/payment-execution)
* [Payment Post-Processing Plugin](/configuration/plugins/payment-post-processing)
* [Financial Instruments and External Cash Transactions API](/api/billing/financial-instruments)


## API Reference

PaymentRequestExecutionLogItem
Properties:
  paymentRequestLocator (ulid, required)
  paymentRequestState (Enum pending | completed | failed | error, required)
  requestTime (datetime)
  transactionId (string)
  note (string)
  data (map<string, object>, required)

# Payment Shortfall Handling



Overview [#overview]

On occasion, customers will make payments towards invoices with amounts that are near to, but slightly less than, the amount needed to settle an invoice. You can use *Shortfall Credits* to automatically settle these invoices when the shortfall amount is less than what would justify the effort of collecting the difference.

Configuration and Plans [#configuration-and-plans]

Shortfall tolerances are configured in <ApiLink name="ShortfallTolerancePlanRef">Shortfall Tolerance Plans</ApiLink>, and each <ApiLink name="AccountResponse">Socotra Account</ApiLink> can be assigned a plan. For those accounts that aren't given a plan, each product configuration may specify a plan, and the default shortfall tolerance plan is configured at the tenant level.

The shortfall thresholds are specified in the `currencyTolerances` property of the plan. This property has type `map<string, number>`, and the key for each threshold is a string that specifies the currency, such as `USD` or `CAN`.

So the configuration might look something like this:

```json
{
  "shortfallTolerancePlans": {
    "basicPlan": {
      "USD": 1.00,
      "CAD": 1.50,
      "EUR": 0.80
    },
    "nonStandardPlan": {
      "USD": 0.20,
      "CAD": 0.30,
      "EUR": 0.15
  }
}
```

In this case, customers assigned the `basicPlan` are treated more leniently than those assigned the `nonStandardPlan`.

<Callout>
  If a shortfall plan does not contain the currency for a given invoice, then shortfall credits will not be generated for that invoice.
</Callout>

Plan Selection [#plan-selection]

When a plan is to be identified for an account, the system will check the `shortfallTolerancePlanName` on the <ApiLink name="AccountResponse">account</ApiLink>. If there is none, it will then check each product being billed on the invoice being processed to check for a `defaultShortfallTolerancePlan`. If none exist, then the `defaultShortfallTolerancePlan` at the tenant level will be used. If no plans are found, or the shortfall tolerance for the given invoice's currency is zero, then shortfall processing will not be performed.

Application [#application]

When a payment is made on an invoice but the invoice remains unsettled, the system will check to see if all the following are true:

* There is a shortfall tolerance plan available to the account (either specified directly on the account, or on the product or tenant)
* The currency for the invoice is represented on the shortfall plan
* The remaining unsettled amount is less than or equal to the specified tolerance

If all the conditions are met, then the system will generate a shortfall credit in the amount of the shortfall, and apply the credit to the invoice. The invoice will then be settled. If the payment's amount is less than the unsettled amount of the invoice minus the shortfall plan threshold, then no credit will be generated.

The new <ApiLink name="ShortfallCreditResponse">shortfall credit's</ApiLink> locator will be stored in the <ApiLink name="PaymentResponse">payment's</ApiLink> `shortfallCreditLocators` array.

The shortfall credits themselves (not just the locators) for a payment can be retrieved with the <ApiLink name="listShortfallCredits" /> API endpoint.

Each shortfall credit will be a credit of type `shortfallWriteoff`.

<Callout>
  If more than one invoice is targeted by the payment, the thresholds are applied *per invoice*. This means the total shortfall credit amount may exceed the specified threshold for these payments. This is true for typical payments that target more than one invoice within a single account, and also for [Aggregate Payments](/features/billing/payments#aggregate-payments).
</Callout>

Payment Reversal [#payment-reversal]

If a payment that created a shortfall credit is reversed, then that credit will be reversed as well, and the unsettled amount on the invoice will revert to the amount before the payment was made (assuming no other payments or credits have been applied or reversed.)

See Also [#see-also]

* [Payments Feature Guide](/features/billing/payments)
* [Payments API](/api/billing/payments)


# Payments



import Image from 'next/image';

Overview [#overview]

The Socotra Payments system handles all aspects of payment management in conjunction with an external payment gateway that executes the actual financial transaction with a financial institution or payments service provider. It consists of the following components:

* **Payments**, which are the actual entity that records the creation, posting, etc. for insureds' payments
* **Financial Instruments**, which are saved payment methods and references at the [Account](/features/accounts) level. Insureds may have a number of credit cards, bank accounts, etc. saved, and any of these can be used as a reference when creating payments.
* **External Cash Transactions**, which are a record of a particular financial transaction that results in funds flowing into the system. Each payment stores information in an external cash transaction, which in turn may reference a financial instrument if it was used for the payment.
* **Payment Distribution**, which contains data about the targets to which the payment is applied.
* **Payment Reversals**, which may exist when a payment fails and must be unallocated due to error, non-sufficient funds, etc.
* **Payment Requests**, which are generated as part of the AutoPay process to manage initiation and error handling for pre-scheduled payments.

Like other configurable entities, payments can be extended with [extension data](/configuration/data-extensions/overview).

Automation for payment handling is detailed in the [Autopay](/features/billing/autopay) and [Payment Execution Service](/features/billing/payment-execution-service) topics.

Payment State Flow [#payment-state-flow]

Payments have a typical state flow from `draft`, to `validated`, and then `posted`.

* Only `draft` payments may be edited.
* `validated` payments may be <ApiLink name="resetPayment">reset</ApiLink> back to `draft`, where they can once again be edited.
* Once posted, payments may become `reversed`.
* If they haven't yet been posted, they may be `discarded`.

When the payment is `posted`, an accounting transaction will be created to debit Cash and credit the payment itself. Then the payment will be distributed, debiting the payment and crediting individual payment target.

When the payment reaches `posted` state, it will be distributed based on its targets. Targets can be either specific invoices, invoice items, or an account, and each target can have a specified `amount`. See [payment-distribution](#payment-distribution), below.

The state flow includes other states that are used in [autopay](/features/billing/autopay) and [automatic payment execution](/features/billing/payment-execution-service). The full flow looks like this:

<Image src="/images/payments/payment-state-flow.png" alt="payment state flow" width={800} height={356} unoptimized />

<span id="financial-instrument" />

Financial Instruments [#financial-instruments]

Accounts have an array of <ApiLink name="FinancialInstrumentResponse">financial instruments</ApiLink>, each of which can store information like:

* `externalIdentifier` to store a lookup ID or token for data in an external system
* `institutionName`, for the credit card or bank name
* `instrumentType`, such as `checking`, `savings`, `creditCard`, etc.
* `defaultTransactionMethod`, such as `eft`, `ach`, `cash`, etc.
* `externalAccountNumber`
* `accountLocator`
* `nickname`, for human identification of the instrument when selecting from a list
* `expirationTime`, an optional time

Payments can optionally reference specific financial instruments or use the account's default instrument upon creation.

External Cash Transactions [#external-cash-transactions]

Payments are not directly associated with financial instruments. If a payment references a financial instrument, this reference is reflected within the associated <ApiLink name="ExternalCashTransactionResponse">external cash transaction</ApiLink>.

An external cash transaction is generated upon the creation of each payment. It may store the following information based on the data provided in the <ApiLink name="PaymentCreateRequest">payment creation request</ApiLink>:

* `financialInstrumentLocator`
* `transactionMethod`, such as `eft`, `ach`, `cash`, etc.
* `transactionNumber`, an optional reference to the external gateway's transactions ID

The `financialInstrumentLocator` is set to the value from the payment creation request if provided, or the default instrument for the associated account when `useDefaultFinancialInstrument` is set to `true`.

The `transactionMethod` is set to the value from the payment creation request if provided, or the associated financial instrument's default method, or `standard` if there is no associated financial instrument.

<span id="payment-distribution" />

Payment Distribution [#payment-distribution]

When a payment is ready for distribution, the system will:

* Based on the `targets`, find all the unsettled invoice items directly associated with that target. For example, if the target is a specific invoice, it will gather all the unsettled invoice items for that invoice.
* Order the invoice items ascending by their `dueTime` (i.e. the `dueTime` of the invoice that contains it.)
* If any targets have an amount specified, distribute to these targets up to the amounts, and then distribute any remaining amounts to all targets.
* Within each `dueTime` group, order the invoice items by invoice locator. This will tend to fully pay some invoices rather than partially pay all invoices if there's a shortfall.
* Create a credit item for each invoice item (with amount equal to the item's unsettled amount) until the amount of the credit is exhausted or no more invoice items remain.
* If the total credit is for less than the sum of the items and the last remainder is less than the unsettled amount of the last invoice item that can be paid, the system will apply all of the remaining credit to that invoice item, leaving it not fully settled.
* If there are sufficient invoice items, the credit will always be fully consumed, regardless of the granularity of the invoice item amounts.
* If there is remaining unapplied credit, the remainder will be transferred the remaining amount to the account's credit balance.

<Callout>
  After distribution, the payment will always be fully distributed. There is no provision for a "partially distributed" payment.
</Callout>

<Callout type="warn">
  Payments cannot be distributed to [Invoices](/features/billing/invoicing) or [Credit Balances](/features/billing/credit-balances) belonging to other customer accounts.
</Callout>

Payment Reversals [#payment-reversals]

A payment may be reversed. It can't be reversed more than once, and there isn't a notion of “reversing the reversal.” If a payment was reversed in error, it will have to be recreated.

Payments that have been reversed can have an optional `reversalReason`, which can be set to a value to document the context of the reversal, including whether the insured was at-fault for the payment being reversed.

When a payment is reversed, the system will offset all of the payment items associated with the payment with the addition of equal-and-opposite payment items associated with the reversal. Similar offsetting will claw back any amounts from the payment to credit balances. This could cause the credit balance to become negative.

<Callout>
  Reversal could cause invoices that were settled to become unsettled, and potentially initiate delinquency if the invoice's due time is in the past. If there is a delinquency that is caused by the reversal, the clock will start as of the time of the reversal. The system does not try to determine what *would* have happened if the payment hadn't ever been created.
</Callout>

<span id="aggregate-payments" />

Aggregate Payments [#aggregate-payments]

Aggregate payments bring additional flexibility to payment targets, making it possible for a payment to span multiple accounts while still making it easy to trace detailed credit flows through the system.

As the name implies, an aggregate payment comprises subpayments. Both aggregate payments and subpayments are <ApiLink name="PaymentResponse">payment objects</ApiLink>. When creating an aggregate payment, you may specify targets that span accounts, but when you post the aggregate payment, you will see subpayments that in turn distribute to those targets. You cannot create subpayments that you manually add to an aggregate; instead, you rely on the system to create subpayments for you, freeing you to focus on the intended payment distribution.

Example [#example]

Suppose there are accounts A and B in the system, each of which has a policy with outstanding invoices of $1000. With a received payment of $4000, you opt to settle invoices on both accounts, with the remaining $2000 distributed to account credit balances. You could create and post an aggregate <ApiLink name="PaymentCreateRequest" /> like this:

```json
{
	"amount": 4000,
	"data": {
		"payerFirstName": "John",
		"payerLastName": "Smith",
		"accountNumber": "1234566",
		"institution": "Big Bank",
		"note": "payment"
	},
	"paymentMode": "aggregate",
	"targets": [
		{
			"containerLocator": "01JQ9ZHGSHX7XCG5HX45SZQ17Y",
			"containerType": "invoice",
			"amount": 1000
		},
		{
			"containerLocator": "01JQ9ZQ6HYY5VZMWTA0VA4BB75",
			"containerType": "invoice",
			"amount": 1000
		},
		{
			"containerLocator": "01JQ9ZPCMKTRTBXTHJNQQFTRPA",
			"containerType": "account",
			"amount": 1000
		},
		{
			"containerLocator": "01JQ9ZGE4HY3BGBDWZGCPZN0ZA",
			"containerType": "account",
			"amount": 1000
		}
	],
	"type": "StandardPayment"
}
```

Which, upon posting, would result in a response like the following - note the creation of subpayments:

```json
{
	"locator": "01JQ9ZZPNFM3WERZVGG7QK2T31",
	"paymentState": "posted",
	"type": "StandardPayment",
	"currency": "USD",
	"amount": 4000.0,
	"remainingAmount": 0.0,
	"data": {
		"accountNumber": "1234566",
		"institution": "Big Bank"
	},
	"createdAt": "2025-03-26T19:48:35.119922Z",
	"createdBy": "dc68c494-6918-487a-bf08-58c2983175dc",
	"targets": [
		{
			"containerLocator": "01JQ9ZHGSHX7XCG5HX45SZQ17Y",
			"containerType": "invoice"
		},
		{
			"containerLocator": "01JQ9ZQ6HYY5VZMWTA0VA4BB75",
			"containerType": "invoice"
		},
		{
			"containerLocator": "01JQ9ZPCMKTRTBXTHJNQQFTRPA",
			"containerType": "account"
		},
		{
			"containerLocator": "01JQ9ZGE4HY3BGBDWZGCPZN0ZA",
			"containerType": "account"
		}
	],
	"externalCashTransactionLocator": "01JQ9ZZPNTHN3GXWGBV41S0C5Q",
	"postedAt": "2025-03-26T19:48:45.819075301Z",
	"subpayments": [
		{
			"subpaymentLocator": "01JQA0015BBZ4KK68WVKRTNABN",
			"amount": 2000.0 // for account A, the sum of the invoice amount and account credit
		},
		{
			"subpaymentLocator": "01JQA0015HX93NJX29JJV2454W",
			"amount": 2000.0 // for account B, the sum of the invoice amount and account credit
		}
	],
	"paymentMode": "aggregate"
}
```

Each subpayment record can be examined as a <ApiLink name="PaymentResponse" />, with all corresponding credit distributions working just as they do for any other payment.

See Also [#see-also]

* [Autopay](/features/billing/autopay)
* [Payment Execution Service](/features/billing/payment-execution-service)
* [Payments](/api/billing/payments)
* [Financial Instruments](/api/billing/financial-instruments)


# Retention Charges



import Image from 'next/image';

Overview [#overview]

Retention charges are additional charges applied during a cancellation transaction to adjust the final amount retained for a policy. These charges may be positive to increase the amount retained or negative to decrease the amount retained.

Common use cases include:

* **Minimum Earned Premiums** - ensuring a minimum amount is retained to cover policy issuance costs
* **Short-Rate Penalties** - retaining additional amounts as a penalty for early cancellation by the insured
* **Custom Fee or Refund Requirements** - implementing other conditional fees or refunds based on custom business rules

Retention charges are fixed-amount, non-proratable charges that are not derived from rate-based calculations, making them conceptually similar to [Flat Charges](/features/billing/flat-charges).

Retention charges are automatically created by the [Cancellation Plugin](/configuration/plugins/cancellation) during cancellation transaction pricing.

Configuration [#configuration]

Retention charges are declared like other charges in <ApiLink name="ConfigurationRef" />, but are distinguished by having their `handling` property set to `retention`.

This is the current charge definition specification:

<ApiSchema name="ChargeRef" />

Retention charges are configured with `handling: retention` and should be specified with `invoicing: next`. See this [guide](/features/billing/flat-charges) for more information on configuring `normal` or `flat` charges.

Here's a tabular depiction of the `handling` and `invoicing` combinations:

<Image src="/images/retention-charges-guide/invoicing-handling-combinations-v2.png" alt="invoicing handling combinations v2" width={450} height={407} unoptimized />

The system will return an error if you attempt to deploy `retention` charges with `invoicing: scheduled` or `invoicing: immediate`.

Retention charges can be configured with `transactionBundlingEnabled: true` to enable [transaction charge bundling](#transaction_retention_charge_bundling) during invoicing. This property will be set to `false` for all charges by default.

A configuration with `normal` and `retention` charges might look like this:

```json
"charges": {
    "Premium": {
        "category": "premium",
        "handling": "normal",
        "invoicing": "scheduled"
    },
    "MinimumPremium": {
        "category": "premium",
        "handling": "retention",
        "invoicing": "next"
    },
    "ShortRate": {
        "category": "fee",
        "handling": "retention",
        "invoicing": "next",
        "transactionBundlingEnabled": true
    }
}
```

Like normal or flat charges, any element that will be associated with a retention charge must declare that charge type in its `charges` list within configuration.

For example, a configuration allowing normal and retention charges to be associated with a `CommercialAuto` element would look like this:

```json
"elements": {
    "CommercialAuto": {
        "charges": [ "Premium", "MinimumPremium" ]
    }
}
```

This ensures that retention charges created during cancellation can be associated correctly with the configured element.

Usage [#usage]

Retention charges are created automatically by the [Cancellation Plugin](/configuration/plugins/cancellation) during cancellation transaction pricing.

The plugin evaluates the system-generated prospective cancellation charges and can output additional retention charges that represent increases or decreases in the amount retained.

Retention Charges via Cancellation Plugin [#retention-charges-via-cancellation-plugin]

When you create retention charges through the cancellation plugin, you set the `amount` on the `RatingItem` instead of the `rate`. If you supply `rate` or `referenceRate`, these will be persisted for reference, but have no functional impact. Here's an example of a retention charge `RatingItem` being created in a cancellation method:

```java
var minPremiumRatingItem = RatingItem.builder()
                        .elementLocator(policy.locator())
                        .chargeType(ChargeType.MinimumPremium)
                        .amount(new BigDecimal("25.00"))
                        .build();
```

Retention charges are fully reversed by the policy system when a reinstatement transaction is issued, regardless of whether or not there is a gap between the cancellation and reinstatement. This will result in reversal charges being generated as part of the reinstatement charges that cancel out the retention charges.

When a cancellation transaction is explicitly reversed through the issuance of a reversal transaction, the billing system will reverse the transaction's retention charges.

Invoicing Behavior [#invoicing-behavior]

Retention charges are billed according to `invoicing: next` behavior, meaning they will be included on the next invoice containing applicable uninvoiced installments.

If there are no applicable uninvoiced installments for a retention charge, then the charge will be billed as `immediate`.

When determining applicable installments for `next` invoicing, only installments matching the retention charge's currency are considered as candidates for assignment.

The following logic is applied to determine which uninvoiced installments are applicable:

1. If [transaction charge bundling](#transaction_retention_charge_bundling) is enabled, only installments originating from the bundled cancellation or reinstatement transaction are considered
2. Else, if the charge has a `policyLocator` set, only installments associated with the policy are considered
3. Else, only installments associated with the account are considered

For `immediate` billing, a single new invoice will be created which will include all retention charges created as part of the cancellation or reinstatement transaction pricing.

Generated early invoices will include all retention charges scheduled for the next invoice when `invoiceThroughTime` is used.

<Callout>
  Retention charges that are billed `immediate` and therefore are on their own invoice will not trigger the [autopay process](/features/billing/autopay). These invoices will need to be handled separately. New payment requests can be created for these which can be handled by the [payment execution service](/features/billing/payment-execution-service).
</Callout>

<span id="transaction_retention_charge_bundling" />

Transaction Charge Bundling [#transaction-charge-bundling]

By default, flat and retention charges with `next` invoicing are included on invoices regardless of which transactions the installments originate from. Transaction charge bundling provides the ability to configure charges so they are included only on invoices that bill installments originating from the associated transaction.

Charge bundling is enabled as part of charge type configuration via the <ApiLink name="ChargeRef" /> `transactionBundlingEnabled` attribute. When enabled, retention charges are bundled with applicable uninvoiced installments originating from the cancellation or reinstatement transaction that resulted in their creation. If there are no remaining uninvoiced installments for the cancellation or reinstatement transaction, charges are invoiced according to default `next` invoicing behavior, as if bundling were disabled.

Bundling applies during scheduled invoice generation and invoice previews.

Retention charges generated by the Cancellation Plugin with bundling enabled will be bundled with the cancellation transaction that triggered Cancellation Plugin execution and charge generation. Similarly, reversed retention charges generated during reinstatement with bundling enabled will be bundled with the reinstatement transaction that triggered Rating Plugin execution and charge generation.

Delinquency [#delinquency]

If invoices containing only retention charges become past due, the corresponding policy will enter delinquency.


## API Reference

ChargeRef
Properties:
  displayName (string) [deprecated]
  category (Enum none | premium | tax | fee | credit | invoiceFee | cededPremium | nonFinancial | surcharge, required)
  handling (Enum flat | normal | retention, required)
  invoicing (Enum scheduled | next | immediate, required)
  transactionBundlingEnabled (boolean, required)

# Write-Offs



Overview [#overview]

There are occasions where an individual or set of invoices may be deemed uncollectible, but still need to become settled so that they don't remain on the system, forever in an incomplete state. Additionally, use cases such as fee discounts at the invoice item level require an even more precise degree of credit handling. **Write-Offs** allow users to write off entire invoices, specific invoice items or partial amounts.

Key Capabilities [#key-capabilities]

* Target either full invoices or individual invoice items.
* Specify a custom amount per target, or allow the system to compute the unsettled amount.
* Supports partial write-offs of invoice items.
* Multiple targets per write-off are supported, processed in the order provided.
* Write-offs propagate to Data Lake for downstream reporting.
* A full reversal capability is supported via a simple `POST` call.

Accounting Behavior [#accounting-behavior]

Granular write-offs follow the same accounting rules as traditional full invoice write-offs. Each target is processed independently and credited accordingly.

API Usage [#api-usage]

Create a write-off by specifying one or more `invoice` or `invoiceItem` targets. All targets must belong to the same account and use the same currency.

<ApiEndpoint name="writeOff" title="Create Write-Off" />

<ApiSchema name="WriteOffRequest" />

<ApiSchema name="WriteOffTarget" />

<Callout>
  Invoices can also be directly targeted for write off via their locator, however this approach is limited in that it can target only the remaining balance of the invoice, and in its entirety.
</Callout>

<ApiEndpoint name="writeOffInvoice" title="Write-Off an Invoice" />

Reversal Support [#reversal-support]

Write-offs can be fully reversed by calling the <ApiLink name="reverseWriteOff">Reverse a Write-Off</ApiLink> API endpoint, which will unsettle all credits across all `invoice` and `invoiceItem` targets. Partial reversals are not supported.

Only manually created write-offs with a `creditType` of `writeOff` can be reversed. Shortfall write-offs cannot be reversed directly. If you need to reverse a shortfall write-off, you must reverse the parent <ApiLink name="reversePayment">payment</ApiLink> or parent <ApiLink name="reverseCreditDistribution">credit distribution</ApiLink>, which will also reverse the shortfall write-off.

<ApiEndpoint name="reverseWriteOff" title="Reverse a Write-Off" />

Limitations [#limitations]

* **Maximum targets:** A request can include up to 100 targets. Requests exceeding this limit will be rejected.

* **Same account constraint:** All targets (`invoice` and `invoiceItems`) must belong to the account specified in the request. Cross-account targeting is not allowed.

* **Same currency:** All targets in a request must have the same currency.

* **No duplicate targets:** Each target must be unique. Duplicate `invoice` or `invoiceItem` entries within the same request will result in an error.

* **Disjoint targets:** `invoiceItems` cannot be targeted individually if they are already indirectly included via their parent invoice in the same request. Each target must be independent.

* **Valid types only:**
  * Only `invoice` and `invoiceItem` container types are supported.
  * Other types (e.g., account) are not valid targets.

* **Target must exist:** All provided target locators must correspond to existing invoices or invoice items; otherwise, the request will fail.

* **Amount must be valid:** The amount specified per target must be positive and non-zero. The amount must not exceed the target's remaining unsettled amount.

* **Settled items cannot be written off:** Targets that are already fully settled are not eligible for write-off.

* **Targets are required:** A write-off request must include at least one valid target.

See Also [#see-also]

* [Write-Offs API](/api/billing/write-offs)


## API Reference

POST /billing/{tenantLocator}/writeOffs — writeOff
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Request body (WriteOffRequest):
Responses:
  200 WriteOffResponse — OK

PATCH /billing/{tenantLocator}/invoices/{locator}/writeOff — writeOffInvoice
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

PATCH /billing/{tenantLocator}/writeOffs/{locator}/reverse — reverseWriteOff
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
  locator (ulid, path, required)
Responses:
  200 WriteOffResponse — OK

WriteOffRequest
Properties:
  accountLocator (ulid, required)
  targets (WriteOffTarget[], required)

WriteOffTarget
Properties:
  containerLocator (ulid, required)
  containerType (Enum invoice | account | subpayment | invoiceItem, required)
  amount (number)

# Document Consolidation



Document Consolidation is a feature that supports the creation of Policy Packets - a combination of multiple documents in a single, organized PDF.

Any document associated with the policy can be included in a policy packet, including any rendered externally and then attached to the policy or quote.

You can configure numerous policy packets, and leverage additional features such as a cover page, table of contents, and page numbering.

To do so, set up the top-level <ApiLink name="ConsolidatedDocumentConfigRef" /> configuration, adding the name of your consolidated document configuration to the `documents` set for applicable products' (<ApiLink name="ProductRef" />). The consolidated document trigger will match the latest trigger time of its subdocuments (those enumerated in the `consolidatedDocuments` array).

Subdocuments continue to be produced independently of the consolidated document, and can be fetched separately from the consolidated document.

Example [#example]

Suppose you have already defined a "WelcomePage" document and a "LegalDisclosures" document, and would like the two to be produced as a single "DocPackage" set. You would define "DocPackage" in <ApiLink name="ConsolidatedDocumentConfigRef" /> like this:

```json
{
	"DocPackage": {
		"consolidatedDocuments": ["WelcomePage", "LegalDisclosures"]
	}
}
```

And then add "DocPackage" to the applicable <ApiLink name="ProductRef" /> `documents` array:

```json
{
	"displayName": "Commercial Auto",
	// ...,
	"documents": ["WelcomePage", "LegalDisclosures", "DocPackage"]
	// ...,
}
```

You'll see the consolidated document produced as a distinct entity from its subdocuments, triggered at the same time as the latest trigger among the documents in its subdocument set (i.e., a consolidated document's trigger is inferred from its subdocuments).

If the above "DocPackage" set had been produced at quote issuance, you could expect to see a result like the following -- note that the consolidated document references the subdocuments, and each subdocument references the consolidated document in `consolidatedTo`:

```json
[
	{
		"locator": "01JT3P746EMZZ8J7KSMPQS36NZ",
		"referenceLocator": "01JT3P6QK4R4VXNJKR0TYRYZ1F",
		"referenceType": "quote",
		"staticName": "DocPackage",
		"documentInstanceState": "ready",
		// ...,
		"external": false,
		"consolidatedFrom": [
			"01JT3P6TNR1A0EWF5P83AEDJNG",
			"01JT3P6TNSTP758DG9CTV63PJZ"
		]
	},
	{
		"locator": "01JT3P6TNR1A0EWF5P83AEDJNG",
		"referenceLocator": "01JT3P6QK4R4VXNJKR0TYRYZ1F",
		// ...,
		"consolidatedTo": ["01JT3P746EMZZ8J7KSMPQS36NZ"]
	},
	{
		"locator": "01JT3P6TNSTP758DG9CTV63PJZ",
		"referenceLocator": "01JT3P6QK4R4VXNJKR0TYRYZ1F",
		// ...,
		"consolidatedTo": ["01JT3P746EMZZ8J7KSMPQS36NZ"]
	}
]
```

Notable Behavior and Limitations [#notable-behavior-and-limitations]

* The order that documents are listed in the `consolidatedDocuments` array is the order that they will appear in the consolidated document.
* The consolidated document will not be produced if none of its subdocuments are produced.
* If any of the candidate subdocuments are unavailable due to conditional rendering logic (i.e are suppressed in the document selection plugin), they will be skipped, with the consolidated document still be produced with the remaining subdocuments.
* If any of those candidate subdocuments are unavailable due to a rendering error, the consolidated document will not be produced.


# Document Management



Overview [#overview]

Documents are managed, rendered, and associated in several areas within Socotra:

* **Configuration**: See the [Document Resources Configuration Guide](/configuration/resources/documents) for an overview, along with the <ApiLink name="DocumentConfigRef" /> configuration entity.
* **Policy Data**: As managed by the policy system and using the [Document Selection](/configuration/plugins/document-selection) and [Document Data Snapshot](/configuration/plugins/document-data-snapshot) plugin configuration guides.
* **Invoice Documents**: See the [Invoicing Feature Guide](/features/billing/invoicing).
* **Direct Attachment and Modification**: Described below.

Document Retrieval [#document-retrieval]

Documents can be retrieved by locator with the <ApiLink name="fetchDocument">Fetch Document</ApiLink> endpoint. To retrieve all the documents for a given entity, you can use any of these endpoints:

* <ApiLink name="fetchDocumentsForTerm">
    Fetch Documents for a Policy Term
  </ApiLink>
* <ApiLink name="fetchDocumentsForSegment">
    Fetch Documents for a Policy Segment
  </ApiLink>
* <ApiLink name="fetchDocumentsForTransaction">
    Fetch Documents for a Policy Transaction
  </ApiLink>
* <ApiLink name="fetchDocumentsForQuote">
    Fetch Documents for a Quote
  </ApiLink>

Direct Document Attachment and Modification [#direct-document-attachment-and-modification]

Most document creation and updates are configured and then managed automatically, as described in the *Overview*, above. You can extend this functionality with direct actions as described here.

This can be useful for managing "trailing documents," which require information that isn't known at the time of policy or transaction bound time or issue time.

Attaching New Documents [#attaching-new-documents]

The <ApiLink name="attachDocument">Attach Document</ApiLink> endpoint can be used to inject a new document directly into Socotra and associate it with any of the following types of entities:

* Quotes
* Policies
* Policy Transactions
* Policy Terms
* Policy Segments

<ApiLink name="DocumentInstanceResponse">Documents added this way</ApiLink> will
have their `external` property set to `true` to indicate that they weren't
created through normal system behavior.

Documents added this way must be fully rendered before upload, such as a full PDF file. Socotra document templates are not used for producing these documents.

Updating Documents [#updating-documents]

Documents that already exist in the system can be updated with the <ApiLink name="replaceDocument">Replace Document</ApiLink> endpoint. You can change the following:

* The `metadata` for the document
* The document `category`
* The document itself

<span id="DeletingDocuments" />

Deleting Documents [#deleting-documents]

External documents, which are documents manually attached through the <ApiLink name="attachDocument">Attach Document</ApiLink> endpoint, can be deleted using the <ApiLink name="deleteDocument">Delete Document</ApiLink> API endpoint.

Both system-generated documents and external documents can be <ApiLink name="softRemoveDocument">soft-deleted</ApiLink>, meaning they will no longer be attached to any entities (such as quotes or policies) to which they are currently attached, but will remain accessible within the system for auditing purposes. Soft-deleted documents will no longer be included in document generation workflows, [document carry-over logic](/configuration/resources/documents), or document consolidation workflows.

When documents are soft-deleted, the `documentInstanceState` will be set to `removed`. Documents can be in any `documentInstanceState` before soft-deletion.

<Callout>
  Soft deletion is permanent and cannot be reversed. Please exercise discretion before soft-deleting documents.
</Callout>

See Also [#see-also]

* [Document Resources Overview](/configuration/resources/documents)
* [Document Selection Plugin](/configuration/plugins/document-selection)
* [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot)
* [Documents API](/api/documents)
* [Document Resources API](/api/resources/document-resources)


# Dynamic Documents



Once you have [specified a document as dynamic](/configuration/resources/documents#static_and_dynamic_documents_configuration), you can upload a template that Socotra will inject with data when it renders the document. Dynamic documents pass through stages as the platform generates instances, including the following:

* `dataReady`: all the data to be made available to the document template has been persisted, including any additional data or metadata specified by the [Document Data Snapshot Plugin](/configuration/plugins/document-data-snapshot).
* `ready`: the document has been rendered and can be downloaded from the platform.

Template Languages [#template-languages]

Dynamic document templates can be written in Liquid or Velocity templating languages. Socotra offers [several dedicated endpoints](/api/resources/document-resources#document_template_creation_and_update_endpoints) to create new dynamic document templates or to update existing ones.

Velocity Example [#velocity-example]

Suppose you wish to include a summary document on every issued quote that includes the name of the product. Here's a basic template:

```text
Summary for Product $data.productName

Lorem ipsum...
```

<Callout>
  You can provide HTML markup in your templates, including references to external resources like stylesheets and images. Examples in this guide are deliberately concise.
</Callout>

After you <ApiLink name="createVelocityDocumentTemplate">upload the template with a name</ApiLink> in an applicable resource group configuration and create a quote, you'll see the document appear as a <ApiLink name="DocumentInstanceResponse" /> in the list returned by <ApiLink name="fetchDocumentsForQuote" />. The `renderingData` property will contain a map of the data object available to the template. The `documentInstanceState` property changes as the document passes through the rendering cycle, with the successful `ready` state indicating that the rendered document can be downloaded from the platform. Rendered documents can be retrieved with the <ApiLink name="fetchDocumentResource" /> endpoint.

Data in `renderingData` can be referenced from the `data` object in the Velocity template. For example, given `renderingData` like the following:

```json
{
	"groupLocator": "01J8JXETQSQHCH2W62BHXEKFR1",
	"underwritingStatus": "none",
	"currency": "USD",
	"accountLocator": "01J8GC55Y1VYVTKSW1FY85NR53",
	"durationBasis": "months",
	"billingLevel": "inherit",
	"productName": "Commercial"
}
```

You could reference any of the values in the template with `$data.productName`, `$data.currency`, `$data.startTime`, and so on. Similarly, you can use any of the standard Velocity statements to traverse the data tree and iterate over elements. For instance, if you had an array of `insureds` in `renderingData`, each of which had `lastName` and `location` data fields, you could display an HTML summary list of insured last names and locations like this:

```text
<ul>
#foreach ($insured in $data.insureds)
    <li>${insured.data.lastName}: $insured.data.location</li>
#end
</ul>
```

Controlling Template Data [#controlling-template-data]

The [Document Data Snapshot](/configuration/plugins/document-data-snapshot) plugin allows you to modify or augment both the data and metadata available to document templates.

Document Snippets [#document-snippets]

You can define reusable document snippets for inclusion in your templates, using the typical syntax for Liquid or Velocity. For example, after configuring and uploading snippets, you may include them in Velocity templates with the `#parse` or `#include` directives. You can also include snippets in [bootstrap configuration](/configuration/general-topics/bootstrap), just as you can with other document templates.

Document snippets can be included in the [bootstrap configuration](/configuration/general-topics/bootstrap), and managed in a fashion similar to other document resources. In document templates, you refer to snippets for inclusion by static name, using the usual syntax for such references (e.g. in Velocity, the `#parse` or `#include` directives), and rely upon the platform's resource selection facilities to include the correct instance of the snippet.

Snippets Example (Velocity) [#snippets-example-velocity]

Suppose you would like to include a footer snippet in a document template, and decide that the static name of the snippet will be `footer`. First, update your main document template to include the `footer` with either `#include` or `#parse`, like this:

```text
#parse( "footer" )
```

Next, update your top-level <ApiLink name="ConfigurationRef">configuration</ApiLink> to define the snippet:

```json
{
	// ...,
	"templateSnippets": {
		"footer": {
			"selectionTimeBasis": "policyStartTime"
		}
	}
	// ...,
}
```

Then include the snippet name in the `templateSnippets` array in the requisite <ApiLink name="DocumentConfigRef" />:

```json
{
	// ...,
	"templateSnippets": ["footer"]
	// ...,
}
```

After deploying, you can upload instances of your snippet. There are snippet-specific upload endpoints for both <ApiLink name="uploadVelocity">Velocity</ApiLink> and <ApiLink name="uploadLiquid">Liquid</ApiLink>. After uploading instances, assign them to appropriate resource groups so that the expected instance is included in the document when the document is rendered.

Custom Fonts [#custom-fonts]

You may include custom fonts in document templates intended for PDF rendering. Custom fonts are managed as a resource.

In order to use a custom font, declare a static name for the font in the `customFonts` array in the top-level <ApiLink name="ConfigurationRef">configuration</ApiLink>. For any documents that require the custom font, add the static name to the <ApiLink name="DocumentConfigRef" /> `customFonts` array.

After deploying the configuration, you can upload the font as a resource with the <ApiLink name="addFont" /> endpoint, in TTF or OTF format. Each file can only contain one font. After uploading the file, you can add the font to one or more resource groups.

<Callout>
  The `selectionTimeBasis` for custom fonts is always `now`.
</Callout>

Templates can reference custom fonts just as they would in any other context. For example, a Velocity template could specify CSS styling like this:

```css
.custom {
	font-family: 'Faculty Glyphic', sans-serif;
	font-weight: 400;
	font-style: normal;
}
```

If the "Faculty Glyphic" font was configured as specified, then the custom font will render as expected. If the font cannot be found, the platform will default to rendering with standard fonts.

Troubleshooting and Template Development [#troubleshooting-and-template-development]

Socotra enforces Velocity's `strict` rendering option.

Embedding SVGs in document templates is not supported.

Streamlining the rendering feedback loop [#streamlining-the-rendering-feedback-loop]

You can use the <ApiLink name="renderDocument">ad-hoc document rendering endpoint</ApiLink> to see how a template would be rendered against a given reference item, such as a quote, policy, or term. This can help with troubleshooting and template refinement since you don't have to conduct any actual transactions to induce document rendering for testing purposes.


# Simplified Accounting Example



import Image from 'next/image';

Overview [#overview]

Here we show the accounting representation of a sequence of operations in Socotra:

* A policy is issued with charges for $100 premium and $20 in tax.
* Two installments are created, with the charges evenly split between them.
* An invoice is issued for the first installment, for half the amounts ($50 premium and $10 tax.)
* A payment is made for $30, which is applied to the invoice but not fully paying it.
* A second payment is made for $60, which fully settles the invoice and leaves a credit left over for use later.

First we start with T-Accounts for the charges, an equity account and two asset accounts to hold the two charges:

<Image src="/images/accounting_example/accounting_example_01.png" alt="accounting example 01" width={600} height={173} unoptimized />

Then we post a transaction establishing the premium and tax charges:

<Image src="/images/accounting_example/accounting_example_02.png" alt="accounting example 02" width={600} height={200} unoptimized />

Note that the equity account is a "credit-side" account, and so it increases with the credit side of the transaction, and the "debit-side" asset accounts increase with the opposite, debit side of the transaction.

After charges are established, we create the first installment based on the charges. When we do this, the asset stored in the charge is transferred to the installment itself:

<Image src="/images/accounting_example/accounting_example_03.png" alt="accounting example 03" width={700} height={178} unoptimized />

We repeat this for the second installment:

<Image src="/images/accounting_example/accounting_example_04.png" alt="accounting example 04" width={700} height={140} unoptimized />

<Callout>
  The system actually will do the accounting at the *installment item* level, rather than the installment level as shown above. We've simplified the view to make the flow easier to understand.
</Callout>

It's likely that the timing configured for invoicing will result in the first invoice being generated right away. To do this, all the installments that have reached their `generateTime` are grouped and put on an invoice. Here, there's just one:

<Image src="/images/accounting_example/accounting_example_05.png" alt="accounting example 05" width={700} height={275} unoptimized />

When a payment is posted, it establishes a liability (because at the moment it is received, it is still the insured's money), and this is balanced against the asset called *Cash*:

<Image src="/images/accounting_example/accounting_example_06.png" alt="accounting example 06" width={700} height={280} unoptimized />

The payment can then be applied, but this one isn't sufficient to fully pay the open invoice:

<Image src="/images/accounting_example/accounting_example_07.png" alt="accounting example 07" width={700} height={280} unoptimized />

When a second payment comes in for $60, we post it as before:

<Image src="/images/accounting_example/accounting_example_08.png" alt="accounting example 08" width={700} height={292} unoptimized />

And pay off the invoice in full:

<Image src="/images/accounting_example/accounting_example_09.png" alt="accounting example 09" width={700} height={280} unoptimized />

Because there's $30 remaining in the payment, we'll store it in the insured's credit balance, where it can be applied or disbursed later:

<Image src="/images/accounting_example/accounting_example_10.png" alt="accounting example 10" width={700} height={288} unoptimized />

Summary [#summary]

After all the transactions are posted, we can examine the state of the policy as it stands:

<Image src="/images/accounting_example/accounting_example_11.png" alt="accounting example 11" width={700} height={287} unoptimized />

From this, we can prove that:

* There are charges on the policy totalling $120, with $100 in premium and $20 in tax
* This has been split evenly between two installments
* One installment has been invoiced and fully paid
* Another installment has yet to be invoiced
* The insured has made payments totalling $90, of which $60 was used to pay the first invoice and $30 remains as a credit

Because accounting transactions also store the *time* they were created, we can determine the exact sequence of events and use this to explain the history of the policy.

See Also [#see-also]

* [Basic Double-Entry Accounting Primer](/features/financials/accounting-primer)


# Basic Double-Entry Accounting Primer



Introduction [#introduction]

Socotra uses double-entry accounting for all of its billing functionality. It follows the principle that for every debit entry (an entry on the left side of an account) there must be a corresponding credit entry (an entry on the right side of an account), ensuring that the accounting equation (Assets = Liabilities + Equity) remains balanced.

Double-entry accounting is essential to accurately record and report financial transactions. This provides a systematic and structured approach to financial tracking, resulting in improved accuracy, error detection, and support for comprehensive financial analysis. By following the principles of double-entry accounting and using T-Accounts to visualize transactions, Socotra helps maintain accurate financial records and supports more informed business decisions.

With this system, Socotra facilitates improved internal controls to safeguard financials, prevent fraud, and ensure compliance with accounting policies and procedures. These controls mitigate risks associated with insurance billing operations and enhance financial integrity. In addition, compliance with regulatory requirements that mandate accurate and transparent financial reporting is simplified, using a systematic and auditable record of transactions.

General Principles [#general-principles]

Socotra follows the general rules for double-entry accounting, including:

1. **The Accounting Equation**: Assets = Liabilities + Equity. This equation must always balance, which provides a check on the accuracy of financial data, and helps to identify errors or discrepancies.
2. **Dual Entry**: Every transaction affects at least two accounts, with one debit entry and one credit entry, ensuring that the accounting equation remains balanced.
3. **Consistency**: Accounting practices are consistent over time to enable accurate financial reporting and analysis.
4. **Materiality**: Only transactions that are significant or material to the financial statements need to be recorded.
5. **Accrual Basis**: Transactions are recorded when they occur, regardless of when cash is exchanged, following the accrual basis of accounting.

<Callout>
  Equity in the accounting equation is considered to include accrued income and expenses. Future releases will allow for transactions to roll up income and expense activity to the equity accounts directly.
</Callout>

T-Accounts [#t-accounts]

T-Accounts are a visual representation of double-entry accounting, used to record and track transactions in individual accounts. Each T-Account resembles the letter "T", with the left side representing debits and the right side representing credits.

T-Accounts provide a clear and visual representation of transactional activity within individual accounts, making it easier to understand and analyze financial data. The structure of T-Accounts ensures that every transaction affects at least two accounts, with one debit entry and one credit entry, thereby maintaining the balance of the accounting equation.

The different types of T-Accounts are:

1. **Assets**: Resources that have economic value. In T-Accounts, increases in assets are recorded as debits, and decreases as credits. Cash received from payments and amounts on unpaid invoices represent carrier assets.
2. **Liabilities**: Obligations or debts owed to external parties. Credit balances on insured accounts are represented with liability accounts.
3. **Income**: Revenue from primary activities. Charges on policies accrue to income accounts.
4. **Expenses**: Costs incurred in operations to generate revenue. Write-offs are a form of expense.
5. **Equity**: A summary of the overall business, which equates to assets minus liabilities when combined with accrued income and expenses.

Different types of accounts are classified based on whether they typically have debit balances (debit-side accounts) or credit balances (credit-side accounts).

* **Debits** *increase* the value of asset and expense accounts, and *decrease* the value of liability, income, and equity accounts.
* **Credits** *decrease* the value of asset and expense accounts, and *increase* the value of liability, income, and equity accounts.

Transactions [#transactions]

Transactions are always balanced between debits and credits, and multiple T-Accounts can be affected. By requiring every transaction to have at least two entries, both the source and destination of financial flows are captured, which ensures accuracy and reliability of financial data. The dual-entry nature of transactions creates a clear audit trail, allowing you to trace the flow of financial transactions and verify accuracy.

See Also [#see-also]

* [Simplified Accounting Example](/features/financials/accounting-example)


# Charges



<span id="charges" />

Charges are objects that record financial amounts on quotes and policy transactions. Each charge has:

* An `amount`, such as $42.50
* A `rate`, which describes the amount per unit time
* An optional `referenceRate`, described later in this topic
* A `category`, such as `premium` or `tax`. Categories are defined by Socotra and aren't extendable
* A `type`, such as `stampTax`, or `goodDriverDiscount`, which is configured within the tenant
* A `tag`, which is a short note that can be added using the rating plugin.

For each quote or policy transaction element, at most one charge of a given type is allowed. Only non-zero charges will be created by the platform: Zero-charge rating items returned by the [Rating Plugin](/configuration/plugins/rating) will not be shown as charges in <ApiLink name="fetchTransactionPricing">transaction</ApiLink> or <ApiLink name="fetchPricedQuote">quote</ApiLink> price responses and will not be sent to the billing system.

During installment scheduling, each charge will be split into installment items based on the installment plan and other configured billing settings for the quote or policy.

Categories [#categories]

The following charge categories are built-in, and all charge types must be configured to use one of these categories:

* Premium
* Tax
* Fee
* Surcharge
* Credit
* Nonfinancial

Charges of category `Nonfinancial` will not be processed for presentation on invoices, but all other charges will.

`Nonfinancial` charges are useful for tracking financial information that isn't to be paid (either from insureds or to agents). For example, technical premium can be tracked as a Nonfinancial charge.

Charge Types [#charge-types]

The allowed types for charges are configured for each tenant. Any number of charge types can be added to the system, and each will specify a category in the tenant configuration. Because of this, within each tenant, the category can be inferred from a charge type. Therefore, during pricing, the type must be returned from the rating plugin for each charge, but the category does not need to be specified.

Reference Rates [#reference-rates]

Reference rates are used for advanced pricing processes and are generally not needed for most cases.

Reference rates allow you to record a canonical rate independently of the actual rate used in price calculation. Essentially, they are a way to say, "when I want to know what the 'real' rate for the charge is, use *this* ("reference") value. But I may manipulate this actual rate in order to coerce a desired amount to result from the price (rate times time) calculation."

For example, Suppose you want to round every charge amount to be a whole number of dollars. For a policy that charges $100 per month but lasts 5.085 months, the amount would normally turn out to be $508.50. In this case, you can set the `referenceRate` to be `100`, and the `rate` to be `99.9017` to get the desired outcome of $508.00. Alternatively, you can set the `referenceRate` to be `100` and the `amount` to $508.00, and the system will compute the `rate` using the `amount`.

Tracking the two different rates ensures you can reliably decide whether a rate should be considered to have changed during a policy transaction.

We discourage the use of reference rates except when essential cases require their use. If you don't need them, you can ignore them.

Data Precision [#data-precision]

Prices (i.e. the `amount` values for each charge) are stored with a precision based on the currency used for the quote or policy. This will be two digits of precision for most currencies.


# Durations



Overview [#overview]

Socotra Insurance Suite has a flexible notion of duration to prevent rigidity and difficulty for policies that aren't month-based, such as event-based policies (travel insurance, e.g.), weekly/biweekly policies, and others.

Usage [#usage]

The fundamental pricing equation in Socotra is `amount = rate * duration`. This equation holds as long as the rate and duration are based the same duration unit (for example, inverse days and days, respectively).

Given the unit, the system will be able to determine the duration of any segment, and elements that need to be priced (via the creation of charges) will implicitly have the same duration as the segment that contains them.

Configuration [#configuration]

The duration unit is specified within configuration as a tenant default and product-level override. The optional `defaultDurationBasis` property is be specified at the top-level of the configuration, and the default's default will be `months`. There is an optional `durationBasis` property for each product. If the product's `durationBasis` is not set, the tenant's default will be used instead.

Like currency and timeZone, the `durationBasis` will be copied to the quote on creation. Therefore changing the duration unit in the configuration will have no effect on previously created quotes or policies.

Supported Duration Bases [#supported-duration-bases]

These units are supported:

* `hours`
* `days`
* `weeks`
* `months`
* `years`

Daylight Saving Time [#daylight-saving-time]

Daylight Saving Time will not be considered for calculating durations. For example, a time segment that covers a shift from Daylight to Standard time, and starting and ending at midnight, and based on a unit of Days will result in an integer number of days, even though an hour may have been added or lost.


# Rounding Service



Socotra will sometimes round fractional values to a certain precision level, such as when required to confirm to precision levels specified in [Data Extensions](/configuration/data-extensions/overview). When it does this, it will use the rounding method specified in the tenant configuration.

Each data extension property can be configured with a different rounding mode with its `roundingMode` property. If no method is specified for a property, the system will use `halfEven`.

Each of the following rounding modes are available:

* `halfEven`: Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case, rounds towards the even neighbor. This is the default.
* `ceiling`: Rounds towards positive infinity.
* `down`: Rounds towards zero.
* `floor`: Rounds towards negative infinity.
* `halfDown`: Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds down.
* `halfUp`: Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds up.
* `up`: Rounds away from zero.


# Moratoriums Billing Recovery (Beta)



<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

Overview [#overview]

Billing workflows such as invoice generation, delinquency, and autopay will resume when their scheduled jobs execute and deferred work queues are processed.

Invoicing [#invoicing]

Upon resumption of invoice generation, a single catchup invoice will be generated containing all receivable amounts that would have been invoiced during the moratorium period. If specified in the `billingHoldScope` object, this catchup invoice will have a `dueTime` scheduled based on the moratorium's `endTime` plus `deferredInvoiceDueOffsetDays`. Otherwise, the invoice will be scheduled according to the applicable installment plan.

Depending on the volume of policies affected by a given moratorium, the catchup invoice may take some time to generate, with all invoices expected to be generated within 24 hours of the expiry of the moratorium.

Auto Pay [#auto-pay]

Auto-Pay functionality applies exclusively to invoices that have already been generated. In scenarios where invoice generation has been suspended, no new invoices will be created, eliminating any Auto-Pay concerns.

For existing invoices, whether generated prior to the moratorium becoming effective, or created because invoice generation was not suspended, the following behavior applies when Auto-Pay is suspended:

When an invoice's scheduled Auto-Pay execution time is reached, the system will automatically defer the payment attempt by 24 hours. This process continues daily until the moratorium is lifted. During each deferral, the system recognizes that the policy is subject to an active moratorium and postpones the Auto-Pay attempt accordingly.

Deliquency [#deliquency]

Delinquency entities for policies governed by the moratorium will continue to be created during suspension but will remain in the `preGrace` state. Existing delinquencies in the `inGrace` state will maintain that status until their `graceEndAt` time is reached, at which point they will revert to the `preGrace` state.

Billing Lifecycle Jobs [#billing-lifecycle-jobs]

Details of rescheduled autopay jobs can be found by fetching the <ApiLink name="fetchInvoiceLifecycleJobData">lifecycle job data</ApiLink> for an invoice.

Get the list of suspended delinquencies using a `policyLocator` or `delinquencyLocator`.

<ApiEndpoint name="getSuspendedDelinquencies" />

<ApiSchema name="SuspendedDelinquencyListResponse" />

<ApiSchema name="SuspendedDelinquency" />

<ApiEndpoint name="fetchCreateDelinquenciesJobDataForInvoice" />

<ApiEndpoint name="fetchDelinquencyMoratoriumJobsForTenant" />

<ApiSchema name="DelinquencyMoratoriumJobsListResponse" />

<ApiSchema name="WorkflowContextDelinquencyMoratoriumJobData" />

<ApiSchema name="DelinquencyMoratoriumJobData" />

<ApiEndpoint name="runDelinquencyMoratoriumsWorkflow" />


## API Reference

GET /billing/{tenantLocator}/delinquencies/suspended/list — getSuspendedDelinquencies
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  delinquencyLocator (ulid, query)
  policyLocator (ulid, query)
  offset (integer, query)
  count (integer, query)
Responses:
  200 SuspendedDelinquencyListResponse — OK

GET /billing/{tenantLocator}/jobs/delinquencies/invoices/{invoiceLocator}/list — fetchCreateDelinquenciesJobDataForInvoice
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  invoiceLocator (ulid, path, required)
  offset (integer, query)
  count (integer, query)
  extended (boolean, query)
Responses:
  200 DelinquencyCreateJobDataListResponse — OK

GET /billing/{tenantLocator}/jobs/delinquencies/moratoriums/list — fetchDelinquencyMoratoriumJobsForTenant
Permissions: read, list
Parameters:
  tenantLocator (uuid, path, required)
  offset (integer, query)
  count (integer, query)
Responses:
  200 DelinquencyMoratoriumJobsListResponse — OK

POST /billing/{tenantLocator}/jobs/delinquencies/moratoriums — runDelinquencyMoratoriumsWorkflow
Permissions: write
Parameters:
  tenantLocator (uuid, path, required)
Responses:
  200 — OK

SuspendedDelinquencyListResponse
Properties:
  listCompleted (boolean, required)
  items (SuspendedDelinquency[], required)

SuspendedDelinquency
Properties:
  delinquencyLocator (ulid, required)
  policyLocator (ulid, required)
  moratoriumType (string, required)
  startTime (datetime, required)
  endTime (datetime, required)

DelinquencyMoratoriumJobsListResponse
Properties:
  listCompleted (boolean, required)
  items (WorkflowContextDelinquencyMoratoriumJobData[], required)

WorkflowContextDelinquencyMoratoriumJobData
Properties:
  workflowJobLocator (ulid, required)
  workflowType (Enum LATTICE_AND_INSTALLMENTS_GENERATION | INVOICE_GENERATION | INVOICE_LIFECYCLE | PAYMENT_EXECUTION | DELINQUENCY_MORATORIUM_EXECUTION, required)
  contextData (DelinquencyMoratoriumJobData, required)
  completedAt (datetime)
  createdAt (datetime, required)

DelinquencyMoratoriumJobData
Properties:
  status (Enum queued | finished | failed | running, required)
  startTime (datetime, required)
  finishTime (datetime, required)
  error (string, required)

# Moratoriums (Beta)



<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

Overview [#overview]

A moratorium is a temporary suspension of certain policy servicing operations and billing operations across a select group of policies. Moratoriums are typically used in scenarios where an insurer, often mandated by a regulatory body, must provide relief to a group of policyholders during a specific time period, such as during a natural disaster or economic hardship.

When creating a moratorium, users have the ability to specify the effective time and end time of the moratorium, the operations to be suspended (such as autopay, cancellations, and delinquency), and the criteria for identifying affected policies (such as product type, geographic location, or other policy attributes). Once a moratorium is active, the system automatically enforces the configuration, ensuring that relevant operations are suspended for all policies that match the specified criteria.

Multiple moratoriums can be active at the same time, and a single policy can be affected by multiple, overlapping moratoriums. If a policy is affected by a moratorium, the `inScope` flag of the <ApiLink name="MoratoriumStatus" /> will show as `true`.

Use Cases [#use-cases]

While the primary use case of the moratoriums feature is regulatory compliance, this feature has also been designed to support other forms of underwriting holds, such as a carrier deciding to suspend quotes for new business, and coverage increases as a result of a catastrophe or in response to shifting market conditions.

Moratorium Status [#moratorium-status]

To check if a given policy is currently being governed by a moratorium, users can check the <ApiLink name="getQuoteMoratoriumsStatuses">status</ApiLink> of the moratorium. This will return a list of all moratoriums for a given policy, including the status of each moratorium, as shown in the example below:

```json
{
	"locator": "01K4B2HRJRPM4TTWYHHAA11BB22CC",
	"moratoriums": {
		"moratorium_1": {
			"applicable": true,
			"eligible": true,
			"inScope": true,
			"applicationMode": "optOut"
		},
		"moratorium_2": {
			"applicable": false,
			"eligible": false,
			"inScope": false,
			"applicationMode": "mandatory"
		}
	}
}
```

The `inScope` flag of the <ApiLink name="MoratoriumStatus" /> object is set to `true` if the moratorium is currently governing the policy. A moratorium is considered to be `inScope` for a policy when **both** of the following conditions are met:

* The moratorium is `applicable` to the policy
* The policy is `eligible` for the moratorium

Applicability [#applicability]

When created, the Moratorium's `applicationMode` determines how the moratorium is applied to policies. The `applicationMode` can be one of the following:

* **Mandatory**: The moratorium is automatically applied to all eligible policies.
* **Opt-Out**: The moratorium is automatically applied to all eligible policies, unless the policy is explicitly set to opt-out.
* **Opt-In**: The moratorium is **not** applied to eligible policies, unless the policy is explicitly set to opt-in.

Eligibility [#eligibility]

A policy's `eligibility` for a moratorium is determined by evaluating the <ApiLink name="MoratoriumPolicyMatchCriteriaRef">productRules</ApiLink> within the moratorium's `policyMatchCriteria`.
This will generally involve checking for a match between the value of some data field whose position in the data model is described in the rule's `path`, against a list of values provided in the `criteriaValues` - for example, a moratorium may be defined to be eligible for all policies whose `zipCode` is one of a list of specified zip codes.

Reporting [#reporting]

Tables providing moratorium details, quote and policy opt-in and opt-out records, and lists of affected quotes and policies are available in [Data Lake](/features/reporting/datalake).

Suspending Operations [#suspending-operations]

There are two scopes that can be suspended by a moratorium: policy servicing operations and billing operations. When creating a moratorium, there must be at least one policy servicing operation or billing operation suspension specified.

Policy Servicing Operations [#policy-servicing-operations]

* Users can specify a list of transaction categories and transaction types that will be suspended for all policies governed by the moratorium. These values can be specified in the `transactionCategory` and `transactionType` fields of the `policyHoldScope` object.
* `transactionType` values provide more granular control over the operations to be suspended.
* Transaction categories and transaction types specified in the `policyHoldScope` object will be allowed up to the `accept` life cycle state, but will be prevented from proceeding to `issued`.
* Quotes can be suspended by including the `issuance` transaction category in the `transactionCategory` list.

Billing Operations [#billing-operations]

* Users can specify a list of billing operations that will be suspended for all policies governed by the moratorium. These operations can be specified using the `billingHoldScope` object.
* This can include:
  * **policyInvoicingHold** - If `true`, no new invoices are generated for policies governed by the moratorium.

  * **autopayHold** - If `true`, autopay will not be triggered for invoices associated with policies governed by the moratorium. Autopay will be rescheduled for 24 hours later until the moratorium ends.

  * **deliquencyHold** - If `true`, new [delinquencies](/features/billing/delinquency) for policies governed by the moratorium, will be created, but will remain in the `preGrace` state.

  * **deferredInvoiceDueOffsetDays** - If specified, any invoices deferred by the `policyInvoicingHold` flag, once generated, will have their due date offset by the specified number of days from the end of the moratorium.

Effective Time [#effective-time]

By default, only policies issued prior to the `effectiveTime` are considered for a moratorium. This requirement can be waived by setting the `effectiveTimeWaived` flag to `true`. These policies must still meet the eligibility criteria defined in the `policyMatchCriteria` object.

End Time [#end-time]

A moratorium remains in effect from its `effectiveTime` through its `endTime`, even if the end time is not known when the moratorium is created. To facilitate this, the `endTime` property is optional and can be added later.

When a moratorium ends, all policies that were governed by the moratorium will immediately allow previously suspended operations to resume.

Any policy servicing operations will be permitted to now move beyond the `accepted` state, but no automatic actions are taken.

Billing workflows such as invoice generation, delinquency, and autopay will resume when their scheduled jobs execute and deferred work queues are processed. Refer to our article on [Moratoriums Billing Recovery](/features/moratoriums/moratoriums-billing-recovery) for more details on the billing recovery process.

Configuration Example [#configuration-example]

* The Texas Department of Insurance has issued bulletin `TDI-B-0914-24`, effective September 14, 2024. The duration is not yet known.
* Invoicing, autopay, and policy cancellations are prohibited for all homeowner policies where the dwelling is in one of the specified zip codes or counties.
* Any invoices deferred during the period should have a due date of no sooner than 15 days from the end of the moratorium.
* Policyholders may elect to forego the protections offered by the bulletin.
* New business policies issued after the moratorium goes into effect are not subject to the protections offered by the bulletin.
* Carriers may choose to prohibit other transaction types, such as limit increases or deductible reductions, during the moratorium period.
* Affected zip codes: \[`75001`, `75006`, `75007`, `75009`, `75010`, `75019`, `75020`]
* Affected counties: \[`Dallas`, `Collin`, `Rockwall`, `Kaufman`, `Ellis`]

Product Configuration [#product-configuration]

```json
{
    "products": {
        "Ho3": {
            "data": {
                "dwellingZip": {
                    "type": "string?"
                },
                "dwellingCounty": {
                    "type": "string?"
                }
            }
        },
        "Ho6": {
            "data": {
                "dwellingAddress": {
                    "type": "Address?"
                }
            },
            "customTypes": {
                "Address": {
                    "data": {
                        "zip": {
                            "type": "string?"
                        },
                        "county": {
                            "type": "string?"
                        }
                    }
                }
            }
        }
    },
    "transactionTypes": {
        "limitIncrease": {
            {
                "category" : "change",
                "costBearing" : true
            }
        },
        "reduceDeductible": {
            {
                "category" : "change",
                "costBearing" : true
            }
        }
    }
}
```

Moratorium Configuration [#moratorium-configuration]

```json
{
	"moratoriums": {
		"TDI_B_0914_24": {
			"type": "disaster",
			"description": "test moratorium",
			"applicationMode": "optOut",
			"effectiveTime": "2025-10-01T00:00:00Z",
			"policyMatchCriteria": {
				"criteriaValues": {
					"zipCode": [
						"75001",
						"75006",
						"75007",
						"75009",
						"75010",
						"75019",
						"75020"
					],
					"counties": ["Dallas", "Collin", "Rockwall", "Kaufman", "Ellis"]
				},
				"productsRules": {
					"rule1": {
						"product": "Ho3",
						"operator": "OR",
						"rules": [
							{
								"path": "data.dwellingZip",
								"criteriaKey": "zipCode"
							},
							{
								"path": "data.dwellingCounty",
								"criteriaKey": "counties"
							}
						]
					},
					"rule2": {
						"product": "Ho6",
						"operator": "OR",
						"rules": [
							{
								"path": "data.dwellingAddress.zip",
								"criteriaKey": "zipCode"
							},
							{
								"path": "data.dwellingAddress.county",
								"criteriaKey": "counties"
							}
						]
					}
				}
			},
			"effectiveTimeWaived": false,
			"policyHoldScope": {
				"transactionCategory": ["cancellation"],
				"transactionType": ["limitIncrease", "reduceDeductible"]
			},
			"billingHoldScope": {
				"policyInvoicingHold": true,
				"autopayHold": true,
				"deferredInvoiceDueOffsetDays": 15
			},
			"displayName": "TDI Bulletin TDI-B-0914-24"
		}
	}
}
```

<ApiSchema name="MoratoriumRef" />

Delinquencies [#delinquencies]

When a moratorium is in effect:

* Delinquency events are suppressed, and the delinquency reverts to the `preGrace` state rather than lapsing.
* Delinquencies are evaluated when any of the following conditions are true: When a delinquency event is about to fire, when a grace period is about to begin, and when a grace period expires. Imposing a moratorium does not immediately interrupt a grace period already in effect. The moratorium takes effect the next time any of these conditions are true.
* Grace periods restart from the beginning after a moratorium is lifted, regardless of how much of the grace period has elapsed.
* It may take up to 24 hours plus up to 59 minutes after a moratorium is lifted for grace periods to restart.
* When a moratorium is lifted, grace periods restart, and delinquency event trigger timing is calculated against the new grace period. Delinquency events that had not yet fired are rescheduled. Delinquency events that already fired are recreated and will fire again during the new grace period.
* When a hold is released, grace periods restart, but delinquency event trigger timing remains unchanged.

Next Steps [#next-steps]

* [Moratoriums Billing Recovery](/features/moratoriums/moratoriums-billing-recovery)

See Also [#see-also]

* [Moratoriums API](/api/moratoriums)


## API Reference

MoratoriumRef
Properties:
  type (string, required)
  description (string)
  applicationMode (Enum optIn | optOut | mandatory, required) — Indicates whether the moratorium applies to all eligible policies or whether there is an option to opt in or out.
  effectiveTime (datetime, required)
  endTime (datetime) — The time the moratorium ends. This can be set after creation and updated to earlier or later.
  policyMatchCriteria (MoratoriumPolicyMatchCriteriaRef, required) — The criteria used to identify which policies are eligible for the moratorium.
  effectiveTimeWaived (boolean) — Indicates whether eligible policies issued after the moratorium effectiveTime are affected.
  policyHoldScope (PolicyHoldScopeRef, required) — Must be at least one of either policyHoldScope or billingHoldScope.
  billingHoldScope (BillingHoldScopeRef, required)
  displayName (string)

# Coverage Terms



Overview [#overview]

Coverage terms are a special kind of policy data. They are more rigidly defined than [data extensions](/configuration/data-extensions/overview), but serve a similar purpose: storing information about the policy and what it covers.

Coverage terms are useful for managing policy aspects such as:

* Deductibles
* Exclusions
* Limits (e.g. split limits, aggregate limits, lifetime limits, etc.)
* Benefit Levels (e.g. term-life payouts)
* Riders (e.g. optional inclusion of additional coverage that doesn't need a full Coverage element)

Coverage terms are associated with elements, typically of the `coverage` category. However, coverage terms can be assigned to elements of any category.

Configuration [#configuration]

Like elements, coverage terms are defined at the root level of the tenant configuration. Each element definition can specify which coverage terms may be used with that element.

Each coverage term definition must have a `name` that is a valid [identifier](/configuration/general-topics/identifiers).

If you would like a value associated with the coverage term, you can choose to leverage `options`, or specify a `value`.

* With `options`, you define a *finite* set of values that the coverage term can take when it is on an element. Each option definition has:
  * A `name` (which also most be a valid identifier)
  * An optional numeric `value`
  * An optional `tag` of type `string`

* With `value`, you supply a <ApiLink name="PropertyRef" /> definition for any of the platform's supported [built-in types](/configuration/data-extensions/data-extension-types#built-in-types), such as `string` or `int`.

You cannot specify both `options` and `value` for a coverage term. See the <ApiLink name="CoverageTermRef" /> reference for comprehensive configuration details.

Sample Configuration [#sample-configuration]

```json
// ... ,
"coverageTerms": {
    "LiabilityLimit": {
      // defining an "options" coverage term
      "type": "limit",
      "displayName": "Liability Limit",
      "options": {
        "PAL100_000" : {
          "displayName" : "$100,000"
        },
        "PAL250_000" : {
          "displayName" : "$250,000"
        },
      // ...,
      }
    },
    "ComputedLimit": {
      // defining a "value" coverage term
      "type": "limit",
      "displayName": "Computed Limit",
      "value": {
        "type": "int",
        "min": 1000,
        "max": 5000
      }
    },
    "SpecialDeductible": {
      // defining a coverage term with no associated value
      "type": "deductible",
      "displayName": "Special Deductible"
    }
}
```

Elements with Coverage Terms [#elements-with-coverage-terms]

Each element definition contains an optional `coverageTerms` property, with an array of strings, each of which must be the name of a configured coverage term.

Creation [#creation]

At run time, each element create request has an optional `coverageTerms` property, which is a `map<string, string>`. For each item, the key must be the name of a valid coverage term for that element. If the coverage term has no options or has a [default option](#default_coverage_term_options), the associated value may be `null`; otherwise, a value conforming to the configured `options` or `value` must be supplied.

Update [#update]

When an element is updated, the update request can do any of:

* Remove a coverage term from the element
* Add a new coverage term to the element, along with its value (just like the protocol on element creation)
* Change the option for a coverage term

<span id="default_coverage_term_options" />

Default Coverage Term Options and Values [#default-coverage-term-options-and-values]

If the name of a coverage term option is prefixed with an asterisk, such as `*deductible`, then that option will be the default option for that coverage term. That means that it doesn't need to be specified when setting the coverage terms for an element. A `value`-based coverage term does not have a default value, even if the <ApiLink name="PropertyRef" /> specifies a `defaultValue`.

Automatic elements cannot have any coverage terms, unless one of these things is true for all coverage terms on the element:

* The coverage term is optional; or
* The coverage term has no options, or a default option.

When an automatic element with coverage terms is automatically added, optional coverage terms will not be added, but required coverage terms will.

Plugins [#plugins]

In plugins, when elements are exposed via the plugin payload, each coverage term is included with its selected option name, value, and tag, if the coverage term has options. An `isVariable` boolean property can be used to distinguish between an options-based (`isVariable: false`) and value-based (`isVariable: true`) coverage term.


# Out-of-Sequence Transactions



Overview [#overview]

Out-of-sequence ("OOS") transactions are a minority case but essential for real-world use cases. They refer to transactions that have been added to the head of the transaction stack (as all transactions must be, unless they are creating a new branch) with an `effectiveTime` earlier than the based-on transaction's `effectiveTime`.

The design of out-of-sequence transaction handling ensures that out-of-sequence transactions will have the same coverage details as if all transactions had been issued in-sequence. The history of the out-of-sequence transactions is maintained as well.

<Callout>
  The `effectiveTime` of a transaction may be the same as the `effectiveTime` of an earlier transaction. In this case, the transaction with the earlier `createTime` will be processed first.
</Callout>

High-Level Approach [#high-level-approach]

There are several key points about out-of-sequence transactions:

* In the transaction stack, all sequences of transactions through a given base transaction (called that transaction's local stack) are in-sequence.
* To handle an out-of-sequence transaction, a special type called an aggregate transaction is used, because it needs to contain at least one reversal and two new transactions: the OOS change and the reapplication of the reversed transaction.
* Clients do not need to declare a transaction as out-of-sequence; the system will identify the situation, creating the aggregate transaction as needed.
* As the system processes out-of-sequence transactions, any change instructions for elements that no longer exist as a result of reapplied transactions will be ignored by the system to allow processing to continue.
* If an out-of-sequence transaction were to be invalidated rather than issued, all that is needed is to mark it as invalidated and it will become effectively nullified. No other significant updates to the policy data are needed because the transaction contains the key details about the changes, and no other transactions are modified.

Static Locators [#static-locators]

When a transaction with locator X is reversed and then reapplied with transaction Y, transaction Y will have `locator` Y and `staticLocator` X. Note that for any local transaction stack, each transaction's `staticLocator` will be unique even though they may be duplicated in the overall stack.

Intervening Out-of-Sequence Transactions [#intervening-out-of-sequence-transactions]

When an out-of-sequence transaction needs to contain reapplication transactions from other transactions contained within aggregate transactions, it will create reapplication transactions that are not nested. For example, suppose we have this series of transactions in the local stack for transaction C:

`A` → `B`: (`B1` → `B2`) → `C`

Here, transaction `B` is an aggregate that contains `B1` and `B2`. If we try to create a new transaction `D` that's effective between `B1` and `B2`, we'd end up with:

`A` → `D`: (`D1` → `D2` → `D3` → `D4`)

So now aggregate transaction `D` contains:

* Transactions B1, B2, and C in its `reverses` array
* `D1`: the reapplication of `B1`
* `D2`: the new OOS change
* `D3`: the reapplication of `B2`
* `D4`: the reapplication of `C`

In this example, the fact that `D1` and `D3` were once part of an aggregate transaction is not retained in the local stack, though that fact is knowable by looking at transaction `B` directly.

Reversals [#reversals]

Issued out-of-sequence changes can themselves be reversed, like any other transaction, aggregate or not (except for the original Policy Issuance).

This is done by applying a new Reversal transaction that reverses the aggregate, and that makes the policy data identical to the state before the aggregate.

See Also [#see-also]

* [Transaction Branching and Invalidation](/features/policy-management/transaction-branching-and-invalidation)
* [The Policy Transaction stack](/features/policy-management/policy-transaction-stack)


# Policy Elements



Overview [#overview]

Policy Elements are the building blocks of any insurance product. They are structured in a hierarchy, with an element of type `product` at the top, and other elements layered below. The structure can be simple or elaborate depending on the needs of the product. A simple warranty product may just have a single product element, while a commercial package policy may have a hierarchy several layers deep.

The structure of the product hierarchy is specified in configuration. Each element type may be configured to contain some number of sub-elements, using the `contents` property of the element definition.

Categories and Types [#categories-and-types]

Each Socotra element must be configured with a `category` and a `type`. The `type` can be any valid identifier, while the `category` must be one of the following built-in values:

* `product`
* `policyLine`
* `exposureGroup`
* `exposure`
* `coverage`

For example, an element may be defined with the category `exposure` and the type `building`.

The `product` element is implicit based on the configuration of the product as a whole, and the other types are declared as stand-alone elements. You may configure any arrangement of hierarchy you want, such as a product with exposures which contain coverages, or coverages which contain exposures, or both.

Example [#example]

In your top-level `config.json`, you may have a section that looks like this:

```json
{
	"coverages": {
		"LiabilityCoverage": {},
		"ComprehensiveCoverage": {}
	},
	"exposures": {
		"Person": {},
		"PersonalVechicle": {}
	}
}
```

`LiabilityCoverage`, `ComprehensiveCoverage`, `Person`, and `PersonalVehicle` are all unique types. Each type's respective category is indicated by its position under one of the recognized category key names. In this case, `LiabilityCoverage` and `ComprehensiveCoverage` are both `coverages`, while `Person` and `PersonalVehicle` are `exposures`.

<Callout>
  There can be only one element definition per type name. Type names must be unique across all categories; for example, you cannot define a `Person` under the `exposures` category and once again under the `coverages` category.
</Callout>

Quantifiers [#quantifiers]

In the `contents` for each element, the allowed sub-elements may be qualified by *Quantifiers*, which describe how Socotra will validate that a draft quote is acceptable. They are indicated by a suffix, or lack of a suffix, on the name of the sub-element.

See the [Quantifiers](/configuration/general-topics/quantifiers) topic for more information.

Coverage Terms [#coverage-terms]

Each element type may also be configured to include any number of Coverage Terms. Each of these is a named type with a set of allowed options and metadata. See the [Coverage Terms](/features/policy-management/coverage-terms) topic for more information.

Data Extensions [#data-extensions]

Each element type may be configured to include a set of required and optional data, of various dataExtensions. See the [Data Extensions](/configuration/data-extensions/overview) topic for details.

See Also [#see-also]

* [Quantifiers](/configuration/general-topics/quantifiers)
* [Coverage Terms](/features/policy-management/coverage-terms)
* [Data Extensions](/configuration/data-extensions/overview)


# Policy Holds



import Image from 'next/image';

Overview [#overview]

Policy Holds are available to prevent the user or system from initiating or continuing transaction processes that should not be made for certain policies in the system. These are implemented using <ApiLink name="EntityHold">Entity Hold</ApiLink> objects. These are created and managed as needed to reflect the onset and eventual conclusion of any desired hold states.

Lifecycle [#lifecycle]

The lifecycle of a hold looks like this:

<Image src="/images/entity_hold.png" alt="entity hold" width={600} height={293} unoptimized />

Policy Holds can be created in `draft` state and then `validated`, but won't have an effect until you explicitly activate them.

When a hold should no longer be in effect, you can explicitly release or discard it.

Policy & Quote Holds [#policy--quote-holds]

When a hold exists for a given policy, any transactions listed either by category in the `transactionCategory` array or explicitly by name in the `transactionType` array of the <ApiLink name="PolicyHoldScope">PolicyHoldScope</ApiLink> of the <ApiLink name="CreateEntityHoldRequest">CreateEntityHoldRequest</ApiLink>, will be prevented for being created for that policy. This will remain the case until the hold is released.

A hold can also be applied to non-issued quotes, preventing the user from progressing the quote beyond the specified quote state. When applied to an existing quote already in the specified state, further progression will be blocked.

Auto-Renewal Holds [#auto-renewal-holds]

A hold can also be applied to prevent the [auto-renewal](/features/policy-management/renewal-management) process from initiating for the given policy. This is done by setting the `autoRenewalHold` property on the <ApiLink name="PolicyHoldScope">PolicyHoldScope</ApiLink> to `true`. When this hold is active, no auto-renewal will be created for the policy, and any existing auto-renewals will be gated from progressing in their lifecycle.

See Also [#see-also]

* [Policy Holds API](/api/policy-management/policy-holds)


# Policy Status



Overview [#overview]

You can easily obtain a policy's status in Socotra and listen on status updates. Socotra defines the following policy statuses:

| Status          | Meaning                                                                                                                                                                                                                                                        |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pending`       | The policy has not yet reached its `startTime`, or it was cancelled prior to reaching its `startTime`.                                                                                                                                                         |
| `expired`       | The policy's `endTime` is in the past.                                                                                                                                                                                                                         |
| `cancelled`     | The transaction stack contains an issued cancellation that has an effective time in the past. It is removed when the policy is reinstated or the cancellation is reversed.                                                                                     |
| `cancelPending` | The transaction stack contains an issued cancellation that has an effective time in the future. The status is removed when the policy is reinstated (with or without a gap), the cancellation is reversed, or the cancellation effective time enters the past. |
| `onRisk`        | The policy is not `pending`, `expired`, or `cancelled`.                                                                                                                                                                                                        |
| `delinquent`    | There is an active [delinquency](/features/billing/delinquency). This status is set when delinquency is `inGrace` and unset when the delinquency is in `preGrace`, `settled`, or `lapseTriggered`.                                                             |
| `doNotRenew`    | The latest term's [auto-renewal](/features/policy-management/renewal-management) object has `doNotRenew`.                                                                                                                                                      |

Socotra does not attempt to impose a singular status in cases where a policy can be said to fulfill multiple state conditions. This is why the platform exposes `statuses`, an array of enumerated values, on <ApiLink name="PolicyResponse" />. For example, a policy's status can be `[onRisk, cancelPending]`.

Obtaining Policy Status [#obtaining-policy-status]

API [#api]

Policy status is provided as `statuses` on the `PolicyResponse` returned by endpoints such as <ApiLink name="fetchPolicy" /> and supplied as inputs to plugins like the [precommit plugin](/configuration/plugins/precommit).

<span id="policy-status-event-stream" />

Event Stream [#event-stream]

The [event stream](/configuration/general-topics/events) includes `policy.status.update`, which is emitted on any change to policy status. The event body includes `newStatuses` and `removedStatuses` to indicate which statuses may have been added and which may have been removed, respectively. Both `newStatuses` and `removedStatuses` have `ListPageResponsePolicyStatus` values:

<ApiSchema name="ListPageResponsePolicyStatus" />

For example, when a new on-risk policy is issued, you should expect to see an event like this:

```json
{
	"locator": "...",
	"requestId": "...",
	"userLocator": "...",
	"timestamp": "...",
	"type": "policy.status.update",
	"data": {
		"removedStatuses": {
			"listCompleted": true
		},
		"policyLocator": "...",
		"newStatuses": {
			"listCompleted": true,
			"items": ["onRisk"]
		}
	}
}
```

If you were to then issue a cancellation effective now or in the past, a new event would be emitted:

```json
{
	"locator": "...",
	"requestId": "...",
	"userLocator": "...",
	"timestamp": "...",
	"type": "policy.status.update",
	"data": {
		"removedStatuses": {
			"listCompleted": true,
			"items": ["onRisk"]
		},
		"policyLocator": "...",
		"newStatuses": {
			"listCompleted": true,
			"items": ["cancelled"]
		}
	}
}
```

As the event implies, `statuses` in `PolicyResponse` would be `[cancelled]`.


## API Reference

ListPageResponsePolicyStatus
Properties:
  listCompleted (boolean, required)
  items (Enum[], required)

# Policy Transaction Stack



Workflow [#workflow]

The policy transaction workflow is identical to the [quotes](/features/policy-quotation/quotes) workflow.

<span id="TransactionData" />

Transaction Data [#transaction-data]

The following policy transaction properties are maintained internally by the system and are not accessible via API:

* `basedOn` is set for all but issuance transactions. basedOn refers to the top-most transaction that:
  * Is immediately lower in the transaction stack and
  * Is not reversed

* The `updateInstruction` contains information on how to change coverage information (adding elements, mutating element data, etc.).

* The `segments` array contains all the segments created by the transaction.

* `reversesTxs` is an array populated for out-of-sequence or reversal cases.

* `reapplicationOf` is used for out-of-sequence handling, where Socotra reverses a set of transactions latest to earliest, applies a new transaction, and then reapplies the reversed transactions. If non-null, `reapplicationOf` contains the locator of the transaction that this one is reapplying.

* `termHead` indicates the head of the term stack that this transaction is based on.

* The `previousChargeSummary` is a set of denormalized summary-level charge amounts by term, element, charge and type. It includes the transaction's new charges, such that the total price and non-financial sums for that entire term through that transaction are reflected in the summary.

* The `staticLocator` refers to the locator of the original transaction. The `staticLocator` field will remain unchanged for a transaction, even when a transaction is reversed and reapplied.

* The `expirationTime` prevents policy transactions from moving to the next stage of the policy transaction [lifecycle](/features/policy-management/policy-transactions#process) if the `expirationTime` is equal to or before the current time when a request is processed. Expired policy transactions can still be reset (moved to the `draft` state) or discarded. If an issued or reversed policy transaction is reapplied, the `expirationTime` will be ignored.

See the [Policy Transactions API](/api/policy-management/policy-transactions) for properties accessible via API.

Descriptions [#descriptions]

Descriptions can be added to policy transactions in the Operations Workbench. These descriptions are stored as [aux data](/api/aux-data/aux-data). You can retrieve descriptions by using the <ApiLink name="getAuxData">Fetch Aux Data</ApiLink> API endpoint, setting the `locator` as the transaction locator, and setting the `key` as `transactionDescription`.

Documents [#documents]

Documents can be created and attached to the transaction at any of the `validated`, `priced`, `underwritten`, `accepted`, or `issued` states, based on the configuration for documents for that transaction. Some of the documents may be copied to the policy or term based on the configuration when the transaction is issued.

Validation [#validation]

Validation works similarly to the process in [quotes](/features/policy-quotation/quotes). Each segment will be validated independently based on the configuration schema.

For example, if there is a vehicle element with quantifier "one or more" declared as `vehicle+` in the configuration contents, then each segment must confirm that there is at least one vehicle active in the segment. This could be satisfied by a vehicle persisting across segments or being replaced with another by the transaction.

The validation plugin should generally check each segment independently in the same way, but since some use cases require context from other segments, all segments to be validated will be sent in one call.

See Also [#see-also]

* [Policy Transactions](/features/policy-management/policy-transactions)
* [Quotes](/features/policy-quotation/quotes)


# Policy Transactions



import Image from 'next/image';

The Policy Transaction is the structure that the policy module uses to track policy changes, starting with *issuance* and any subsequent modifications, such as endorsement, renewal, cancellation, and reinstatement.

Structure [#structure]

Policy transactions are independent. After validation, most of the important data on a transaction is immutable. This offers the following capabilities:

* The state of the policy (including data, pricing, coverages, and other [elements](/features/policy-management/policy-elements)) as of a moment in time can be easily assessed: start at the most recently issued transaction and proceed down the transaction stack until you find the first transaction issued on or before the given time.
* The state of the policy as of a certain effective time can be easily found: start at the most recently issued transaction and find the policy segment that spans the given effective time.
* It is easy to answer questions like "what would the policy look like if this transaction were to be issued?"
* The pricing "caused" by a transaction is easy to find: it's stored in the transaction itself, for premium and any other relevant charge.
* When reverting transactions (such as in reinstatements and transaction reversals), the data and prices for the policy will be restored to the exact values immediately before the reversed transaction, even in complex out-of-sequence cases.

See the [Policy Transaction Stack](/features/policy-management/policy-transaction-stack) topic for details about these and other cases.

Provisional Transactions [#provisional-transactions]

Like [quotes](/features/policy-quotation/quotes), transactions are created in a provisional state starting with `draft` and advancing through intermediate steps for validation, pricing, underwriting, and other processes, and ultimately proceeding through issuance (or, potentially, invalidation and/or discard.)

Provisional transactions can be chained (for example, one prospective transaction can be based on an earlier transaction that hasn't been issued yet.) Any number of transactions may be stacked in this way, provided that no transaction is based on a transaction with an earlier state. For example, a `validated` transaction can't be based on a `draft` transaction.

Transactions can also be branched, allowing convenient side-by-side comparisons while ensuring only one branch can go on to be issued.

Basic Transactions [#basic-transactions]

The following transactions are included in Socotra Insurance Suite:

* Issuance
* Policy Change
* Renewal
* Cancellation
* Reinstatement
* Reversal

<span id="Process" />

Process [#process]

Policy transactions exhibit a workflow similar to the [policy quotation](/features/policy-quotation/quotes) process:

<Image src="/images/policy_transaction_main_flow.png" alt="policy transaction main flow" width={800} height={301} unoptimized />

With underwriting flow:

<Image src="/images/policy_transaction_underwriting_flow.png" alt="policy transaction underwriting flow" width={800} height={151} unoptimized />

Compared to quotes, the major difference with policy transactions is the addition of the `initialized` step. The transaction automatically enters this step when it is advanced, or when it is edited from `draft` state.

On creation, transactions begin in the `draft` state and contain a set of change instructions, such as add a new coverage, remove an exposure, update data or coverage terms, etc. These are descriptors of how the existing policy data (as of the effective time of the new transaction) should be changed.

When `initialized`, the transaction will use the change instructions to materialize the segment for the revised coverage period. This includes creation of the new elements and setting the data extensions and coverage terms. At this point the segment data can be modified directly, much like quotes are modified when they are in `draft` state, but the effective time of the transaction can no longer be changed.

Edits to the segment data will also automatically generate updates or changes to the transaction's change instructions, such that the collection of change instructions, when applied to the previous segment's data, is guaranteed to produce the current segment data.

Policy transactions in the `issued` state cannot be discarded, invalidated, or reset, and policy transactions in the `accepted` state cannot be discarded or reset.

<span id="trx-reset" />

Transaction Reset [#transaction-reset]

Like quotes, policy transactions that have advanced past `draft` state but are not yet `issued`, `rejected`, or `discarded` can be <ApiLink name="resetTransaction">reset</ApiLink>. Accepted transactions must first be `refused` before they can be reset. For transactions, there is a choice between resetting to `initialized` state, or resetting to `draft` state.

The default is reset to `initialized` state, which will remove pricing, documents, and underwriting information (based on the <ApiLink name="ResetOptions" />), but will retain the segment data that was created based on its change instructions. This can be helpful if you want to retain the locators of newly created elements, as they won't change based on the default reset action.

Alternatively, you can set the `resetToDraft` query parameter to `true`, and the segment data will be discarded. It will be regenerated when the transaction is edited or revalidated.

Reversing Multiple Transactions [#reversing-multiple-transactions]

When attempting to [reverse](/api/policy-management/policy-transactions#create-a-reversal-transaction) a series of the most recently issued transactions in a transaction stack, we recommend specifying a target transaction locator in the `toTransaction` field. The system will reverse each transaction in order of most recently issued to least recently issued until it reaches the target transaction.

Alternatively, you can list the locators of any transactions you wish to reverse in the `reverseTransactions` array, regardless of their location within the transaction stack. The system will reverse the specified transactions and will reapply all other transactions. If any reapplications are associated with a term that no longer exists as the result of a reversal, the request will fail, and none of the reversals specified in the request will be processed.

Regardless of which reversal approach is used, a reversal will always add a new reversal transaction to the transaction stack.

<Callout>
  A renewal transaction followed by additional transactions cannot be reversed by itself. It must be reversed together with all transactions that follow by using `toLocator` or `reverseTransactions`.
</Callout>

Policy Transaction Extension Data [#policy-transaction-extension-data]

Extension data can be associated with policy transactions through <ApiLink name="TransactionDataChangeInstructionCreateRequest">TransactionDataChangeInstructionCreateRequest</ApiLink> objects or the <ApiLink name="patchTransactionData">Patch Transaction Data</ApiLink> API endpoint to accommodate custom data that relates to an entire policy transaction.

Policy transaction extension data can be configured through the `data` property at the top level of each <ApiLink name="TransactionTypeRef">TransactionTypeRef</ApiLink> configuration object.

Here's an example of a `TransactionTypeRef` configuration object:

```json
{
	"FlatPolicyholderBankruptcy": {
		"category": "cancellation",
		"costBearing": true,
		"data": {
			"cancellationReason": {
				"displayName": "Reason for Transaction",
				"type": "string"
			},
			"premiumAdjustment": {
				"displayName": "Additional Manual Premium",
				"type": "int?",
				"tag": ["currency"]
			},
			"premiumAdjustmentJustification": {
				"displayName": "Reason for Additional Manual Premium",
				"type": "string?"
			}
		}
	}
}
```

Once this configuration has been deployed, you can associate extension data with a policy transaction through the <ApiLink name="patchTransactionData">Patch Transaction Data</ApiLink> API endpoint.

For example:

```json
{
	"setData": {
		"cancellationReason": "Affordability"
	}
}
```

See the [Data Extensions](/configuration/data-extensions/overview) feature guide for more information.

<Callout>
  Policy transaction extension data can only be associated with a named policy transaction.
</Callout>

See Also [#see-also]

* [Policy Transaction Stack](/features/policy-management/policy-transaction-stack)
* [Quotes](/features/policy-quotation/quotes)
* [Policy Transaction API](/api/policy-management/policy-transactions)


# Reinstatement



Overview [#overview]

Reinstatement is a [policy transaction](/features/policy-management/policy-transactions) that restores coverage to the policy after a cancellation. There are two basic types of reinstatement:

* A *standard* reinstatement is effective as of the cancellation time, so that coverage on the policy is continuous once the reinstatement is issued.
* A *reinstatement with a gap* is effective after the cancellation time, so that there is a period of time where there is no coverage, even after the reinstatement is issued.

Behavior [#behavior]

The *cancellation period* is the time from the onset of the cancellation (based its effective time) and the remainder of the policy (the `endTime` of the latest term). It is possible for there to be more than one cancellation involved: For example, a policy could be cancelled effective February 1, and then cancelled again effective January 1. This has the effect of pulling the cancellation earlier. In this case, the cancellation period would be January 1 onward after the second cancellation was applied.

A <ApiLink name="reinstatePolicy">reinstatement transaction</ApiLink> can be effective any time in the cancellation period, but not before. For example, a policy that starts January 1, and then is cancelled effective March 1, cannot be reinstated effective February 1 because that would be before the cancellation period starts.

If the effective time of the reinstatement is not specified, then the default will be the beginning of the cancellation period.

Reinstatement After Multiple Cancellations [#reinstatement-after-multiple-cancellations]

If a policy is cancelled as of a certain time, then a second cancellation may only be effective-dated before that time, since it would have no effect if it were effective-dated during an already-cancelled period.

When there are multiple cancellations, any reinstatement applied will restore all coverage after the effective time of the reinstatement. For example, if there is a cancellation effective February 1 and another effective March 1:

* A reinstatement effective February 1 would restore all coverage.
* A reinstatement effective February 15 would restore all coverage after February 15, leaving a gap in coverage between February 1 and February 15. (Note that the March 1 cancellation is not reapplied, so coverage continues through the end of the policy.)
* A reinstatement effective March 1 would undo the effect of the March 1 cancellation but leave the month of February with a gap.

<span id="reinstatementWithGap" />

Reinstatement with a Gap [#reinstatement-with-a-gap]

The reinstatement can be made effective after the cancellation effective time, which will result in reinstatement with a gap. This will create two new segments for the policy term:

* A `gap` segment, which indicates that there is no coverage between the cancellation effective time and the reinstatement effective time; and
* A normal segment, which indicates the resumption of coverage.

Reinstatement with gap is otherwise the same as a typical reinstatement.


# Renewal Management and Auto-Renewal



Overview [#overview]

Renewal Management covers different modes for renewing a policy:

* **Standard**: Manual renewal created and managed with explicit actions taken by the client, extending the policy's `endTime` by creating a new term
* **Auto-Renewal**: Automatic handling of renewal creation and optionally, issuance
* **Do Not Renew**: Mark policies for non-renewal when they do not meet underwriting or appetite thresholds, using the auto-renewal mechanism
* **Renewal with a Gap**: Renewing the policy such that the new term starts strictly *after* the preceding term's end time.

Renewal management operates at a term level, so that terms contain the settings for automatic renewal handling. Only the latest term can have an active Auto-Renewal.

<Callout>
  When renewing with a gap, there is no gap segment created. Rather, the terms have a period of time between them that no term or segment covers.
</Callout>

Manual Renewal [#manual-renewal]

To manually renew a policy, create a [renewal transaction](/features/policy-management/policy-transactions) with a new `endTime` for the policy. This end time must be strictly greater than the current policy end time.

You may also make coverage changes, installment plan changes, etc. as you would be able to do with a standard policy change. The lifecycle of the renewal transaction follows the same process as other policy transactions.

<span id="autorenewal" />

Auto-Renewal [#auto-renewal]

Each <ApiLink name="AccountResponse">account</ApiLink> can be assigned an <ApiLink name="AutoRenewalPlanRef">Auto-Renewal Plan</ApiLink>. If one is set, then an <ApiLink name="AutoRenewalResponse">Auto-Renewal</ApiLink> will be created based on the `renewalCreateLeadDays` property on the plan.

If there is not already an Auto-Renewal set on the latest term, one can be created manually with the <ApiLink name="createAutoRenewal">Create Auto-Renewal</ApiLink> API endpoint.

The auto-renewal has a set of triggers to create a <ApiLink name="PolicyTransactionResponse">renewal transaction</ApiLink>, and advance it through acceptance and issuance.

An existing auto-renewal can be updated to change the times that renewal transaction will be accepted and/or issued.

Policies that have an auto-renewal plan that has `generateAutoRenewals` set to `true` will have auto-renewals added to new policy terms at the time they are created. Policies issued with quotes that have this setting will be created with an auto-renewal on their first term.

Auto-Renewal States [#auto-renewal-states]

The `autoRenewalState` property on the auto-renewal has the following meanings:

* `active`: The auto-renewal is active and the trigger times set will continue to advance the renewal transaction through issuance
* `issued`: A renewal transaction for the term has been issued and so the auto-renewal is no longer active
* `doNotRenew`: The renewal transaction will not be accepted or issued, and other renewal transactions for that policy will likewise be prevented from issuance.
* `terminated`: The renewal referenced has reached a terminal state (`invalidated`, `rejected`, `refused`, or `discarded`). There will be no additional plugin calls or events for the auto-renewal.
* `discarded`: The auto-renewal will be inactive with no plugin calls or events.
* `error`: The auto-renewal is in an error state and cannot advance, but it can be <ApiLink name="updateAutoRenewal">updated</ApiLink> via the API.

<span id="auto_renewal_plugin" />

Auto-Renewal Plugin [#auto-renewal-plugin]

For each of the non-null time on the auto-renewal options, before any automatic action, a plugin will fire. You can use this plugin to generate notices, call external systems, etc.

Manually advancing the renewal transaction will not trigger the plugin. However, if the transaction is manually accepted and then allowed to be issued through the auto-renewal workflow, it will trigger the plugin at the expected time with `renewalEvent: issue`.

The renewal options object itself will be sent to the plugin as part of this request:

```
{
    renewalEvent": create | issue | accept
    "autoRenewal": { /* The entire Auto-Renewal as would be sent through the API */ }
}
```

The renewal event will be `create`, `accept`, or `issue`.

And the plugin can return a response of this form to update the auto-renewal:

```
{
    autoRenewalState: active | doNotRenew | discarded
    renewalTransactionType: string
    newTermDuration: integer?
    renewalTransactionCreateTime: DateTime?
    renewalTransactionAcceptTime: DateTime?
    renewalTransactionIssueTime: DateTime?
}
```

<Callout>
  If the `autoRenewalState` is set to `discarded` on the `create` event, then no renewal transaction will be created.
</Callout>

Manual Renewal Operations on an Auto-Renewal [#manual-renewal-operations-on-an-auto-renewal]

It is OK to create a renewal transaction while an auto-renewal is active. You may want to then update the auto-renewal with the locator of the alternate renewal so that it is then managed automatically.

Advancing a renewal transaction manually will not modify the `renewalTransactionAcceptedTime` or `renewalTransactionIssuedTime` properties. These times are specifically reserved for automatic actions and are not updated during manual advancements.

If *any* renewal is issued for that term, either automatically or manually, the auto-renewal for that term, if it exists, will change state to `issued`.

If the renewal transaction referenced by the auto-renewal is manually advanced ahead of the planned automatic events, the plugin will still fire but no automatic action will occur.

Cancellations and Auto-Renew [#cancellations-and-auto-renew]

When a renewal transaction being managed by Auto-Renewal is followed by a cancellation, the renewal will be reset to `draft` state. The auto-renewal will then become `invalidated` (but the renewal itself will *not* be invalidated.) You can manage the renewal manually from that point, or reactiveate the auto-renewal, which will advance the renewal on the next pending trigger time for the auto-renewal.

Do Not Renew [#do-not-renew]

The auto-renewal can put the policy into "Do Not Renew" status <ApiLink name="markPolicyForDoNotRenew">via the API</ApiLink>. It will then have state `doNotRenew`. No renewal transaction for that policy will be permitted to be issued when an auto-renewal with this state exists on the policy.

Use the <ApiLink name="reactivateAutoRenewal">reactivate</ApiLink> endpoint to lift the do-not-renew status.

Renewal with a Gap [#renewal-with-a-gap]

By specifying an `effectiveTime` for the renewal that is after the current policy end time, the renewal will be created with a gap. The new term, and the first segment within that term, will have `startTime` equal to the renewal's `effectiveTime`.

<Callout>
  Unlike [reinstatement with a gap](/features/policy-management/reinstatements#reinstatementWithGap), there is no gap segment created for a renewal with a gap. The gap period is not covered by any terms or segments.
</Callout>

See Also [#see-also]

* [Renewal Management and Auto-Renewal API](/api/policy-management/renewal-management)
* <ApiLink name="AutoRenewalPlanRef">
    Configuration
  </ApiLink>


# Transaction Branching and Invalidation



import Image from 'next/image';

The [transaction stack](/features/policy-management/policy-transaction-stack) is more than just a simple stack. It allows for branching in certain conditions.

Branching is needed to handle situations where there are multiple provisional transactions, of which the insured will accept one of them (or one set of them) and not accept the others. For example, the insured may wish to quote different levels of coverage when considering adding a new exposure to a policy.

The branching structure handles these situations cleanly while maintaining the important invariants we hold to with policy data.

<Callout>
  Even with complex branching, from the point of view of any given transaction, the transactions below it form a stack without branches.
</Callout>

Example [#example]

Consider an auto policy with a Buick covered. Then, Susan (the insured) is considering purchasing a new vehicle for her 16-year-old son: either a 2020 Chevrolet Corvette or a 1983 Toyota Tercel. She can ask for details about both of these:

* First, a policy change transaction is created for the Corvette and advanced to `priced` state. By default, its `basedOn` property will be set to the first transaction's locator.

Then, a separate policy change transaction is created for the Toyota, only this one has its `basedOn` property will be the same as the Corvette transaction's (pointing at the issuance transaction) rather than the existing top level transaction (the Corvette transaction itself).

The branching in the transaction stack now looks like this:

<Image src="/images/transaction_branching/initial.png" alt="initial" width={600} height={250} unoptimized />

<Callout>
  The branches above are not materialized entities in the system; they are shown based on interpreting the transaction stack starting at the transaction heads, Tx2 and Tx3.
</Callout>

Suppose the initial policy rate was $600 per six months, and the rate increase for the two transactions was calculated at +$1800 for the Corvette and +$450 for the Toyota. Because Susan is prudent, she chooses the Toyota, so transaction #3 is issued. The system will automatically invalidate any transaction on a parallel branch from a branch containing an issued transaction, so the branches in the policy now look like this:

<Image src="/images/transaction_branching/branch_b_issued.png" alt="branch b issued" width={600} height={240} unoptimized />

We can assess the state of coverage as usual by starting at the top of the stack for the relevant transaction; here we care about the top-most issued transaction and choose transaction 3, and proceed down to transaction 1. So the interpreted (called local) in-force transaction stack for the policy looks like this:

<Image src="/images/transaction_branching/local_stack.png" alt="local stack" width={600} height={135} unoptimized />

<Callout>
  There is always *exactly one* answer to the question “what is the top-most issued transaction in the stack?” This will often be the starting point for analyzing data about the policy.
</Callout>

Details [#details]

Any transaction can be based on the top of the transaction stack that is in an extendible state (one that's not `discarded` or `rejected` or `refused` or `invalidated`), or alternatively a transaction can be based on a transaction further down the stack, provided that no transaction above that fork point is itself issued (since that would lead to automatic invalidation of the new transaction).

Any transaction must be in the same or earlier state as the transaction it is based on (for example, priced transactions cannot be based on unpriced transactions.)

When branches are formed this way, issuing any transaction in a branch will invalidate all transactions in all parallel branches.

The invalidation discussion above is driven by the need for our stack of issued transactions to be *primary*. That is, there really can't be any alternative to an issued transaction, though the issued transaction itself could be updated with a policy change or even reversed. Also, issued transactions are, in a sense, the “permanent record” of the policy. We can't look at the policy data and ignore the fact that some issued transaction existed, even if has been reversed.

Conversely, non-issued "provisional" transactions aren't primary in the same way as issued transactions, so those are handled differently than issued transactions:

Provisional non-accepted transactions can be taken out of consideration at any time by the client either invalidating them directly or discarding them outright. All transactions above the invalidated or discarded transaction will automatically have their state set to invalidated or discarded, respectively, as well.

Likewise, resetting such transactions will reset those that are above; they would all then be in `draft` state.

`accepted` transactions cannot be discarded, but they can be invalidated.

`invalidated`, `rejected` and `discarded` transactions can usually be completely ignored for most purposes. When the API is queried about transactions, `discarded` transactions will never be included unless that specific transaction is requested by its locator.

<Callout>
  Invalidated and rejected transactions may be filtered out, or perhaps filtered by default unless the user specifically wants them to be included; this is behavior may change.
</Callout>

As mentioned above, all of these provisional transactions will be automatically invalidated when a transaction on a parallel branch is issued.

Elements [#elements]

New elements can be added to a policy by a transaction. There can be more than one “creating” transaction because transactions can add a new element with either this for an element that already exists:

```json
{
	"addElements": [
		{
			"locator": "ABC"
		}
	]
}
```

or with this:

```json
{
	"addElements": [
		{
			"type": "vehicle",
			"data": {
				"make": "Toyota",
				"model": "Camry",
				"vin": "123abc"
			}
		}
	]
}
```

The first approach can be useful when creating different branching alternatives (say, by creating the same element in each branch but varying its initial data.) In such a case, attempting to add an element with an invalid locator or that references a discarded element would cause an error.

<span id="autoRebase" />

Auto-Rebasing [#auto-rebasing]

Auto rebasing is available when a transaction is to be based on some transaction other then the latest created transaction, and transactions that would be invalidated are still desired.

For example, suppose a policy is issued on January 1, and a renewal, effective July 1 is created on June 15, but is only `accepted` but not `issued`.

Then, a policy change effective June 20 needed. You now have three options for how to handle this:

1. Base the policy change on the renewal. It will be a standard out-of-sequence transaction, but to issue it would require issuing the renewal transaction as well.
2. Base the policy change on the issuance transaction. The renewal will be invalidated when the change is issued because it is in a conflicting branch.
3. Base the policy change on the issuance, but also set `autoRebase=true` when issuing it.

For the auto-rebase case, the system will do the following when the policy change transaction is issued:

* It will change the `baseTransactionLocator` of the renewal to be the locator of the new policy change transaction.
* And, it will reset the renewal to `draft` (because it will need to be reprocessed based on possible changes to the policy contents.)

By default, `autoRebase` is set to `true` for these cases. Select `false` if you would prefer conflicting transactions to be invalidated.

All conflicting branches that *can* be rebased *will* be rebased, in the case there is more than one branch.

<Callout>
  Only branches that start with an `effectiveTime` on or after the effective time of the new transaction can be automatically rebased. All others will be invalidated because they would create out-of-sequence situations, and for those a different base transaction should probably be used.
</Callout>

See Also [#see-also]

* [Out of Sequence Transactions](/features/policy-management/out-of-sequence-transactions)
* [The Policy Transaction stack](/features/policy-management/policy-transaction-stack)


# Quick Quotes



import Image from 'next/image';

Overview [#overview]

Quick Quotes are designed to be a lightweight and performant way to provide pricing information to a prospective insured with minimal burden to the prospective insured or agent. They are similar to [quotes](/features/policy-quotation/quotes), except that:

* An [account](/features/accounts) is not required to validate a Quick Quote.
* Not all data on a full quote needs to appear on a Quick Quote. See the [Data Scopes](/configuration/data-extensions/overview#data-scopes) topic for details.
* Quick Quotes do not have an underwriting process.
* Quick Quotes cannot be used to issue policies; rather, they can be used to create *full* quotes as the basis for an issued policy.
* Quick Quotes do not have [documents](/features/documents/document-management).

Workflow [#workflow]

The flow for quick quotes looks like this:

<Image src="/images/policy_quotation/quick_quotes_flow.png" alt="quick quotes flow" width={600} height={222} unoptimized />

<Callout>
  The quick quote will automatically be reset to `draft` state whenever its data is changed. As with [quotes](/features/policy-quotation/quotes), pricing data is deleted when the quick quote is reset.
</Callout>

Quotation [#quotation]

The quick quote can be used to create a full quote with the <ApiLink name="createQuoteFromQuickQuote" /> endpoint.

The quote will be created with applicable data from the quick quote, including all data that has data scope of both quote and quickQuote. The account does not need to be set, but if it is it must reference an existing, valid account.

If the `markAsQuoted` property in the create request is `true`, then the newly created quote will have its `quickQuoteLocator` set to reference the quick quote, and the quick quote will advance to the `quoted` state. In this case the quick quote will no longer be changeable or able to create additional quotes.

Discard [#discard]

Any quick quote may be discarded unless it has been marked as quoted, as described above.

See Also [#see-also]

* [Quotes](/features/policy-quotation/quotes)
* [Quick Quotes API](/api/quick-quotes)


# Quote Groups



import Image from 'next/image';

Quote groups can be used to categorize quote variants that represent a single prospective contract or marketing opportunity.

Quote groups allow you to:

* Manage multiple quote alternatives for the same opportunity
* Ensure that only one of those quotes can reach a certain state, such as `accepted`
* Understand the journey from alternatives to the bound option

Quote groups are established after intake and before binding: once you know enough about the risk to start producing real offers, a quote group can serve as the container for those offers, helping to enforce consistency and prevent redundant policy issuance.

Quote groups have the following structure (see <ApiLink name="QuoteGroupResponse" />):

<Image src="/images/quote-groups/quote-groups-structure.png" alt="Quote groups structure" width={600} height={1028} unoptimized />

<a href="/quote-groups-structure.txt" download>
  Mermaid diagram source
</a>

Usage [#usage]

You can create a new quote group with the <ApiLink name="createQuoteGroup" /> API endpoint, specifying a `name` and `settings`. In settings, you must provide a `stateUniqueness` quote state value that tells the platform that only one quote in the group may be in the specified state at any given time. For example, if you set `stateUniqueness` to `priced`, you could have many quotes in the group in the `draft` or `validated` state, but only one in the `priced` state (and thereafter), which also causes the quote group to be `locked`, preventing quotes from joining or leaving the quote group. In this way, quote groups prevent duplicate business from advancing beyond a specified stage of the quote lifecycle, and also help to ensure that once a quote enters the specified state, you retain a view of which quotes have been considered as part of the production process.

In `settings`, you can also specify a value for `enforceProductUniformity`. This property tells the platform whether the group can have quotes with different products (`false`) or only one product (`true`). The `fieldEnforcementDeclarations` array can contain an array of objects of the form `{ name: string, paths: map<string, string> }`, where the `paths` map keys are product names and the values are field path declarations. The `name` is a custom value you provide. For example, you could have a `fieldEnforcementDeclarations` array like this:

```json
[
	{
		"name": "specialCode",
		"paths": {
			"PersonalAuto": "data.specialCode",
			"CommercialAuto": "data.customCode"
		}
	}
]
```

In this case, where the quote group accommodates quotes with different products (`enforceProductUniformity: false`), the platform will enforce value equality for "producer code", which for `PersonalAuto` is indicated by the field located at `data.specialCode` (a product-level data extension) and for `CommercialAuto` is the field located at `data.customCode`. Data extension paths can be given for fields deeply nested in the data model for your product, but can only involve singular items (meaning no array subscripting).

Aside from data extensions, field enforcement paths can also refer to the following:

* Jurisdiction
* Region
* Producer Code

You can use the <ApiLink name="validateQuoteGroup" /> API endpoint to check the validity of your quote group's enforcement rules against your product configuration.

Updating Quote Groups [#updating-quote-groups]

You may add quotes and remove quotes from a quote group as long as it is in the `open` (not `locked`) state. The <ApiLink name="updateQuoteGroup" /> API endpoint lets you commit constituency updates and change the `name` or `quoteGroupNumber` in a single request. Note, however, that only the `name` of the quote group can be changed when it is in the `locked` state.

The `settings` on a quote group **cannot** be modified after quote group creation. If you need to update the settings in order to change the enforcement field declarations, product uniformity rule, or state uniqueness, create a new group with those settings and place your quotes in the new group.

You may move quotes from one quote group to another, assuming that the quote groups involved are not locked and the quote does not violate the target quote group's settings. A quote can only belong to a single quote group. Adding a quote to a quote group will cause it to be removed from whatever quote group it is already in. Adding a quote to a quote group will fail if the original quote group is `locked`.

<Callout>
  Quotes in the `draft` state can still be updated, even if they belong to a `locked` quote group.
</Callout>

Associated Entities [#associated-entities]

You can create [diary entries](/features/work-management/diaries) referring to quote groups, and can also reference quote groups in other work management features, such as [tasks](/features/work-management/tasks) and [user associations](/features/work-management/user-associations).

<span id="PreferredQuotes" />

Preferred Quotes [#preferred-quotes]

A maximum of one quote locator can be marked as a `preferredQuoteLocator` within each quote group, which can be used to indicate that the specified quote is the most likely quote to be issued.

The `preferredQuoteLocator` can be set when <ApiLink name="createQuoteGroup">creating a quote group</ApiLink> or <ApiLink name="updateQuoteGroup">updating a quote group</ApiLink>. The `preferredQuoteLocator` must refer to a quote within the specified quote group. The `preferredQuoteLocator` can be set to null by setting `resetPreferredQuote` to `true`. If `resetPreferredQuote` is set to `true` and a non-null value is provided for `preferredQuoteLocator`, the request will fail.

If a quote reaches the state specified in the `stateUniqueness` field, that quote locator will become the `preferredQuoteLocator`, and attempts to mark a different quote locator as the `preferredQuoteLocator` will fail. This quote locator will remain marked as the `preferredQuoteLocator` if the quote moves to a different state, until a different quote reaches the state specified in the `stateUniqueness` field.

See Also [#see-also]

* [Quotes](/features/policy-quotation/quotes)


# Quotes



<span id="quotes" />

import Image from 'next/image';

The Quotation ("Quote to Issue") process controls how a new policy is constructed and issued. In Socotra, Quotes are entirely distinct from Policies, with a dedicated workflow.
The nominal flow includes the following events:

* Quote Creation in Draft state
* Quote Validation (including built-in config validation and custom scripted validation)
* Pricing
* Underwriting Checks
* Acceptance
* Policy Issuance

The typical quotation workflow looks like this:

<Image src="/images/policy_quotation/policy_quotation_main_flow.png" alt="policy quotation main flow" width={800} height={263} unoptimized />

Quotes must have all the data required to create an issued policy. Policies are typically created in the `issued` state. There is no such thing as an unissued policy. Therefore:

* All custom data that a policy has for a given product must also be on the quote
* There is no extra requirement or opportunity to inject additional data when the quote is issued and the policy is created, although this may become a future capability
* When a quote is issued, resulting in the creation of a policy, the policy has the same `locator` as the quote

Quote State Flow [#quote-state-flow]

Quotes have a `quoteState` property, which can take any of the following values:

Standard Flow [#standard-flow]

* `draft`: The quote is mutable, so its data, coverage terms, and other attributes (like `startTime`, `endTime`, etc.) can be changed. Newly created quotes are in `draft` state. This is the only state that allows these changes. Note: the `productName` is the basis for the quote, including its validation operations, and as such is not mutable after creation.
* `validated`: The quote has been validated, both against its configuration (based on its product) and any custom validation.
* `priced`: The quote has pricing generated.
* `underwritten`: The quote has passed underwriting checks.
* `accepted`: The quote has been accepted but not yet issued. This state requires successfully passing underwriting checks.
* `issued`: The quote has been issued, and a policy has been created. The resulting policy has the same `locator` as the quote.

Atypical States [#atypical-states]

* `underwritingBlocked`: The quote cannot proceed due to underwriting flags, but is not in a denied state of `declined` or `rejected`.
* `declined`: The quote did not pass underwriting but it can be re-underwritten or reset.
* `rejected`: The quote did not pass underwriting and cannot be re-underwritten or reset, but can be discarded.
* `refused`: Indicates that the customer has decided not to accept coverage. These quotes can be discarded or reset.
* `discarded`: The quote has been disposed of so it cannot be processed further. It will not appear in any response unless directly fetched by locator.

<span id="quote-reset" />

Quote Reset [#quote-reset]

You may wish to change data or attributes on a quote that has been validated or even progressed past validation. Instead of a complex system determining and allowing "safe" mutations under such conditions, Socotra allows quotes to be "reset" to `draft`.

Conditions:

* Quotes in states `validated`, `priced` and `underwritten` can be directly reset.
* A quote that has progressed to an `accepted` state may only be reset if it has first been `refused`.
* Issued quotes result in the creation of a policy, and cannot be reset.

When a quote is reset, it will return to `draft` state, and all data that is mutable in `draft` state can be changed. This includes:

On reset:

* All pricing will be deleted.
* An option will allow underwriting flags and documents to be deleted, cleared, or left intact.

<Callout type="warn">
  The pricing information that is deleted on quote reset is not recoverable.
</Callout>

Grouping [#grouping]

See the [Quote Groups](/features/policy-quotation/quote-groups) guide for details on functionality that allows you to group quotes and enforce uniformity and state uniqueness rules.

<span id="CalculatingEndTime" />

Calculating End Time [#calculating-end-time]

When creating a quote through the <ApiLink name="createQuote">Create a Quote</ApiLink> API endpoint, the `endTime` can be specified manually. However, if no `endTime` value is provided, the system will instead calculate the `endTime` automatically based on the `termDuration`, `durationBasis`, and `startTime` values specified in the <ApiLink name="QuoteCreateRequest">request</ApiLink>.

For example, if the `termDuration` value is set to `6`, and the `durationBasis` value is set to `months`, the system will set the `endTime` value to 6 months after the `startTime`.

When updating a quote through the <ApiLink name="updateQuote">Update a Quote</ApiLink> API endpoint, the system will recalculate the `endTime` the same way if the `resetEndTime` flag is set to `true` in the <ApiLink name="QuoteUpdateRequest">request</ApiLink>.

Time Zones [#time-zones]

Tenants have a default time zone. If a Quote is created with a specified time zone, that time zone will be persisted on the quote. If a Quote is created without specifying a time zone, the time zone will be copied from the tenant's default. Either way, the time zone will be persisted and the tenant default is no longer used for that quote.

Time zones are mutable for quotes in `draft` state only.

<span id="UpdatingAccountLocator" />

Updating Account Locator [#updating-account-locator]

The `accountLocator` associated with a quote can be updated through the <ApiLink name="updateQuote">Update a Quote</ApiLink> API endpoint as long as all of the following criteria are met:

* The quote must be in the `draft` state
* The target account must be in the `validated` state
* The target account must be an account type that has been configured to support the quote's product type

Currencies [#currencies]

As with time zones, quotes will use a specified currency if specified, and otherwise copy the tenant default currency. These, too, will be mutable in `draft` state only.

Error Handling [#error-handling]

When trying to advance multiple steps, say from `draft` to `issued`, the progression can stop because of things like:

* Validation errors
* Underwriting failures
* Plugin errors

If this happens, the response might not have all the information needed to resolve the situation. For example, the <ApiLink name="QuotePriceResponse" /> doesn't have validation error info. To resolve this,

1. Examine the `state` of the quote.
2. See that it is still `draft`, indicating there was a validation failure.
3. Attempt to <ApiLink name="validateQuote">validate</ApiLink> it.

See Also [#see-also]

* [Quotes API](/api/quotes/quotes)
* [Quote Groups](/features/policy-quotation/quote-groups)
* [Quick Quotes](/features/policy-quotation/quick-quotes)


# Appointments



import Image from 'next/image';

Appointments authorize [producers](/features/producer-management/producers) to conduct business in relation to a limited set of [products ](/getting-started/create-a-tenant-configuration-file#what-is-an-insurance-product) and [jurisdictions](/features/jurisdictions), even if a producer is [licensed](/features/producer-management/licenses) to conduct business in relation to additional products and jurisdictions. Each appointment is associated with one producer. Products can be configured to require producers associated with a quote or policy transaction to have a [valid appointment](#AppointmentCriteria) when an underwriting request is processed.

Appointments can contain extension [data](/configuration/data-extensions/overview). Extension data for appointments supports [media](/features/work-management/media) data.

<Callout>
  Appointments do not require producers to be licensed, though this is typically the case.
</Callout>

Lifecycle [#lifecycle]

The following diagram illustrates the lifecycle for appointments:

<Image src="/images/producer-management/appointment-lifecycle.png" alt="Appointment lifecycle" width={500} height={129} unoptimized />

Appointments begin in the `draft` state after creation and will move to the `validated` state following a successful validation request.

Appointments in the `draft` or `validated` states will move to the `discarded` state following a successful discard request. Once appointments are moved to the `discarded` state, they cannot be moved back to the `validated` state and cannot be used again.

Configuration [#configuration]

Before appointments can be created, they must be defined within the `producerAppointments` object in the `producerManagement` <ApiLink name="ConfigurationRef">configuration</ApiLink> object.

For example:

```json
{
	"producerManagement": {
		"producerAppointments": {
			"ExampleProducerAppointment": {
				"abstract": true,
				"extend": "AnotherProducerAppointment",
				"data": {},
				"defaultSearchable": false
			}
		}
	}
}
```

Appointments can be defined as `abstract`, meaning they cannot be created directly. Appointments can inherit data from the appointment specified in the `extend` field.

Extension [data](/configuration/data-extensions/overview) can be defined in the `data` field.

The `defaultSearchable` field can be used to modify [search](/features/search) behavior.

Create an Appointment [#create-an-appointment]

Once your configuration changes have been deployed, create an appointment through the <ApiLink name="createProducerAppointment" /> API endpoint.

Here's an example request:

```json
{
	"type": "ExampleProducerAppointment",
	"appointmentNumber": "34677263",
	"producerCodes": ["43668", "84634"], // An empty list means all producer codes associated with a producer
	"jurisdictions": ["CA", "FL"], // An empty list means all jurisdictions
	"products": ["CommercialAuto", "CommercialProperty"], // An empty list means all products
	"licenses": ["01HSZ77AA61B87613", "01J37GAVZ732AB176"], // Optionally associate the appointment with one or more license locators
	"effectiveTime": "2026-06-15T00:00:00Z",
	"expirationTime": "2027-06-15T00:00:00Z",
	"data": {}
}
```

The request object contains the following fields:

* `type` - The name of an appointment listed in the `producerAppointments` configuration object
* `appointmentNumber` - An appointment number associated with the appointment
* `producerCodes` - The producer codes covered by the appointment
* `jurisdictions` - The jurisdictions covered by the appointment
* `products` - The products covered by the appointment
* `licenses` - License locators associated with the appointment
* `effectiveTime` - When the appointment becomes active
* `expirationTime` - When the appointment expires
* `data` - Extension [data](/configuration/data-extensions/overview)

An empty list for `producerCodes`, `jurisdictions`, or `products` means the appointment applies to all possible values for the given field.

The `producerCodes` field can include producer codes associated with the producer and producer codes associated with producers contained within the producer hierarchy.

Appointment details can be updated through the <ApiLink name="updateProducerAppointment" /> API endpoint. Expired licenses can be renewed by updating the `effectiveTime` and `expirationTime` values.

Use the <ApiLink name="validateProducerAppointment" /> API endpoint to validate an appointment.

Refer to the [Producer Management API](/api/producer-management) index for additional API endpoints.

<span id="AppointmentCriteria" />

Underwriting Criteria for Appointments [#underwriting-criteria-for-appointments]

Products can be configured to require [producers associated with a quote or policy transaction](/features/producer-management/producers#associateProducer) to meet the following underwriting criteria:

* Producers must have a non-expired appointment currently in effect and in the `validated` state for the product.
* Producers must have an appointment associated with the `jurisdiction` that matches the `jurisdiction` associated with the product. See the [Jurisdictions](/features/jurisdictions) feature guide for more information.

These requirements can be enabled by setting the `producerQualification` field at the top level of the <ApiLink name="ProductRef" /> configuration to `appointment`. The default value is `none`.

If the `producerQualification` field is set to `appointment`, and a quote or policy transaction associated with a producer fails to meet the above underwriting criteria, <ApiLink name="underwriteQuote">underwriting</ApiLink> requests will fail, and the system will automatically add an [underwriting](/features/underwriting) flag to the quote or policy transaction. See the [Producers](/features/producer-management/producers#underwritingFlagProducers) feature guide for more information.

Underwriting criteria for appointments are evaluated based on the `producerCode` associated with a quote or policy transaction. The `producerCodeOfRecord` associated with a quote or policy transaction has no effect on underwriting criteria for appointments.

<Callout>
  These requirements are only enforced if a quote or policy transaction is associated with a producer. If a product is not associated with a `jurisdiction`, producers associated with the product are not required to have an association with any specific `jurisdiction`.
</Callout>

Here's an example product configuration:

```json
{
	"products": {
		"CommercialAuto": {
			"producerQualification": "appointment" // none | license | appointment - The default value is none
		}
	}
}
```

See Also [#see-also]

* [Producers](/features/producer-management/producers)
* [Licenses](/features/producer-management/licenses)
* [Producer Management API](/api/producer-management)
* <ApiLink name="ProducerManagementRef" />
* [Jurisdictions](/features/jurisdictions)
* [Data Extensions](/configuration/data-extensions/overview)
* [Underwriting](/features/underwriting)


# Licenses



import Image from 'next/image';

Licenses authorize [producers](/features/producer-management/producers) to conduct business in relation to specific [products ](/getting-started/create-a-tenant-configuration-file#what-is-an-insurance-product) and [jurisdictions](/features/jurisdictions). Each license is associated with one producer. Products can be configured to require producers associated with a quote or policy transaction to have a [valid license](#LicenseCriteria) when an underwriting request is processed.

Licenses can contain extension [data](/configuration/data-extensions/overview). Extension data for licenses supports [media](/features/work-management/media) data.

Lifecycle [#lifecycle]

The following diagram illustrates the lifecycle for licenses:

<Image src="/images/producer-management/license-lifecycle.png" alt="License lifecycle" width={500} height={129} unoptimized />

Licenses begin in the `draft` state after creation and will move to the `validated` state following a successful validation request.

Licenses in the `draft` or `validated` states will move to the `discarded` state following a successful discard request. Once licenses are moved to the `discarded` state, they cannot be moved back to the `validated` state and cannot be used again.

Configuration [#configuration]

Before licenses can be created, they must be defined within the `producerLicenses` object in the `producerManagement` <ApiLink name="ConfigurationRef">configuration</ApiLink> object.

For example:

```json
{
	"producerManagement": {
		"producerLicenses": {
			"ExampleProducerLicense": {
				"abstract": true,
				"extend": "AnotherProducerLicense",
				"data": {},
				"defaultSearchable": false
			}
		}
	}
}
```

Licenses can be defined as `abstract`, meaning they cannot be created directly. Licenses can inherit data from the license specified in the `extend` field.

Extension [data](/configuration/data-extensions/overview) can be defined in the `data` field.

The `defaultSearchable` field can be used to modify [search](/features/search) behavior.

Create a License [#create-a-license]

Once your configuration changes have been deployed, create a license through the <ApiLink name="createProducerLicense" /> API endpoint.

Here's an example request:

```json
{
	"type": "ExampleProducerLicense",
	"licenseNumber": "34677263",
	"producerCodes": ["43668", "84634"], // An empty list means all producer codes associated with a producer
	"jurisdictions": ["CA", "FL"], // An empty list means all jurisdictions
	"products": ["CommercialAuto", "CommercialProperty"], // An empty list means all products
	"effectiveTime": "2026-06-15T00:00:00Z",
	"expirationTime": "2027-06-15T00:00:00Z",
	"data": {}
}
```

The request object contains the following fields:

* `type` - The name of a license listed in the `producerLicenses` configuration object
* `licenseNumber` - A license number associated with the license
* `producerCodes` - The producer codes covered by the license
* `jurisdictions` - The jurisdictions covered by the license
* `products` - The products covered by the license
* `effectiveTime` - When the license becomes active
* `expirationTime` - When the license expires
* `data` - Extension [data](/configuration/data-extensions/overview)

An empty list for `producerCodes`, `jurisdictions`, or `products` means the license applies to all possible values for the given field.

The `producerCodes` field can include producer codes associated with the producer and producer codes associated with producers contained within the producer hierarchy.

License details can be updated through the <ApiLink name="updateProducerLicense" /> API endpoint. Expired licenses can be renewed by updating the `effectiveTime` and `expirationTime` values.

Use the <ApiLink name="validateProducerLicense" /> API endpoint to validate a license.

Refer to the [Producer Management API](/api/producer-management) index for additional API endpoints.

<span id="LicenseCriteria" />

Underwriting Criteria for Licenses [#underwriting-criteria-for-licenses]

Products can be configured to require [producers associated with a quote or policy transaction](/features/producer-management/producers#associateProducer) to meet the following underwriting criteria:

* Producers must have a non-expired license currently in effect and in the `validated` state for the product.
* Producers must have a license associated with the `jurisdiction` that matches the `jurisdiction` associated with the product. See the [Jurisdictions](/features/jurisdictions) feature guide for more information.

These requirements can be enabled by setting the `producerQualification` field at the top level of the <ApiLink name="ProductRef" /> configuration to `license`. The default value is `none`.

If the `producerQualification` field is set to `license`, and a quote or policy transaction associated with a producer fails to meet the above underwriting criteria, <ApiLink name="underwriteQuote">underwriting</ApiLink> requests will fail, and the system will automatically add an [underwriting](/features/underwriting) flag to the quote or policy transaction. See the [Producers](/features/producer-management/producers#underwritingFlagProducers) feature guide for more information.

Underwriting criteria for licenses are evaluated based on the `producerCode` associated with a quote or policy transaction. The `producerCodeOfRecord` associated with a quote or policy transaction has no effect on underwriting criteria for licenses.

<Callout>
  These requirements are only enforced if a quote or policy transaction is associated with a producer. If a product is not associated with a `jurisdiction`, producers associated with the product are not required to have an association with any specific `jurisdiction`.
</Callout>

Here's an example product configuration:

```json
{
	"products": {
		"CommercialAuto": {
			"producerQualification": "license" // none | license | appointment - The default value is none
		}
	}
}
```

Next Steps [#next-steps]

* [Appointments](/features/producer-management/appointments)

See Also [#see-also]

* [Producers](/features/producer-management/producers)
* [Producer Management API](/api/producer-management)
* <ApiLink name="ProducerManagementRef" />
* [Jurisdictions](/features/jurisdictions)
* [Data Extensions](/configuration/data-extensions/overview)
* [Underwriting](/features/underwriting)


# Producer Management Overview



Producer management refers to a set of features within Socotra designed to support producers such as agents and brokers.

Topics [#topics]

* [Producers](/features/producer-management/producers) - Individuals or organizations authorized to conduct business on behalf of an insurance company or potential client, such as agents and brokers
* [Licenses](/features/producer-management/licenses) - Authorize producers to conduct business in relation to specific products and jurisdictions
* [Appointments](/features/producer-management/appointments) - Authorize producers to conduct business in relation to a limited set of products and jurisdictions, even if a producer is licensed to conduct business in relation to additional products and jurisdictions


# Producers



import Image from 'next/image';

Producers refer to individuals or organizations authorized to conduct business on behalf of an insurance company or potential client, such as agents and brokers.

Each producer is associated with one or more producer codes, which can be used to categorize the work performed by a producer. Only one producer can be associated with a given producer code. Each producer can specify a parent producer, forming a producer hierarchy.

Quotes and policies can be associated with a maximum of one producer code at a time.

Products can be configured to require producers associated with a quote or policy transaction to have a valid license or appointment when an underwriting request is processed. See the [Licenses](/features/producer-management/licenses#LicenseCriteria) and [Appointments](/features/producer-management/appointments#AppointmentCriteria) feature guides for more information.

Producers and producer codes can contain extension [data](/configuration/data-extensions/overview). Extension data for producers and producer codes support [media](/features/work-management/media) data.

Lifecycle [#lifecycle]

The following diagram illustrates the lifecycle for both producers and producer codes:

<Image src="/images/producer-management/producer-lifecycle.png" alt="Producer and producer code lifecycle" width={500} height={279} unoptimized />

Producers and producer codes begin in the `draft` state after creation and will move to the `validated` state following a successful validation request.

Producers and producer codes can be moved to the `suspended` state to temporarily prevent them from being used until they are moved back to the `validated` state following a successful unsuspend request. Once producers and producer codes are moved to the `retired` or `discarded` state, they cannot be moved back to the `validated` state and cannot be used again.

<Callout>
  Producer codes cannot be discarded if they are currently associated with a quote that has advanced beyond the `draft` state or a policy.
</Callout>

Configuration [#configuration]

Before producers and producer codes can be created, they must be defined within the `producerManagement` <ApiLink name="ConfigurationRef">configuration</ApiLink> object.

For example:

```json
{
	"producerManagement": {
		"producers": {
			"ExampleProducer": {
				"abstract": true,
				"extend": "AnotherProducer",
				"data": {},
				"defaultSearchable": false
			}
		},
		"producerCodes": {
			"ExampleProducerCode": {
				"abstract": true,
				"extend": "AnotherProducerCode",
				"numberingPlan": "ExampleNumberingPlan",
				"numberingString": "ExampleText",
				"data": {},
				"defaultSearchable": false
			}
		}
	}
}
```

Producers and producer codes can be defined as `abstract`, meaning they cannot be created directly. Producers and producer codes can inherit data from the producer or producer code specified in the `extend` field.

Producer codes can be automatically generated based on the `numberingPlan` and `numberingString` specified in the configuration. We strongly recommend using a separate numbering plan for each producer code type to avoid potential duplication of producer codes. See the [Entity Numbering](/configuration/general-topics/entity-numbering) feature guide for more information.

Extension [data](/configuration/data-extensions/overview) can be defined in the `data` field.

The `defaultSearchable` field can be used to modify [search](/features/search) behavior.

Products can be configured to require producers associated with a quote or policy transaction to have a valid license or appointment when an underwriting request is processed.

Here's an example product configuration:

```json
{
	"products": {
		"CommercialAuto": {
			"producerQualification": "license" // none | license | appointment - The default value is none
		}
	}
}
```

See the [Licenses](/features/producer-management/licenses#LicenseCriteria) and [Appointments](/features/producer-management/appointments#AppointmentCriteria) feature guides for more information.

Create a Producer [#create-a-producer]

Once your configuration changes have been deployed, create a producer through the <ApiLink name="createProducer">Create Producer</ApiLink> API endpoint.

For example:

```json
{
	"type": "ExampleProducer"
}
```

The `type` field refers to the name of a producer defined in the configuration. The `parentLocator` field can be used to specify a parent producer, forming a producer hierarchy.

For example:

```json
{
	"type": "ExampleProducer",
	"parentLocator": "01CH383XHA23A"
}
```

Producer details can be updated through the <ApiLink name="updateProducer">Update Producer</ApiLink> API endpoint.

Use the <ApiLink name="validateProducer">Validate Producer</ApiLink> API endpoint to validate a producer.

Refer to the [Producer Management API](/api/producer-management) index for additional API endpoints.

Create a Producer Code [#create-a-producer-code]

The <ApiLink name="createProducerCode">Create Producer Code</ApiLink> API endpoint can be used to create a producer code.

For example:

```json
{
	"type": "ExampleProducerCode",
	"code": "9217262"
}
```

The `producerLocator` request parameter identifies the producer that will be associated with the producer code. Producer code details can be updated by using the <ApiLink name="updateProducerCode">Update Producer Code</ApiLink> API endpoint.

The `type` field refers to the name of a producer code defined in the configuration. The optional `code` field refers to the producer code. The producer code must be unique. If no producer code is specified, a producer code will be automatically generated based on the [numbering plan](/configuration/general-topics/entity-numbering) specified in the configuration for the producer code `type`.

Use the <ApiLink name="validateProducerCode">Validate Producer Code</ApiLink> API endpoint to validate a producer code.

Refer to the [Producer Management API](/api/producer-management) index for additional API endpoints.

<span id="associateProducer" />

Associate a Producer Code with a Quote or Policy [#associate-a-producer-code-with-a-quote-or-policy]

You can associate a producer code with a quote by adding the following field to the top level of the request object when <ApiLink name="createQuote">creating a quote</ApiLink> or <ApiLink name="updateQuote">updating a quote</ApiLink>:

```json
{
	"producerCode": "9217262"
}
```

The `producerCode` value refers to the `code` value that was used when creating the producer code.

Producer codes associated with a policy can be updated through the <ApiLink name="changePolicy">Create a Policy Change Transaction</ApiLink> API endpoint or any endpoint that accepts a <ApiLink name="ProducersChangeInstructionCreateRequest" /> request object.

Here's an example of a request for the Create a Policy Change Transaction API endpoint:

```json
[
	{
		"action": "producers",
		"setProducerCode": "Example Code 2", // Optional - Update the producer code
		"clearProducerCode": false // Optional - Clear the producer code
	}
]
```

Producer codes must be in the `validated` state before they can be associated with a quote or policy.

Producer Code of Record [#producer-code-of-record]

If a policy has an associated producer code, the policy will also be associated with a producer code of record, which refers to the original producer code for a term. The producer code of record will be set to the current producer code when a renewal transaction is <ApiLink name="issueTransaction">issued</ApiLink>.

The producer code of record associated with a policy can be updated manually through the <ApiLink name="changePolicy">Create a Policy Change Transaction</ApiLink> API endpoint or any endpoint that accepts a <ApiLink name="ProducersChangeInstructionCreateRequest" /> request object. Changes will be applied to a policy once a transaction is <ApiLink name="issueTransaction">issued</ApiLink>.

Here's an example of a request for the Create a Policy Change Transaction API endpoint:

```json
[
	{
		"action": "producers",
		"setProducerCodeOfRecord": "Example Code 3", // Optional - Update the producer code of record
		"revertProducerCodeOfRecord": false // Optional - Set the producer code of record to the current producer code
	}
]
```

Unlike producer codes, producer codes of record can be in the `validated`, `suspended`, or `retired` state when associated with a quote or policy.

<Callout>
  If the `setProducerCodeOfRecord` value is set to the current producer code value, the system will instead process the request as if the `revertProducerCodeOfRecord` value was set to `true` once the transaction is issued.
</Callout>

Producer Code History [#producer-code-history]

The <ApiLink name="fetchPolicySnapshot" /> API endpoint can be used to view the producer code and producer code of record values associated with a policy at a specified point in time. These snapshots account for [out-of-sequence transactions](/features/policy-management/out-of-sequence-transactions) and the reapplication of policy renewals.

Here's an example of the `date` query parameter:

```text
2025-01-01T00:00:00Z
```

<span id="underwritingFlagProducers" />

Add an Underwriting Flag for Invalid Producers [#add-an-underwriting-flag-for-invalid-producers]

If any of the following conditions are true for a quote or policy transaction associated with a producer, <ApiLink name="underwriteQuote">underwriting</ApiLink> requests will fail, and the system will automatically add an [underwriting](/features/underwriting) flag to the quote or policy transaction:

* The producer code, its associated producer, or any of the producer's parent producers are not in the `validated` state.
* The `producerQualification` field is set to `license` in the <ApiLink name="ProductRef" /> configuration for the quote or policy, but the producer does not have a license that meets the [license criteria](/features/producer-management/licenses#LicenseCriteria). See the [Licenses](/features/producer-management/licenses#LicenseCriteria) feature guide for more information.
* The `producerQualification` field is set to `appointment` in the <ApiLink name="ProductRef" /> configuration for the quote or policy, but the producer does not have an appointment that meets the [appointment criteria](/features/producer-management/appointments#AppointmentCriteria). See the [Appointments](/features/producer-management/appointments#AppointmentCriteria) feature guide for more information.

This underwriting flag can be customized through the `underwritingFlag` <ApiLink name="UnderwritingFlagRef">configuration</ApiLink> object.

For example:

```json
{
	"producerManagement": {
		"producers": {
			"ExampleProducer": {
				"abstract": true,
				"extend": "AnotherProducer",
				"data": {},
				"defaultSearchable": false
			}
		},
		"producerCodes": {
			"ExampleProducerCode": {
				"abstract": true,
				"extend": "AnotherProducerCode",
				"numberingPlan": "ExampleNumberingPlan",
				"numberingString": "ExampleText",
				"data": {},
				"defaultSearchable": false
			}
		},
		"underwritingFlag": {
			"level": "none", // none | block | reject | decline | info
			"tag": "Example tag", // Default is "Invalid Producer Qualification"
			"note": "Example note"
		}
	}
}
```

This underwriting flag can be removed from a quote or policy transaction like any other flag. This allows you to complete the underwriting process even if the producer is invalid.

If an `underwritingFlag` configuration is not provided, the system will automatically generate a configuration with `level` set to `info`.

See the [Underwriting](/features/underwriting) and [Underwriting Plugin](/configuration/plugins/underwriting) feature guides for more information on underwriting flags.

Plugins [#plugins]

Precommit Plugin [#precommit-plugin]

The Precommit Plugin can be used to modify the value of a producer or producer code before saving it to the database. See the [Precommit Plugin](/configuration/plugins/precommit) feature guide for more information.

For example:

```java
public class PreCommitPluginImpl implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(PreCommitPluginImpl.class);

    @Override
    public AgencyProducer preCommit(AgencyProducerRequest request) {
        AgencyProducer producer = request.producer();

        return request.producer().toBuilder()
            .data(producer.data().toBuilder().email("first.agency@socotra.com").build())
            .build();
    }

    @Override
    public SubAgencyProducer preCommit(SubAgencyProducerRequest request) {
        SubAgencyProducer producer = request.producer();

        return request.producer().toBuilder()
            .data(producer.data().toBuilder().email("first.subagency@socotra.com").build())
            .build();
    }

    @Override
    public CaliforniaProducerCode preCommit(CaliforniaProducerCodeRequest request) {
        CaliforniaProducerCode producerCode = request.producerCode();

        return request.producerCode().toBuilder()
            .data(producerCode.data().toBuilder().description("added by preCommit").build())
            .build();
    }
}
```

Validation Plugin [#validation-plugin]

The Validation Plugin can be used to execute custom validation logic on a producer or producer code. See the [Validation Plugin](/configuration/plugins/validation) feature guide for more information.

For example:

```java
public class ValidationPluginImpl implements ValidationPlugin {
    private static final Logger log = LoggerFactory.getLogger(ValidationPluginImpl.class);

    @Override
    public ValidationItem validate(AgencyProducerRequest request) {
        AgencyProducer producer = request.producer();

        if (!producer.data().status().equalsIgnoreCase("active")) {
            return ValidationItem.builder()
                .locator(producer.locator())
                .elementType(producer.type())
                .addError("producer must be active")
                .build();
        }

        return ValidationItem.builder().build();
    }

    @Override
    public ValidationItem validate(CaliforniaProducerCodeRequest request) {
        CaliforniaProducerCode producerCode = request.producerCode();

        if (!producerCode.data().status().equalsIgnoreCase("active")) {
            return ValidationItem.builder()
                .locator(producerCode.locator())
                .elementType(producerCode.type())
                .addError("producer code must be active")
                .build();
        }

        return ValidationItem.builder().build();
    }
}
```

Next Steps [#next-steps]

* [Licenses](/features/producer-management/licenses)

See Also [#see-also]

* [Producer Management API](/api/producer-management)
* <ApiLink name="ProducerManagementRef" />
* [Appointments](/features/producer-management/appointments)
* [Data Extensions](/configuration/data-extensions/overview)
* [Precommit Plugin](/configuration/plugins/precommit)
* [Validation Plugin](/configuration/plugins/validation)
* [Underwriting](/features/underwriting)
* [Underwriting Plugin](/configuration/plugins/underwriting)


# Data Lake Data Model



import Image from 'next/image';

The **Data Lake** is Socotra's reporting data model — a single, product-agnostic relational representation of your book of business.

The Data Lake does not have a *custom* data model: the data model is identical across every tenant and product, and doesn't change as your configuration evolves. Configuration changes flow through as new data (rows and values), never as new tables or columns.

The Data Lake is accessible two ways, both exposing this exact same data model: query it directly via [Data Lake Database](/features/reporting/datalake), a hosted SQL database, or replicate it into your own warehouse via [Delta Files](/features/reporting/delta-files). See the [Reporting Overview](/features/reporting/reporting-overview) for guidance on choosing between the two.

See the entity relationship diagrams below for an overview of the Data Lake data model. Although the diagrams are visually separated by platform service below, there is no real service-level distinction between them.

A complete, field-level reference for every table in the Data Lake data model — including detailed relationship mappings between tables — is available in the [Data Lake Table Reference](/features/reporting/tables).

**Policy Tables**

<Image src="/images/data-lake/data-lake-schema.jpg" alt="Data Lake Policy Tables" width={600} height={2291} unoptimized />

**Billing Tables**

<Image src="/images/data-lake/data-lake-schema-billing.jpg" alt="Data Lake Billing Tables" width={600} height={2033} unoptimized />

**Claims Tables**

<Image src="/images/data-lake/data-lake-schema-claims.jpg" alt="Data Lake Claims Tables" width={300} height={7411} unoptimized />

**Work Management Tables**

<Image src="/images/data-lake/data-lake-schema-work-management.jpg" alt="Data Lake Work Management Tables" width={300} height={4242} unoptimized />

**Producer Management Tables**

<Image src="/images/data-lake/data-lake-schema-producer-management.jpg" alt="Data Lake Producer Management Tables" width={300} height={3441} unoptimized />

**Auxiliary Data Tables**

<Image src="/images/data-lake/data-lake-schema-aux-data.jpg" alt="Data Lake Aux Data Tables" width={300} height={3788} unoptimized />

**Moratoriums Tables**

<Image src="/images/data-lake/data-lake-schema-moratoriums.jpg" alt="Data Lake Moratorium Entity Tables" width={300} height={3735} unoptimized />

<Callout>
  Column order may differ between Data Lake Database and Delta Files, though the
  underlying data model and schema — names, types, and meaning — is otherwise
  identical.
</Callout>

Relationship with API Entities [#relationship-with-api-entities]

The Data Lake data model maintains generally consistent, 1:1 relationships with the corresponding API entities, with intentional but minor variations that serve different purposes.

For example, in comparing the Data Lake's `policies` table and the API's `PolicyResponse` object, you can see that they expose many of the same attributes - locator, product name, timestamps, etc. - but that the naming conventions differ slightly.

Any `locator`, or unique identifier, within a Data Lake table will correspond to the locator for that entity in the API. However, not all Data Lake tables will have a corresponding analogue in the API data model. If there's an API entity you'd like to see added to the Data Lake data model, reach out to your Socotra representative.

Some API entities will have multiple related Data Lake tables, particularly in cases where there are objects nested within an API response. For example, the `preferences` object on a quote within the `QuoteResponse` API object lives in the `quote_preferences` table, distinct from the parent `quotes` table. Similarly, some tables have fields not seen in a related API representation, often introduced to facilitate simplified queries against the Data Lake, such as `total_amount` and `total_remaining_amount` in the `invoices` table.

Product Configuration [#product-configuration]

Any custom fields defined for a product within configuration, along with their values, are called data extensions. These persist in the Data Lake as rows of key-value pairs in a variety of data extension tables (`policy_data_extensions`, `quote_data_extensions`, etc.) — this is what it means for the data model to be product-agnostic: a custom field never becomes a new column, it's just a new row. You may want to pivot them into a more conventional columnar form for reporting as part of custom transformations.

Any custom types or plans defined in configuration are also reflected as values for columns on the relevant entity tables, such as `element_type` or `installment_plan_name`.

Records in the Data Lake may not reflect all custom fields, types, or plans defined in configuration — only the scope of data that has actually been generated by the platform. The Data Lake does not persist or reflect any details of the configuration itself.

<Callout>
  Note that records in the Data Lake may reflect custom fields, types, or plans
  that existed in prior, previously deployed versions of your configuration.
</Callout>

The configuration data model API provides the easiest view of the custom fields, types, or plans defined in the latest deployed version of your tenant configuration.

See Also [#see-also]

* [Reporting Overview](/features/reporting/reporting-overview)
* [Data Lake Database](/features/reporting/datalake)
* [Data Lake Delta Files](/features/reporting/delta-files)
* [Data Lake Table Reference](/features/reporting/tables)


# Data Lake Database



import Image from 'next/image';

Data Lake Database is Socotra's hosted MariaDB instance — a relational representation of your book of business, made available for you to query directly with SQL.

This page covers enabling it, connecting to it, and replicating it into your own data infrastructure. For the data model itself — entity relationships, API mapping, data extensions — see [Data Lake Data Model](/features/reporting/data-model).

For a full reference of all Data Lake tables, see the [Data Lake Table Reference](/features/reporting/tables).

Getting Started [#getting-started]

Prerequisites [#prerequisites]

* Socotra-provided credentials and connection details
* IP registration with Socotra to allow connections from your IP
* A MariaDB-compatible client, such as MySQL Workbench or DBeaver

Enablement [#enablement]

Data Lake is not enabled by default. Contact your Socotra representative to request onboarding details.

Once Data Lake is enabled for your business account, all tenants will automatically have their data flow through. However, in many cases this does not mean that your credentials will have access to data for these tenants.

Credentials have access provisioned on a per-schema level. For the default per-tenant schema option, credentials granted access to all tenants in the business account at the time of enablement will not automatically be granted access to schemas for future tenants added to the business account; this access must be explicitly requested. For the per-business account schema option, any credential with access to that schema will by definition have access to all tenants' data in the business account, without any additional provisioning required.

Schema Isolation Options [#schema-isolation-options]

Data Lake is enabled at the [Business Account](/features/business-accounts) level and by default will replicate data for all `test` and `production` tenants in the account.

Users may elect one of the following schema options upon enablement:

* **Per-Tenant Schema (default)** - A separate schema is created for each tenant. While the schemas are identical, their data is unique to each tenant. Querying across tenants is supported via `UNION` statements.
* **Business Account Schema** - A single, consolidated schema contains data for all tenants across the business account.

A tenant identification field (`tenant_locator`) on each table will enable users to distinguish the source of each record, regardless of which schema isolation option is selected.

Changing the selected schema isolation option after enablement will require a period of data inaccessibility.

For details on the data schema itself — table relationships, API entity mapping, data extensions — see the [Data Lake Data Model](/features/reporting/data-model) guide. For conventions like locators, primary keys, and timestamps, see [Schema Conventions](/features/reporting/tables#schema-conventions) in the Table Reference.

Update Frequency [#update-frequency]

Data Lake is continuously loaded with new data from the corresponding tenant, usually within minutes and for the majority of customers, at most 2 hours.

In scenarios involving extremely large volumes or complex data structures, such as bulk ingestion of data via Migration APIs or other large scale use cases, data loads may exceed 2 hours.

Connecting [#connecting]

Any MariaDB-compatible client works, including popular analytical tools:

* Tableau: [https://help.tableau.com/current/pro/desktop/en-us/examples\_mariadb.htm](https://help.tableau.com/current/pro/desktop/en-us/examples_mariadb.htm)
* Microsoft Power BI: [https://mariadb.com/docs/server/clients-and-utilities/graphical-and-enhanced-clients/mariadb-direct-query-adapter-for-microsoft-power-bi](https://mariadb.com/docs/server/clients-and-utilities/graphical-and-enhanced-clients/mariadb-direct-query-adapter-for-microsoft-power-bi)

<Callout>
  Data Lake runs MariaDB version 11.4.x. You can check the specific version at
  any time with the `SELECT VERSION();` query.
</Callout>

Data Replication [#data-replication]

While [Delta Files](/features/reporting/delta-files) is the recommended, purpose-built path for replicating Data Lake data into your own infrastructure, you can also replicate directly from Data Lake using a data integration (ELT) tool such as [Fivetran](https://fivetran.com/).

<Image src="/images/reporting/datalake-db-replication-flow.png" alt="Data Lake replication flow" width={684} height={70} unoptimized />

<Callout type="warn">
  Data Lake does not expose binary logs (binlogs). Tools connecting directly to it must rely on alternative methods to detect changes — such as scanning the database or polling based on the `datalake_updated_timestamp` column — which can add load or complexity depending on the approach.

  If replicating via Fivetran specifically, use its [Teleport Sync](https://fivetran.com/docs/connectors/databases/mariadb#fivetranteleportsync) method, which detects changes using a checksum-based approach, rather than its standard binlog-based CDC method.
</Callout>

Any other tool or method that can connect via provided ODBC/JDBC credentials, provide static IPs for whitelisting, and doesn't require binlog access may also be used to replicate via Data Lake.

Sample Queries [#sample-queries]

Converting Timestamps to a Local Time Zone [#converting-timestamps-to-a-local-time-zone]

Data Lake datetimes are stored as MariaDB `datetime(6)`, in the format `YYYY-MM-DD HH:MM:SS`, with the `(6)` indicating precision down to microseconds. For example: `2024-11-30 12:34:56.123456`.

All datetimes are expressed in Coordinated Universal Time (UTC). Use the MariaDB `CONVERT_TZ` function to convert to a local time zone; for example, to list all policies effective on or after midnight Jan 1st 2024 PST:

```sql
SELECT * FROM `data_lake_my_tenant_locator`.`policies`
WHERE start_time_utc < CONVERT_TZ('2024-01-00 12:00:00', 'America/Los_Angeles', 'UTC');
```

<Callout>
  Refer to the following MariaDB documentation for details.

  * Date and Time Data Types: [https://mariadb.com/docs/skysql-dbaas/ref/xpand/functions/CONVERT\_TZ/](https://mariadb.com/docs/skysql-dbaas/ref/xpand/functions/CONVERT_TZ/)
  * Date and Time Functions: [https://mariadb.com/docs/server/reference/data-types/date-and-time-data-types](https://mariadb.com/docs/server/reference/data-types/date-and-time-data-types)
</Callout>

See Also [#see-also]

* [Reporting Overview](/features/reporting/reporting-overview)
* [Data Lake Data Model](/features/reporting/data-model)
* [Data Lake Delta Files](/features/reporting/delta-files)
* [Data Lake Table Reference](/features/reporting/tables)


# Data Lake Delta Files



import Image from 'next/image';

Delta Files are Socotra's purpose-built mechanism for replicating [Data Lake](/features/reporting/datalake) data into your own infrastructure — the recommended path for production replication (see [Reporting Overview](/features/reporting/reporting-overview#data-lake)).

Appropriately permissioned API clients can list and retrieve a series of incremental diff files via a pair of endpoints optimized for programmatic consumption.

Getting Started [#getting-started]

Delta files are enabled on a business account level. Once enabled for a business account, delta files will be generated for all existing and future tenants and will be automatically available via API.

Delta files are not enabled by default. Contact your Socotra representative and request to have delta files enabled for your business account, providing the name of the business account and the delta file format that you prefer (`sql` or `csv`).

Overview [#overview]

Consuming the Socotra [Data Lake Delta file API](/api/reporting/data-lake-delta-file) involves a recursive, two-step process:

1. Get an index of available files for a given table.
2. Retrieve the necessary individual files.

The delta files are provided in `sql` or `csv` format, containing all requisite upsert statements (for `sql`) or updated records (for `csv`) to replicate table records in the correct format and order.

Delta files in `csv` format follow [RFC:4180](https://www.rfc-editor.org/info/rfc4180/) formatting, with comma delimiters and standard quote escaping for fields containing special characters, and `null` values are represented as empty fields.

In order to ensure a complete and accurate replication, all delta files for a given table's latest schema version must be consumed, and in the order in which they are presented within the index.

While each delta file enumerated in the index array will include metadata related to the generation of that file's contents, it is not recommended to rely on that metadata to derive the correct order of consumption. **The system handles and guarantees this via the ordering of the files in the index array**.

<Callout>
  There may be more delta files available than can be returned in a single index response. See the section on pagination below.
</Callout>

Update Frequency [#update-frequency]

Delta files are generated at most once every two hours following Data Lake updates. If an update occurs within two hours of the previous delta file generation, the system will generate the next set once the interval has elapsed. This two-hour interval is configurable by environment. If no data changes were processed since the last set of files was generated, no new files are generated for that interval — the next set is generated as soon as the next change is processed.

Data changes are themselves processed usually within minutes, and for the majority of customers, at most 2 hours (see [Data Lake Database Update Frequency](/features/reporting/datalake#update-frequency) for the same underlying processing step). Combining both steps, changes to underlying data typically appear in a delta file within two hours, but not more than four. Review each file's `dataProcessedThroughTime` (described below) to understand exactly which underlying data changes it reflects.

Data Availability [#data-availability]

Files are generated in batches. For each batch, the system first selects a single `dataProcessedThroughTime`, then updates every table, with the exception of [Moratoriums tables](/features/reporting/tables#moratoriums-tables), through that same point in time.

Delta files do not become available as each table finishes processing. Instead, the system waits until processing has completed for all non-moratorium tables in the batch, and only then publishes the files. As a result, all non-moratorium tables published in the same batch share the same `dataProcessedThroughTime`.

Moratoriums are updated together as their own group and may complete later than the other tables. As a result, they should not be expected to share the same `dataProcessedThroughTime` as the other tables.

The `dataProcessedThroughTime` represents the latest time of operational data changes included in that batch for the table.

If retrieving data for all tables except moratoriums, pass the `dataProcessedThroughTime` in the request to ensure that data is consistent across all tables. This prevents a scenario where some tables have newer data than others if a new batch is published while you are still fetching files.

For example, passing `lastFile` along with `dataProcessedThroughTime` in the <ApiLink name="fetchDeltaFiles">Fetch List of Delta Files</ApiLink> API request returns all files generated since the last file and up through that processed time.

File Size [#file-size]

The maximum size of a delta file is 10,000 statements (for `sql`) or 10,000 rows (for `csv`).

Schema Versioning [#schema-versioning]

Since the schema of any source Data Lake table may evolve over time, each table consumed via the Delta File API has a corresponding version number. The version number is a sequentially incrementing integer.

When a source table schema update occurs, a new schema version is automatically made available in the Delta File API, and all historical data is regenerated into the newest version. Historical versions will remain available, but updated delta files will not be generated for it.

For each table's schema version, files containing the requisite `drop` and `create` statements are also provided.

On first consumption of the Delta File API, the `create` statement will be needed. The `drop` and `create` files will be used in sequence when a new table schema version becomes available.

Pagination [#pagination]

The number of files available for a specific table and schema version may vary based on data volume and growth rate. The <ApiLink name="DeltaFilesGetResponse">Fetch List of Delta Files API Response</ApiLink> is limited to 100 Delta files per request. If more than 100 files exist, the consuming client must paginate through results.

To ensure complete indexing, use the `lastFile` parameter in the <ApiLink name="fetchDeltaFiles" /> to continue retrieving additional files beyond the initial response.

Client Example [#client-example]

A sample client implementation, illustrating how to consume the API programmatically, is available upon request.

<Callout>
  Additional reference tooling and documentation for consuming the Delta Files
  API and driving the replication patterns below are planned for an upcoming
  release.
</Callout>

Data Replication [#data-replication]

Replicating Data Lake data via Delta Files follows the same general pattern regardless of your destination, and is deliberately tool-agnostic — it works with whatever cloud storage, warehouse, lake, or destination you already use.

One common pattern for exporting delta files is as follows:

1. Files are exported from the Delta Files API and landed into your own staging area.
2. Files are ingested from that staging area into staging tables in your destination.
3. Staging tables are merged/upserted into your final Data Lake tables.

<Image src="/images/reporting/delta-files-replication-flow.png" alt="Delta Files replication flow: the Delta Files API loads into your staging area, then staging tables in your destination, then final Data Lake tables in your destination via merge/upsert" width={1084} height={90} unoptimized />

<Callout type="warn">
  Use `csv` format delta files for import into any non-MariaDB SQL destinations. `csv` files are dialect-agnostic and load cleanly into any destination. `sql` files contain MariaDB-flavored upsert statements, which may not load cleanly against a different SQL dialect.
</Callout>

The platform generates files on a two-hour cadence, but you control how frequently you process them; for example, you may set up a daily process to extract and ingest files.

Example: Databricks or Snowflake [#example-databricks-or-snowflake]

If replicating files into Databricks or Snowflake, [Databricks' Autoloader](https://docs.databricks.com/aws/en/ingestion/cloud-object-storage/auto-loader/) or [Snowflake's Snowpipe](https://docs.snowflake.com/en/user-guide/data-load-snowpipe-intro) can pick up files from your cloud storage staging area automatically and load them into staging tables, ready to be merged/upserted into final Data Lake tables.

Delta Files APIs [#delta-files-apis]

Fetch Delta Files API [#fetch-delta-files-api]

Clients can retrieve an index of the available files for a particular Data Lake table using the <ApiLink name="fetchDeltaFiles">Fetch List of Delta Files</ApiLink> endpoint.

<Callout>
  The `transformationTable` parameter uses a distinct set of `DataLake{entity}` names (e.g. `DataLakePolicies`, `DataLakePolicyTransactions`, `DataLakeInvoices`) that don't match the `snake_case` table names used elsewhere, such as in [Data Lake Database](/features/reporting/datalake) or the [Table Reference](/features/reporting/tables) (e.g. `policies`, `transactions`, `invoices`).

  The `createTableFile` and `dropTableFile` DDL, however, use the standard Data Lake table name (e.g. `CREATE TABLE invoices ...`), matching what you'd see elsewhere in the Data Lake schema.
</Callout>

<ApiSchema name="DeltaFilesGetRequest" />

Sample DeltaFilesGetRequest [#sample-deltafilesgetrequest]

```json
{
	// required
	"tenantLocator": "b6f8aa30-b978-4934-bef3-627XXXXXXXXX",
	"transformationTable": "DataLakeInvoices",

	// optional
	"deltaFileType": "csv",
	"version": 0,
	"dataProcessedThroughTime": "1734542240",

	// optional, mutually exclusive
	// "startTime":1734542240221,
	"lastFile": "DataLakeInvoices/version_0/2025/March/b6f8aa30-b978-4934-bef3-627b0e6edd88_DataLakeInvoices_1451606100_1741713134734.csv"
}
```

<ApiSchema name="DeltaFilesGetResponse" />

<ApiSchema name="DeltaFile" />

Sample DeltaFilesGetResponse [#sample-deltafilesgetresponse]

```json
{
	"version": 0,
	"createTableFile": "DataLakeInvoices/version_0/createTable.sql",
	"dropTableFile": "DataLakeInvoices/version_0/dropTable.sql",
	"s3Bucket": "socotra-kernel-develop-dm-delta",
	"deltaFiles": [
		{
			"deltaFileType": "csv",
			"fileName": "DataLakeInvoices/version_0/2025/March/b6f8aa30-b978-4934-bef3-627b0e6edd88_DataLakeInvoices_1451606100_1741713134934.csv",
			"jobStartTime": 1451606100,
			"jobEndTime": 1741582882,
			"generationTime": 1741713134934,
			"recordCount": 1000,
			"md5HashSum": "a1b2c3d4e5f67890abcdef1234567890"
		},
		{
			"deltaFileType": "csv",
			"fileName": "DataLakeInvoices/version_0/2025/March/b6f8aa30-b978-4934-bef3-627b0e6edd88_DataLakeInvoices_1451606100_1741713135163.csv",
			"jobStartTime": 1451606100,
			"jobEndTime": 1741582882,
			"generationTime": 1741713135163,
			"recordCount": 1000,
			"md5HashSum": "8d4a2f9c1e7b3d5a0f6c8e2b4a9d1f7c"
		},
		{
			"deltaFileType": "csv",
			"fileName": "DataLakeInvoices/version_0/2025/March/b6f8aa30-b978-4934-bef3-627b0e6edd88_DataLakeInvoices_1451606100_1741713135490.csv",
			"jobStartTime": 1451606100,
			"jobEndTime": 1741582882,
			"generationTime": 1741713135490,
			"recordCount": 198,
			"md5HashSum": "e3b0c44298fc1c149afbf4c8996fb924"
		}
	]
}
```

Fetch Delta File API [#fetch-delta-file-api]

Clients can download each individual Delta File using the <ApiLink name="fetchDeltaFile">Fetch Specific Delta File</ApiLink> endpoint. The response will be a streamed file `StreamingResponseBody<string>`.

<ApiSchema name="DeltaFileDownloadRequest" />

See Also [#see-also]

* [Reporting Overview](/features/reporting/reporting-overview)
* [Data Lake Data Model](/features/reporting/data-model)
* [Data Lake Database](/features/reporting/datalake)
* [Data Lake Delta File API Guide](/api/reporting/data-lake-delta-file)


## API Reference

DeltaFilesGetRequest
Properties:
  tenantLocator (uuid, required) — Locator of the tenant corresponding to the data
  transformationTable (Enum DataLakeAccountDataExtensions | DataLakeAccounts | DataLakeAffectedTransactions | DataLakeAuxData | DataLakeBillingHolds | DataLakeClaimDataExtensions | DataLakeClaims | DataLakeCreditDistributions | DataLakeCreditItems | DataLakeDelinquencies | DataLakeDelinquencyReferences | DataLakeDiaries | DataLakeDisbursementDataExtensions | DataLakeDisbursements | DataLakeFaTransactionAccountLines | DataLakeFaTransactions | DataLakeFnolDataExtensions | DataLakeFnols | DataLakeInstallmentItems | DataLakeInstallments | DataLakeInstallmentSettings | DataLakeInvoiceItems | DataLakeInvoices | DataLakeLedgerAccountLineItems | DataLakeLedgerAccounts | DataLakeMoratoriumElections | DataLakeMoratoriums | DataLakeMoratoriumStatuses | DataLakePaymentDataExtensions | DataLakePayments | DataLakePolicies | DataLakePolicyAutoRenewals | DataLakePolicyCoverageTerms | DataLakePolicyDataExtensions | DataLakePolicyElementCharges | DataLakePolicyElements | DataLakePolicyElementTree | DataLakePolicyElementUnderwritingFlags | DataLakePolicyPreferences | DataLakePolicySegments | DataLakePolicyStatuses | DataLakePolicyTerms | DataLakePolicyTransactionChangeInstructions | DataLakePolicyTransactions | DataLakeProducerCodeDataExtensions | DataLakeProducerCodes | DataLakeProducerDataExtensions | DataLakeProducerHierarchy | DataLakeProducers | DataLakeQuoteCoverageTerms | DataLakeQuoteDataExtensions | DataLakeQuoteElementCharges | DataLakeQuoteElements | DataLakeQuoteElementTree | DataLakeQuoteElementUnderwritingFlags | DataLakeQuotes | DataLakeTaskReferences | DataLakeTasks | DataLakeUserAssociations | DataLakeUserQualifications | DataLakeWriteOffs, required) — Name of the desired Data Lake table
  deltaFileType (Enum sql | csv) — The format of the delta files to be returned. Defaults to `sql` if omitted
  version (integer) — Target a specific schema version; defaults to latest if omitted
  startTime (integer) — Files in returned index will all have a `generationTime` later than `startTime`. Format is UNIX timestamp in UTC milliseconds (e.g. 1741713134934)
  lastFile (string) — Only files after this file in the index will be returned. Must provide full `fileName`
  dataProcessedThroughTime (integer) — Only files with a `dataProcessedThroughTime` prior to or equal to this time will be returned. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)

DeltaFilesGetResponse
Properties:
  version (integer, required) — Target a specific schema version; defaults to latest if omitted
  createTableFile (string, required) — Path & name of file with necessary sql statement to create the table in the destination schema
  dropTableFile (string, required) — Path & name of file with necessary sql statement to drop the existing version of the table in the destination schema
  s3Bucket (string, required) — The source S3 bucket required for the <ApiLink name='DeltaFileDownloadRequest' />
  dataProcessedThroughTime (integer, required) — The time of the latest operational change that will be reflected in the data. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)
  deltaFiles (DeltaFile[], required) — The index of individual delta files

DeltaFile
Properties:
  deltaFileType (Enum sql | csv, required) — The format of the delta file
  fileName (string, required) — The name of the delta file
  jobStartTime (integer, required) — The that the job to generate the file began. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)
  jobEndTime (integer, required) — The that the job to generate the file ended. Format is UNIX timestamp in UTC seconds (e.g. 1451606100)
  generationTime (integer, required) — The time that the file was generated. Format is UNIX timestamp in UTC milliseconds (e.g. 1741713134934)
  recordCount (integer) — For files with `deltaFileType` = `csv`, the number of rows in the file, excluding headers
  md5HashSum (string) — For files with `deltaFileType` = `csv`, the MD5 format hashsum for the file contents, including headers

DeltaFileDownloadRequest
Properties:
  tenantLocator (uuid, required) — Locator of the tenant corresponding to the data
  s3Bucket (string) — The name of the S3 bucket as returned by the <ApiLink name='DeltaFilesGetResponse' />. Only required if requesting `createTableFile` or `dropTableFile`, and `deltaFileType` is `csv`
  fileName (string, required) — The name of the file to be requested. Value may be `fileName`, `createTableFile`, or `dropTableFile`

# Metrics



Socotra's Metrics APIs provide visibility into a variety of key business metrics across the entirety of your environment, without the need for any pre-configuration. Reports can be run on GWP, Quote & Policy counts among others, with options to aggregate on a variety of levels including tenants, products and time periods.

Overview [#overview]

The following metrics are currently available:

* Gross Written Premium
* Issued Policies
* Priced Quotes
* New Business Conversion Rate
* Issued Renewals
* Expired Policies
* Renewal Rate

These metric reports can be consumed as raw data via API, or as visualizations via the Reporting Workbench, both of these options also support the export of result data in csv format.

API Usage [#api-usage]

Regardless of the metric, the desired time range that the query should cover must be specified in the request body via the mandatory `startTime` and `endTime` parameters. All other request parameters described below are optional.
Time filtering behaves inclusive on the left, exclusive on the right, meaning `startTime : 2024-01-01` and `endTime : 2025-01-01` will include all of **Jan 1st 2024**, and none of **Jan 1st 2025**.

<Callout type="warn">
  While metric requests can cover future periods, the service design has been optimized for retrospective reporting. Result sets for rates that are future looking are susceptible to distortion and are not recommended or supported.
</Callout>

Within the requests there are a variety of ways to specify how the returned results should be structured, these options generally fall into two categories, **aggregations** and **filters**.

Aggregations [#aggregations]

Aggregation parameters afford control over how the result set is broken out into different groups. The options here include:

* **periodic** - takes a single value from the enum list of `none`, `day`, `week`, `month`, `quarter` or `year`.
  * Will break results into brackets of time per the periodic specified. e.g. a request for Gross Written Premium over a one year time frame with the `periodic` of `month` will return a result set of 12 values, each showing the Gross Written Premium for the respective month. The sum of the amounts in the result set will equal the amount returned had the request been made without any `periodic` specified.

* **groupByTenant** - takes a boolean flag `true` or `false`.
  * If set to true the results are broken out into sets representing each tenant that contributed data. e.g. In an implementation with multiple tenants deployed, a request for Gross Written Premium over a one year time frame with the `groupByTenant` flag set to `true` will return a result set with values for each distinct tenant. The sum of the amounts in the result set will equal the amount returned had the request been made without the `groupByTenant` flag set.

* **groupByProduct** - takes a boolean flag `true` or `false`.
  * If set to true the results are broken out into sets representing each product that contributed data. e.g. In an implementation with multiple products deployed, a request for Gross Written Premium over a one year time frame with the `groupByProduct` flag set to `true` will return a result set with values for each distinct product. The sum of the amounts in the result set will equal the amount returned had the request been made without the `groupByProduct` flag set.

<Callout>
  Aggregation parameters are not mutually exclusive and can be used in combination.
</Callout>

Filters [#filters]

Filter parameters afford control over whether data from certain sources should be included or suppressed from the result sets. The options here include:

* **tenantType** - takes a single value from the enum list of `production` or `test`.
  * Will ensure that result data is only sourced from tenants of the type specified in the request.

* **tenantLocators** - takes an array of tenant locators.
  * Will ensure that result data is only sourced from tenants specified in the request.

* **products** - takes an array of product names.
  * Will ensure that result data is only sourced from entities (quotes, policies, transaction, charges etc) associated with the products specified in the request.

* **currencies** - takes an array of ISO 4217 currency codes.
  * Only applicable to the GWP metric. Will ensure that a distinct result set per currency code specified will be included in the response (assuming that charges in that currency exist and are captured in the broader result set).

Backfill Zero [#backfill-zero]

Sparse data sets or requests that utilize more granular periodic values such as `day` or `week` are more likely to contain observation gaps in the result set. To de-burden direct UI consumption of the APIs from having to deal with observation gaps, the service supports a `backfillZeroes` query parameter in the endpoint url.
Default to false, if set to true the system will inject an observation with a value of `0` into the result set.

<Callout type="warn">
  In order to protect system performance there is a limit of 55 imposed for backfilling zeros that will apply to any sub-set of observations. When requesting a result set for a one year period, the system will support backfilling in combination with a periodic of `years`, `quarters`, `months` or `weeks`. A periodic of `days` in such cases is not supported because the number of observations will exceed 55.
</Callout>

<ApiSchema name="MetricRequest" />

<ApiSchema name="MetricResponse" />

<ApiSchema name="DataPoint" />

Metric Definitions [#metric-definitions]

Gross Written Premium [#gross-written-premium]

**Definition:** The sum of all charges of category `premium` attributed to transactions in state `issued` or `reversed` whose `issuedTime` falls within the specified period, with some adjustments to ensure historical immutability.

Charges in Socotra are generated during the processing of transactions, and they can be both positive and negative. The GWP metric for a period will include charges from all transactions; this includes new business, cancellation, reinstatement, renewal, and mid-term changes. Premium charges related to cancellation and mid-term changes may be negative.

To preserve historical immutability, two mechanisms govern how charges are attributed:

* For reversed transactions, which do not have explicit premium charges generated by the system upon reversal, reversal charges are materialized and booked at the `issuedTime` of the affecting (reversing) transaction rather than the original.
* For reapplied transactions (OOS scenarios), since the reapplication's `issuedTime` is copied from the original, the `issuedTime` of the aggregate transaction created by the OOS is used as the canonical reference instead.

These adjustments ensure that OOS and reversal transactions do not reach back and modify a closed period; instead, they produce a new, visible premium impact in the period in which they occur.

As a result, GWP for a period includes:

* Premium charges from all `issued` and `reversed` transactions, booked at their actual `issuedTime`. In OOS scenarios, reapplications of reversed transactions have their `issuedTime` copied from the original, reversed transaction; however, for the purposes of this calculation, the premium is booked at the `issuedTime` of the aggregate transaction created by the OOS.
* For any `issued` transaction that is later `reversed`, the original premium charges are negated and then materialized as explicit reversal charges, booked at the `issuedTime` of the reversing transaction rather than the original, reversed transaction.

Issued Policies [#issued-policies]

**Definition:** The count of quotes whose `issuedTime` falls within the specified period.
Policies are created in Socotra when a quote is moved to the issued state.

Priced Quotes [#priced-quotes]

**Definition:** The count of quotes which reached the `priced`, or some subsequent, state within the specified period.
Quotes that meet this criteria but are subsequently `discarded` or `reset` will not be included in the count.

New Business Conversion Rate [#new-business-conversion-rate]

**Definition:** The proportion of **Priced Quotes** that go on to become **Issued Policies** within the specified period. More specifically the rate is calculated as the count of **Priced Quotes** in the specified period, divided by the count of **Issued Quotes** in that same specified period, where set of issued quotes is a subset of the identified priced quotes.
Within a result set, a priced quote that gets assigned to a certain period, but whose issuance falls in a subsequent period, will not contribute to the conversion rate of either period.

Issued Renewals [#issued-renewals]

**Definition:** The count of renewal transactions whose `issuedTime` falls within the specified period.
Policies are renewed in Socotra when a transaction of category `renewal` is moved to the issued state.

Expired Policies [#expired-policies]

**Definition:** The count of policies where the `endTime` of the latest term falls within the specified period.
If the `endTime` was set via a cancellation transaction, the policy is not counted as an expiry.

Renewal Rate [#renewal-rate]

**Definition:** The proportion of policies **eligible** for renewal that went on to be renewed in within the specified period.
A policy is deemed eligible for renewal in a given period if either a) the policy was actually renewed in the specified period, or b) the `endTime` of the latest term falls within the specified period.

<Callout>
  For the renewal rate the periodic parameter is mandatory, if it is not set - exception will be raised.
</Callout>

See Also [#see-also]

* [Metrics API](/api/reporting/metrics)
* [Reporting Overview](/features/reporting/reporting-overview)
* [Data Lake Data Model](/features/reporting/data-model)
* [Data Lake Database](/features/reporting/datalake)
* [Data Lake Delta Files](/features/reporting/delta-files)


## API Reference

MetricRequest
Properties:
  groupByProduct (boolean)
  groupByTenant (boolean)
  tenantLocators (uuid[])
  products (string[])
  tenantType (Enum test | production | retired | deleted)
  startTime (datetime, required)
  endTime (datetime, required)
  periodic (Enum none | day | week | month | quarter | year)
  currencies (string[])
  localStartDateAdjusted (date, required)
  localEndDateAdjusted (date, required)

MetricResponse
Properties:
  offset (integer, required)
  count (integer, required)
  startDate (date, required)
  endDate (date, required)
  periodic (Enum none | day | week | month | quarter | year, required)
  results (DataPoint[], required)

DataPoint
Properties:
  productName (string, required)
  tenantLocator (uuid, required)
  currency (string, required)
  dataPointStartDate (date, required)
  value (number, required)

# Reporting Overview



import Image from 'next/image';

Socotra makes your data available via the **Data Lake**, a relational view of your operational data at its most granular level to support any analytical needs. It can be queried directly via SQL for quick insights, or easily replicated into your data infrastructure to support custom transformations.

High-level business insights are also available for fast consumption via **Metrics**.

<Callout>
  Operational data updates are reflected in the below reporting offerings often
  in minutes and typically within two hours. For real-time data needs, consider
  an API-based approach.
</Callout>

Overview [#overview]

Socotra offers the following reporting solutions:

* **[Data Lake Database](/features/reporting/datalake)** — a hosted MariaDB SQL database you can query directly with any SQL client or connect to BI/ELT tools via provided ODBC/JDBC credentials.
* **[Data Lake Delta Files](/features/reporting/delta-files)** — incremental diff files, retrieved via API in `csv` or `sql` format, purpose-built for replicating Data Lake data into your own infrastructure.
* **[Metrics](/features/reporting/metrics)** — a set of pre-aggregated, high-level business metrics, such as Gross Written Premium, accessible via the UI or API with `csv` export.

Both Data Lake Database and Delta Files require enablement; Metrics are enabled by default.

<Callout>
  Data Lake Database and Delta Files both expose the exact same underlying data
  model — they're two different ways of getting at the same data, not two
  different data models.
</Callout>

<Image src="/images/reporting/reporting-architecture-overview.png" alt="Reporting architecture overview: Data Lake accessed directly via Data Lake Database for ad-hoc queries and BI tools, or replicated into your data infrastructure via database replication or the Delta Files API using file-based replication; Metrics accessed via the Metrics API, with the Reporting Workbench UI built on top for visuals and CSV download" width={1157} height={346} unoptimized />

Data Lake [#data-lake]

The Data Lake is a flexible, product-agnostic relational data model that Socotra maintains on your behalf, automatically reflecting your operational data according to your product configuration — no customization required.

Deploy a configuration, start generating data, and the corresponding tables and rows populate automatically. As your product definition evolves with new fields, entity types, and plans, the resulting data simply flows through — ready for you to transform and analyze however your business demands.

For a deeper look at the data model, entity relationships, and how data extensions work, see the [Data Lake Data Model](/features/reporting/data-model) guide. For a detailed listing of all tables and fields, see the [Data Lake Table Reference](/features/reporting/tables).

There are two ways to access your Data Lake data, depending on where you are in your implementation and what your reporting needs look like:

* **Direct SQL Access** - connect to the Data Lake Database directly to execute SQL queries, no pipeline required.
* **Data Replication to Your Data Infrastructure** - replicate your Data Lake data into your destination of choice, such as Databricks or Snowflake, via file-based or database replication.

Direct SQL Access [#direct-sql-access]

Query data directly, no pipeline required. Great for ad-hoc queries, reports, and BI tool visualizations. This is a read-only connection — no custom views or transformations on Socotra's side — and all ODBC/JDBC credential provisioning is managed within the Socotra system upon request.

Complex transformations run directly against the Data Lake Database aren't guaranteed to scale or perform well as data volume grows over time. Consider replicating data into your own data infrastructure as your data volume grows.

Data Replication to Your Data Infrastructure [#data-replication-to-your-data-infrastructure]

As your reporting needs grow, replicating your data to your own data infrastructure gives you room to build and maintain your own transformations, analytics, and governance, and to combine your Socotra data with other sources.

To replicate your Data Lake data into your own cloud storage location, data warehouse/lake, or other destination of choice, consider the two options: **file-based replication** or **database replication**.

File-Based Replication [#file-based-replication]

Delta files are incremental diff files that are generated directly by the system in both `csv` and `sql` format and made available via API. They contain only the rows that changed, making them the most efficient path for replication. They are independent of the Data Lake Database instance entirely.

See the [Data Lake Delta Files](/features/reporting/delta-files#data-replication) replication guide for more information.

Database Replication [#database-replication]

Replicate directly from the Data Lake Database using a data integration (ELT) tool of your choice, such as Fivetran. This can be a good fit if you already have ELT tooling and pipelines in place, since it lets you point that existing setup at the Data Lake Database rather than adopting a new replication mechanism.

The Data Lake Database doesn't expose binary logs (binlogs), so change detection generally relies on scanning or timestamp polling rather than binlog-based CDC. If you're using Fivetran, use its Teleport Sync method, which detects changes via a checksum-based approach rather than its standard binlog-based CDC.

See the [Data Lake Database](/features/reporting/datalake#data-replication) guide for more on replicating via the database.

Metrics [#metrics]

Metrics give you fast access to high-level business insights — such as gross written premium, issued policy counts, and renewal rates — without any enablement or preconfiguration required.

Pull metrics in `csv` or `json` format programmatically via API, or use the Reporting Workbench UI to visualize them and export results as `csv`.

See the [Metrics](/features/reporting/metrics) guide for the full list of available metrics and API details.

Related Offerings [#related-offerings]

For real-time or custom needs beyond Data Lake and Metrics, Socotra also provides:

* **APIs** — Pull any entity in real time and transform it into your own data model. Since Data Lake already provides this in relational form, APIs generally aren't the recommended path for reporting, but they're a good fit for truly real-time needs. See the API Reference section for details.
* **Events** — A full event stream you can consume as another building block for event-driven or custom reporting pipelines. See the [Events](/configuration/general-topics/events) guide for details.
* **Search** — Request lists of entities matching specific criteria in real time via API. See the [Search](/features/search) guide for details.

See Also [#see-also]

* [Data Lake Data Model](/features/reporting/data-model)
* [Data Lake Database](/features/reporting/datalake)
* [Data Lake Delta Files](/features/reporting/delta-files)
* [Data Lake Table Reference](/features/reporting/tables)
* [Metrics](/features/reporting/metrics)


# Diaries



Overview [#overview]

Diaries are a structured, user-driven log of notes in relation to a given entity. For example, a running series of notes relating to management of a policy transaction (such as a cancellation and the reasons for it, or notes of conversations with the insured), could be captured in a series of diary entries.

You can associate diaries with the following entities:

* Policies
* Quotes
* Quote Groups
* Transactions
* Underwriting flags
* Accounts
* Invoices
* Payments
* FNOLs
* Tasks
* Elements

<Callout>
  Diary entries can be associated with elements within a quote or policy segment using their `staticElementLocator`. This locator remains the same throughout the quote and policy lifecycle, meaning a diary entry associated with a quote element will remain associated with all of its corresponding policy segment elements.
</Callout>

Diary Entries [#diary-entries]

The primary diary element is called a <ApiLink name="DiaryEntryResponse">Diary Entry</ApiLink>. For each of the supported entity types, a series of entries can be created. Each is timestamped and can be given an optional `category` value.

Diary entries are referred to by either a `locator` (which is specific to a given diary entry) or a `referenceLocator` (such as a quote or policy locator) which will indicate all the diary entries for that entity. The endpoints <ApiLink name="fetchLatestDiaryEntryByLocator" /> or <ApiLink name="fetchLatestDiaryEntriesByReference" /> are used for these two types of retrieval. The former will return a single diary entry, and the latter can return multiple entries.

Revisioning [#revisioning]

When a diary entry for an entity is updated with the <ApiLink name="updateDiary" /> endpoint, old entries are not removed. Rather, they remain accessible with the <ApiLink name="fetchAllDiaryEntriesByLocator" /> endpoint. To see only the latest entries, use either the <ApiLink name="fetchLatestDiaryEntryByLocator" /> or <ApiLink name="fetchLatestDiaryEntriesByReference" /> endpoints.

Discard [#discard]

Diary entries may be <ApiLink name="discardDiary">discarded</ApiLink>, which means they will no longer be available except by direct reference by locator.

<Callout>
  The discard function will discard the entry as a whole, including all revisions. To keep the entry, you may want to simply <ApiLink name="updateDiary">update</ApiLink> it, which will exclude the existing entry from the "latest" fetch endpoints.
</Callout>

See Also [#see-also]

* [Diary API](/api/aux-data/diary)


# Media



Overview [#overview]

Socotra allows you to upload files and manage associations with system entities. This supports a range of "capturing document" use cases, such as linking a set of uploaded photos to a ["first notice of loss" (FNOL)](/features/claims/fnol) record or a quote.

Media data may be associated with the following entities:

* Policies
* Policy Transactions
* Quotes
* Tasks
* User Associations
* First Notice of Loss (FNOL) records
* Diaries
* Producers
* Producer codes
* Licenses
* Appointments

As with diaries, media data are versioned. The Media Data API exposes "latest" endpoint analogues for all fetch endpoints as a convenience.

Example [#example]

You could add a photo linked to a quote by <ApiLink name="createMediaData">creating media data</ApiLink>. After doing so, you could see the latest edition of that media entry in the list of media items associated with the quote by using <ApiLink name="fetchLatestMediaDataByReference" />. You'll get a response like the following:

```json
{
	"listCompleted": true,
	"items": [
		{
			"locator": "01JSJ5VJYY13NWRY90HZN86HZP",
			"filename": "iCSYeKcoFftqYvlcgDhe",
			"title": "iCSYeKcoFftqYvlcgDhe",
			"tag": "iCSYeKcoFftqYvlcgDhe",
			"references": [
				{
					"type": "quote",
					"locator": "01JSJ5KRK761CNTHRFE2J6Y9QS"
				}
			],
			"createdAt": "2025-04-23T20:36:30Z",
			"createdBy": "dc68c494-6918-487a-bf08-58c2983175dc",
			"updatedAt": "2025-04-23T20:36:30Z",
			"updatedBy": "dc68c494-6918-487a-bf08-58c2983175dc"
		}
	]
}
```

You can use the locator for the media data entry to download it, update it, delete it, or to view different versions of the file via API.

See Also [#see-also]

* [Media API](/api/aux-data/media)


# Tasks



Overview [#overview]

*Tasks* represent work that users are expected to perform, often in relation to one or more system entities. They can be any of a set of types. Tasks can be used in a wide variety of situations, such as:

* An underwriter that needs to verify that a property inspection has been done satisfactorily
* A customer service representative that needs to contact an insured about a past-due invoice or pending lapse
* An agent coordinator that needs to ensure agents' and brokers' training and qualification process is complete

<Callout>
  Tasks differ from [User Associations](/features/work-management/user-associations) in that they represent a discrete activity that is no longer active once the task is completed. User associations typically represent longer-term associations where a user has an ongoing responsibility with regard to a particular entity.
</Callout>

Configuration [#configuration]

Each task type needs to be configured. In configuration, we might have:

```json
{
	"tasks": {
		"customerService": {
			"customerInquiry": {
				"defaultDeadlineDays": 1.5
			}
		},
		"underwriting": {
			"inspectionReview": {
				"defaultDeadlineDays": 2.25,
				"underwritingBlock": true
			}
		}
	}
}
```

<ApiSchema name="TaskTypeRef" />

Here we have two task types defined: `customerInquiry` has category `customerService`, and `inspectionReview` has category `underwriting`.

Deadlines [#deadlines]

Tasks have an optional `deadlineTime`, which represents the time by which the user is expected to complete the task.

If the `deadlineTime` for an incomplete task is changed, the task's state would also change as needed. For example, if changing from the past to the future, the state would change from `pastDeadline` to `active`.

<Callout>
  Future releases will enable automated task reassignment and/or escalation of tasks to supervisors or alternative users for tasks that are incomplete at their deadline time. An alternative `escalationTime` will allow escalation at a different time if desired.
</Callout>

Creation of Tasks [#creation-of-tasks]

Tasks are created manually via discrete calls to the Socotra API or programmatically via integration or plugins.

Tasks may also be created as part of underwriting flag creation via the inclusion of the optional `taskCreation` property in any <ApiLink name="UnderwritingFlagCreateRequest" />. The `taskCreationResponse` property of the <ApiLink name="UnderwritingFlagResponse" /> will contain the status of the resulting task creation.

The following changes can be made via the API to an existing task:

* Changing or removing the assigned user
* Completing it
* Cancelling it
* Changing the `deadlineTime`
* Adding or removing references
* Adding underwriting flag associations (to any type of flag, not just block)
* Removing underwriting flag associations

Underwriting Blocks [#underwriting-blocks]

When tasks are created and have types that are configured with `blocksUnderwriting: true`, then an underwriting flag will be created on the task's reference entities of type <ApiLink name="QuoteResponse">Quote</ApiLink> or <ApiLink name="PolicyTransactionResponse">Policy Transaction</ApiLink>. Likewise, if a quote or policy transaction is later added to the task, a flag will be created. Flags created this way are always of type `block`.

Underwriting flags have an optional `taskLocator` property to track this association. When there is a link between a task and an underwriting flag, completing or cancelling the task will clear the flag (but not vice versa: clearing a flag manually doesn't complete the task.)

You can update tasks to add underwriting flags that already exist. These too will clear when the tasks are completed or cancelled.

Task Diaries [#task-diaries]

Like other entities, Tasks are able to have associated [Diaries](/features/work-management/diaries).

See Also [#see-also]

* [Work Management API](/api/work-management)


## API Reference

TaskTypeRef
Properties:
  defaultDeadlineDays (number, required)
  blocksUnderwriting (boolean, required)
  numberingPlan (string)
  numberingString (string)

# User Associations



Overview [#overview]

User associations are a relationship between system users and various entities within the system. These are useful for creating lists of entities that are relevant to a user, without needing to do a proactive search or using an external tracking system. Associations share some similarities with [tasks](/features/work-management/tasks), but function separately from tasks.

User associations also have roles that describe the reason for the association.

The following are the types of relationships that can be modelled with user associations:

* User Jack Smith is the lead underwriter for quote 1234
* User Sally Jones is one of several associate underwriters for quote 4567
* User Frank Brown is a fraud investigator for claim C9043
* User Tina Wilson was a customer support responder for account A8894, but that association is no longer active

In each of these cases, there is a relationship between a single entity and a single user, described by a role that describes the relationship.
Some association roles, like Lead Underwriter above, can be made exclusive: only one user may have that role at a time for that entity for these kinds of roles. Others are non-exclusive, and multiple users may have the same role.

Scope [#scope]

The following entities can have user associations:

* Accounts
* Quotes
* Quick Quotes
* Quote Groups
* Policies
* Policy Transactions
* Invoices
* Underwriting Flags

Configuration [#configuration]

The work management block within configuration contains information about user associations and roles. It might look like this:

```json
{
	"workManagement": {
		"userAssociationRoles": {
			"underwriter": {
				"appliesTo": ["quote", "transaction"],
				"exclusive": false,
				"qualification": {}
			},
			"leadUnderwriter": {
				"appliesTo": ["quote", "transaction"],
				"exclusive": true,
				"qualification": {
					"underwriting": "uw4+"
				}
			},
			"claimsAssociate": {
				"appliesTo": ["fnol", "claim"],
				"qualification": {
					"claimsAdjuster": "ca2+",
					"claimsManager": "cm1+"
				}
			}
		},
		"qualifications": {
			"underwriting": ["uw1", "uw2", "uw3", "uw4", "uw5"],
			"claimsAdjuster": ["ca1", "ca2", "ca3", "ca4"],
			"claimsManager": ["cm1", "cm2", "cm3"]
		}
	}
}
```

Here, we see that there can be more than one `underwriter` on a claim or subclaim, but only one `leadUnderwriter`. Moreover, not just any user can be a lead underwriter; this is reserved for those users designated as having qualification `uw4+` or higher. See Role Qualification below for more details.

Configuration changes to associations and qualifications are all considered "safe" and can be deployed without restriction. As with other parts of the configuration, removal of an association type or qualification from a configuration set will result in those items being left as-is when it is deployed.

<span id="RoleQualification" />

Role Qualification [#role-qualification]

Association roles can be configured as requiring qualification, which means that at least one of the <ApiLink name="UserQualification">qualifications</ApiLink> listed must be possessed by a user to be assigned that role. A `+` symbol means that that qualification, or one later in the list of qualifications for that qualification type, is acceptable.

The test for qualification when there are multiple items listed under qualification is an "OR" test. For example, for the `claimsAssociate` role above, users with either `ca2` (or higher) or `cm1` (or higher) will be qualified.

User Association State [#user-association-state]

Each <ApiLink name="UserAssociation" /> will have an `associationState` which describes its status:

* `active`: This is the typical case, and indicates the user is currently involved with the entity
* `completed`: The user no longer has a need for the entity, and the association history is maintained
* `unassigned`: The association does not have a user
* `discarded`: The association should no longer be returned when fetching associations for a user or entity

Association History [#association-history]

When an association is created, unassigned, completed, or uncompleted, this information is stored in the association history, which is retrievable on a user or entity basis.

See Also [#see-also]

* [Work Management API](/api/work-management)


# Work Management Overview



Work management refers to a set of features within Socotra designed to support users with their work.

For example:

* Recording and reviewing human-authored contextual data associated with quotes, policies, and other entities
* Being alerted to important system events
* Having direct access to data that relates to their work
* Organizing and tracking important tasks that require attention
* Defining relationships among workgroups and other parts of the organization

Work management is supported by these features:

* [Diaries](/features/work-management/diaries) - Human-written textual information with history that can be associated with quotes, policies, and other entities
* [Tasks](/features/work-management/tasks) - These are concrete units of work for individual users. Tasks might include property inspections, reviews, and approvals.
* [User Associations](/features/work-management/user-associations) - Relationships between users and entities such as accounts or policies, and the specific role a user has in that relationship
* [Workgroups](/features/work-management/workgroups) - Hierarchical groupings of tasks, users, and entities such as quotes and policies
* [Auto-Assign](/features/work-management/workgroups#AutoAssign) - Automatically assigns tasks and creates associations.
* [Workplans](/features/work-management/workplans) - Templates that automatically create tasks and assign tasks in response to system events

The following features are under development:

* **Notifications** - Alerts users to important events triggered by internal or external activity

See Also [#see-also]

* [Work Management API](/api/work-management)


# Workgroups



Workgroups are hierarchical groupings of [tasks](/features/work-management/tasks), users, and entities such as quotes and policies.
The <ApiLink name="autoAssign">Auto-Assign</ApiLink> API endpoint can be used to automatically assign tasks and create [associations](/features/work-management/user-associations) between users and entities.

Workgroups can have multiple child workgroups, but only one parent workgroup. Multiple users can be assigned to the same workgroup.

Create a Workgroup [#create-a-workgroup]

The <ApiLink name="createWorkgroup">Create Workgroup</ApiLink> API endpoint can be used to create workgroups and add users to workgroups.

For example:

```json
{
	"name": "Level2.1",
	"users": ["n8ec-akn2-nad9"],
	"tag": "tag"
}
```

```json
{
	"name": "Level2.2",
	"users": ["jae8-3ndc-bd23"],
	"tag": "tag"
}
```

Once these workgroups have been created, you can create a parent workgroup and specify child workgroups by including the locators of the above workgroups in the list of `subgroups`.

For example:

```json
{
	"name": "Level1",
	"subgroups": ["01NCA87CDD8D", "01SNCZOA83BC"],
	"users": ["vf23-nd72-7bd3"],
	"tag": "tag"
}
```

You can also specify a parent workgroup when creating a workgroup by specifying the locator of a parent workgroup in the `parentLocator` field.

For example:

```json
{
	"name": "Level1",
	"parentLocator": "01DVS65J7BSL",
	"users": ["vf23-nd72-7bd3"],
	"tag": "tag"
}
```

The <ApiLink name="listWorkgroups">List Workgroups</ApiLink> and <ApiLink name="getWorkgroup">Get Workgroup</ApiLink> API endpoints can be used to retrieve workgroup details. See the [Work Management API](/api/work-management) index for additional workgroup API endpoints.

<span id="AutoAssign" />

Auto-Assign [#auto-assign]

The <ApiLink name="autoAssign">Auto-Assign</ApiLink> API endpoint can be used to automatically assign a task to a user within a workgroup hierarchy.

Auto-Assigning Tasks to Users [#auto-assigning-tasks-to-users]

The auto-assign algorithm will first attempt to assign the task to a user within the specified workgroup who has an [association](/features/work-management/user-associations) with the specified entity. If no such users are found within the workgroup, the algorithm will traverse the workgroup hierarchy using the specified `traversal` method until it finds a workgroup that contains a user who has an association with the specified entity, and will assign the task to that user.

If the algorithm finds multiple candidates within a workgroup, it will assign the task based on round robin selection, meaning it will select the user who has gone the longest without being auto-assigned a task.

Here's an example of an auto-assign request to assign an existing task to a user who is currently associated with a quote:

```json
{
	"taskLocator": "01HBL21O8VAZ",
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote",
	"workgroupLocator": "01DVS65J7BSL"
}
```

You can also specify a new task that will be created before the auto-assign algorithm attempts to assign the task.

For example:

```json
{
	"task": {
		"description": "Example description",
		"type": "underwritingReferral"
	},
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote",
	"workgroupLocator": "01DVS65J7BSL"
}
```

Auto-Assigning Tasks to Workgroups [#auto-assigning-tasks-to-workgroups]

If no candidates are found within the workgroup hierarchy, the algorithm will refer to the value of the `assignToGroup` field to determine whether it should then attempt to assign the task to the workgroup specified in the request instead of a user:

* `never` - The task will never be assigned to the workgroup.
* `ifNotAssigned` - The task will be assigned to the workgroup only if the task is not currently assigned to a different workgroup. This is the default value.
* `always` - The task will always be assigned to the workgroup.

Here's an example of an auto-assign request that specifies a value for the `assignToGroup` field:

```json
{
	"taskLocator": "01HBL21O8VAZ",
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote",
	"workgroupLocator": "01DVS65J7BSL",
	"assignToGroup": "never"
}
```

Traversal [#traversal]

The auto-assign algorithm can traverse a workgroup hierarchy using either a `depthFirst` or `breadthFirst` approach. Sibling workgroups are ordered by workgroup locator in ascending order.

By default, the `traversal` approach is `none`, meaning the auto-assign algorithm will only attempt to assign tasks to users within the workgroup specified in the request, but will not traverse the workgroup hierarchy when attempting to find users.

Here's an example of an auto-assign request that specifies a value for the `traversal` field:

```json
{
	"taskLocator": "01HBL21O8VAZ",
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote",
	"workgroupLocator": "01DVS65J7BSL",
	"traversal": "breadthFirst"
}
```

Auto-Assigning Qualified Users [#auto-assigning-qualified-users]

If a value for the `associationRole` field is specified in the request, the algorithm will only assign the task to a user with at least one of the [qualifications](/features/work-management/user-associations#RoleQualification) necessary to be assigned to the specified association role. See the [User Association](/features/work-management/user-associations) guide for more information.

<Callout>
  Ensure users have the necessary qualifications before attempting to auto-assign tasks. User qualifications can be updated using the <ApiLink name="updateUserQualifications">Update User Qualifications</ApiLink> API endpoint.
</Callout>

Here's an example of an auto-assign request that specifies a value for the `associationRole` field:

```json
{
	"taskLocator": "01HBL21O8VAZ",
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote",
	"workgroupLocator": "01DVS65J7BSL",
	"associationRole": "leadUnderwriter"
}
```

Auto-Assigning Tasks Without Specifying a Workgroup [#auto-assigning-tasks-without-specifying-a-workgroup]

If no workgroup is provided in the request, the algorithm will attempt to assign the task to a user who is associated with the specified entity, regardless of whether the user has been added to a workgroup. For this use case, if no such users are found, the request will fail, regardless of the value of the `assignToGroup` field. If the algorithm finds multiple candidates, it will assign the task based on round robin selection.

Here's an example of an auto-assign request that doesn't specify a `workgroup`:

```json
{
	"taskLocator": "01HBL21O8VAZ",
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote"
}
```

Using Auto-Assign to Create Associations [#using-auto-assign-to-create-associations]

If no task is provided in the request, the algorithm will attempt to create an [association](/features/work-management/user-associations) between a user and the entity specified in the request. For this use case, if no such users are found, the request will fail, regardless of the value of the `assignToGroup` field. If the algorithm finds multiple candidates, it will assign the task based on round robin selection.

Here's an example of an auto-assign request to create an association:

```json
{
	"referenceLocator": "01PWA37PACZQ",
	"referenceType": "quote"
}
```

Next Steps [#next-steps]

* [Workplans](/features/work-management/workplans)

See Also [#see-also]

* [Tasks](/features/work-management/tasks)
* [User Associations](/features/work-management/user-associations)
* [Work Management API](/api/work-management)


# Workplans



Workplans are templates that automatically create [tasks](/features/work-management/tasks), assign tasks, and create [associations](/features/work-management/user-associations) in response to system [events](/configuration/general-topics/events) such as policy creation and quote validation.

When an event specified within the `workplanTriggers` <ApiLink name="ProductRef">configuration</ApiLink> object is triggered, the system will attempt to create the task specified in the workplan and [auto-assign](/features/work-management/workgroups#AutoAssign) the task, or create an association between a user and the entity specified in the workplan. See the [Workgroups](/features/work-management/workgroups) feature guide for more information.

Two [plugins](/configuration/plugins/overview) can be implemented to customize workplan functionality, which are executed in the following order: The [Workplan Selection Plugin](#WorkplanSelectionPlugin), then the [Workplan Execution Plugin](#WorkplanExecutionPlugin). The Workplan Selection Plugin specifies which workplans will be executed when an event is triggered. The Workplan Execution Plugin modifies the tasks and associations contained within each workplan returned by the Workplan Selection Plugin.

Configuration [#configuration]

The `workplanTriggers` configuration object specifies which workplans will be executed when an event occurs. Workplans are identified by the value specified in their `name` field.

For example:

```json
{
	"workplanTriggers": {
		"policy.quote.create": ["exampleWorkplan"],
		"policy.quote.issue": ["anotherWorkplan", "oneMoreWorkplan"]
	}
}
```

A comprehensive list of events can be found [here](/configuration/general-topics/event-definitions).

Once this configuration has been deployed, the system will begin executing the above workplans in response to the specified events.

Create a Workplan [#create-a-workplan]

The <ApiLink name="createWorkplan">Create Workplan</ApiLink> API endpoint can be used to create a workplan.

For example:

```json
{
	"name": "exampleWorkplan",
	"defaultGroup": "exampleWorkgroup",
	"items": [
		{
			"task": {
				"description": "Example task",
				"type": "underwritingReferral"
			},
			"referenceType": "quote",
			"referenceLocator": "01LAV31DAC8F"
		}
	]
}
```

When the workplan in the above example is executed in response to the event defined in the `workplanTriggers` configuration object, the auto-assign algorithm will attempt to create the specified `task` and assign it to a user in the specified workgroup who has an [association](/features/work-management/user-associations) with the specified quote.

See the [Workgroups](/features/work-management/workgroups) feature guide for more information on the auto-assign algorithm.

Workgroups specified in the request must be created manually using the <ApiLink name="createWorkgroup">Create Workgroup</ApiLink> API endpoint before the workplan is executed. Otherwise, workplan execution will fail.

The <ApiLink name="listWorkplans">List Workplans</ApiLink> and <ApiLink name="getWorkplan">Get Workplan</ApiLink> API endpoints can be used to retrieve workplan details. See the [Work Management API](/api/work-management) index for additional workplan API endpoints.

Plugins [#plugins]

<span id="WorkplanSelectionPlugin" />

Workplan Selection Plugin [#workplan-selection-plugin]

The Workplan Selection Plugin specifies which workplans will be executed when an event is triggered.

The request object contains an event and its associated workplans as specified in the `workplanTriggers` configuration object. The response object contains a list of workplans that will be executed in response to the event specified in the request object. Workplans can be added or removed as needed from the list of workplans returned by the response object.

If this plugin is not implemented, the system will execute workplans based on the `workplanTriggers` configuration object.

The following implementation example filters workplans specified in the `workplanTriggers` configuration object based on workplan `name`:

```java
public class WorkplanSelectionPluginImpl implements WorkplanSelectionPlugin {
    private static final Logger log = LoggerFactory.getLogger(WorkplanSelectionPluginImpl.class);

    @Override
    public WorkplanSelectionResponse selectWorkplans(WorkplanSelectionRequest workplanSelectionRequest) {
        if (workplanSelectionRequest.workplansSelection().eventType().equals("policy.quote.create")) {
            List<WorkplanSelectionItem> filteredWorkplans = workplanSelectionRequest.workplansSelection().workplans().stream()
                    .filter(workplan -> workplan.name().startsWith("quote"))
                    .collect(Collectors.toList());

            return WorkplanSelectionResponse.builder()
                    .workplansToExecute(filteredWorkplans)
                    .build();
        } else {
            return WorkplanSelectionResponse.builder()
                    .workplansToExecute(workplanSelectionRequest.workplansSelection().workplans())
                    .build();
        }
    }
}
```

<span id="WorkplanExecutionPlugin" />

Workplan Execution Plugin [#workplan-execution-plugin]

The WorkplanExecutionPlugin modifies the tasks and associations contained within each workplan returned by the WorkplanSelectionPlugin.

The request object contains a workplan and the tasks and associations contained within the workplan. The response object contains a list of tasks and a list of associations that will be created when the workplan is executed. Tasks and associations can be added or removed as needed from the lists returned by the response object.

If this plugin is not implemented, the system will create the pre-defined tasks and associations for a given workplan when the workplan is executed.

The following implementation example modifies tasks based on workplan `name`:

```java
public class WorkplanExecutionPluginImpl implements WorkplanExecutionPlugin {
    private static final Logger log = LoggerFactory.getLogger(WorkplanExecutionPluginImpl.class);

    @Override
    public WorkplanExecutionResponse decorateWorkplanExecution(WorkplanExecutionRequest workplanExecutionRequest) {
        List<TaskCreateRequest> modifiedTasks = new ArrayList<>(workplanExecutionRequest.execution().tasks());
        List<UserAssociationCreateRequest> associations = new ArrayList<>(workplanExecutionRequest.execution().associations());

        if (workplanExecutionRequest.execution().workplanName().equals("underwritingReview")) {
            modifiedTasks.remove(0);
        }

        return WorkplanExecutionResponse.builder()
                .tasks(modifiedTasks)
                .associations(associations)
                .build();
    }
}
```

See Also [#see-also]

* [Workgroups](/features/work-management/workgroups)
* [Tasks](/features/work-management/tasks)
* [User Associations](/features/work-management/user-associations)
* [Auto-Assign](/features/work-management/workgroups#AutoAssign)
* [Events](/configuration/general-topics/events)
* [Event Definitions](/configuration/general-topics/event-definitions)
* [Work Management API](/api/work-management)
* [Plugins](/configuration/plugins/overview)


# Audit Logging



Audit logging provides a chronological record of changes made by users within the Socotra Insurance Suite.\
Users with `events.read` and `events.list` permissions can view audit log entries through the [Events API](/api/events/events).\
New entries are added to the audit log whenever changes occur to entities like quotes, policies, and invoices.

Refer to our documentation on [Event Definitions](/configuration/general-topics/event-definitions) for a comprehensive list of [events](/configuration/general-topics/events) that support audit logging.

Use Cases [#use-cases]

Benefits of audit logging include:

* Detecting security breaches
* Investigating unauthorized activity and operational issues
* Fulfilling regulatory requirements
* Supporting legal documentation

Viewing the Audit Log [#viewing-the-audit-log]

Users can view a list of all audit log entries for a tenant within a time range through the <ApiLink name="fetchMultipleEvents">Fetch Multiple Events</ApiLink> API endpoint.

The request for this endpoint requires a tenant locator and a start timestamp and/or an end timestamp.

For example:

| **Parameter**  | **Value**              |
| -------------- | ---------------------- |
| tenantLocator  | 01Y8FGF6FGE5JAX        |
| startTimestamp | 2025-07-18T00:00:00.0Z |
| endTimestamp   | 2025-07-21T00:00:00.0Z |

Users can also search by [event type](/configuration/general-topics/event-definitions) using the `type` parameter.\
Limit the number of entries shown in the response using the `pageSize` parameter, and search by page ID using the `pagingToken` parameter.

For example:

| **Parameter** | **Value**                   |
| ------------- | --------------------------- |
| type          | policy.account.create       |
| pageSize      | 3                           |
| pagingToken   | eyJW1lDWkpBNUJFSlJYUkEifQ== |

The response from the <ApiLink name="fetchMultipleEvents">Fetch Multiple Events</ApiLink> API endpoint contains the following fields:

<ApiSchema name="EventResponse" />

Next Steps [#next-steps]

* [Secure Deployment](/features/security/secure-deployment)

See Also [#see-also]

* [Events](/configuration/general-topics/events)
* [Events API](/api/events/events)
* [Event Definitions](/configuration/general-topics/event-definitions)
* <ApiLink name="fetchEvent">
    Fetch an Event
  </ApiLink>
* <ApiLink name="fetchMultipleEvents">
    Fetch Multiple Events
  </ApiLink>
* <ApiLink name="fetchEventsForARequest">
    Fetch Events for an API Request
  </ApiLink>
* <ApiLink name="fetchScheduledPolicyEvents">
    Fetch Scheduled Policy Events
  </ApiLink>


## API Reference

EventResponse
Properties:
  locator (ulid, required)
  requestId (ulid, required) — Identifier of the transaction request that triggered the event
  userLocator (uuid, required)
  timestamp (datetime, required)
  type (string, required)
  data (map<string, object>, required)

# Authentication and Identity



Authentication is the process of verifying the identity of a user to restrict access to a software system.

The Socotra Insurance Suite provides multiple authentication options for users:

* **Native Login** - Authenticate through the [Socotra Insurance Suite ](https://ui-ec-sandbox.socotra.com/en/login) UI using login credentials managed by our software system.
* **Single Sign-On (SSO)** - Authenticate through an identity provider that supports SAML-based [SSO](/configuration/general-topics/identity-providers) or OIDC-based SSO, such as Azure AD, Okta, or Google SAML.
* **Personal Access Token** - Authenticate using a [Personal Access Token](/features/security/personal-access-tokens) (PAT).

Native logins and SSO logins result in the creation of a JWT (JSON Web Token) that contains a set of [permissions](/features/security/roles-and-permissions) assigned to a user.\
JWTs expire after a certain amount of time, requiring users to receive a new JWT to reauthenticate.

Users can authenticate API requests using a PAT instead of login credentials.\
PATs function similarly to JWTs, but users can configure PAT details, including permissions, tenants, and token expiration date.

API endpoints support all authentication options.\
Regardless of which authentication method is used, once a user receives a token, this token can be used to authenticate API requests.

<span id="service_accounts" />

Service Accounts [#service-accounts]

A service account is a type of user meant for use by software integrations only. Service accounts can only authenticate API requests using a PAT.

Admins can create service accounts by setting the `serviceAccount` flag in the <ApiLink name="UserCreateRequest" /> to `true` when <ApiLink name="createUser">creating a user</ApiLink>. Use the <ApiLink name="createServiceAccountAuthToken">Create a Service Account Auth Token</ApiLink> API endpoint to generate a PAT for a service account.

<Callout>
  The `enableUser` parameter cannot be set to `true` when using the <ApiLink name="createUser">Create a User</ApiLink> API endpoint to create a service account.
</Callout>

Best Practices [#best-practices]

Native login and SSO should only be used by humans logging in through the Socotra Insurance Suite UI or authenticating API requests through Postman.
Software integrations should only use PATs for authentication.

We highly recommend requiring users to change their credentials every 30 to 90 days in production environments.

Next Steps [#next-steps]

* [Role-Based Access Control (RBAC)](/features/security/roles-and-permissions)

See Also [#see-also]

* [Log Into Socotra](/getting-started/log-into-socotra)
* [Single Sign-On (SSO)](/configuration/general-topics/identity-providers)
* [Personal Access Tokens](/features/security/personal-access-tokens)
* [Create a User](/getting-started/create-a-user)
* [Password Policies](/features/security/password-policies)
* [Passwords API](/api/configuration-and-development/passwords)


# Data Access Controls



<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

Overview [#overview]

Data access controls prevent users from viewing, creating, and editing entities based on field values for a given entity type. Policies, quotes, and accounts are the only entity types that currently support data access controls. Policies and quotes share the same data access control configuration.

Data access controls prevent users from accessing entities, unlike [data masking](/features/security/data-masking), which prevents users from accessing specific fields within an entity.

By default, data access controls are disabled, but users will still be prevented from accessing entities if they don't possess the necessary [permissions](/features/security/roles-and-permissions).

Policy Fields [#policy-fields]

The following policy fields currently support data access controls:

* `productName`
* `region`
* Extension `data` fields

Account Fields [#account-fields]

The following account fields currently support data access controls:

* Extension `data` fields

<Callout>
  Extension `data` fields must be specified at the root level of the extension `data` object.
</Callout>

Enabling Data Access Controls [#enabling-data-access-controls]

Data access controls can be enabled through the <ApiLink name="DataAccessControlRef" /> object in the tenant [configuration](/configuration/general-topics/deployment).

<ApiSchema name="DataAccessControlRef" />

To enable data access controls, set the `enabled` flag to `true`.

For example:

```json
{
	"dataAccessControl": {
		"enabled": true
	}
}
```

<Callout type="warn">
  Before setting the `enabled` flag to `true`, [configure data access controls](#configuring-data-access-controls) to avoid unintentionally blocking access for users.
</Callout>

The `policy` and `account` properties can be used to specify which fields associated with policies or accounts will be used to determine whether a user can access a policy or account.

For example:

```json
{
	"dataAccessControl": {
		"enabled": true,
		"policy": {
			"fields": ["productName", "region"]
		},
		"account": {
			"fields": ["data.region"]
		}
	}
}
```

Only field names can be specified here. Field values can be specified when [configuring data access controls](#configuring-data-access-controls).

Extension `data` fields must be of type `string` with a list of pre-defined `options`.

<span id="configuring-data-access-controls" />

Configuring Data Access Controls [#configuring-data-access-controls]

The <ApiLink name="addUserDataAccess" /> API endpoint can be used to configure data access controls for a user in relation to a specific tenant. Only [admins](/features/security/roles-and-permissions#special_roles) can configure data access controls.

The `accessControlFields` property in the <ApiLink name="UserDataAccessRequest" /> can be used to specify permissible field values for a given entity type.

<ApiSchema name="UserDataAccessRequest" />

In order for a user to access an entity, the `accessControlFields` property must contain a matching value for all fields listed under the corresponding entity type. If any of the fields don't have a matching value, the user will be prevented from accessing the entity and will receive a `403 Forbidden` response.

For example:

```json
{
	"accessControlFields": {
		"policy": {
			"productName": ["CommercialProperty"],
			"region": ["North", "South"]
		},
		"account": {
			"data.region": ["North", "South"]
		}
	}
}
```

In the example above, the user would be allowed to access a policy where the `productName` field is set to `CommercialProperty` and the `region` field is set to `North`. The user would not be allowed to access a policy where the `productName` field is set to `CommercialProperty` and the `region` field is set to `West`.

Wildcard Values [#wildcard-values]

Specify all possible values for a given field using the following format:

```json
{
	"accessControlFields": {
		"account": {
			"data.region": ["*"]
		}
	}
}
```

Next Steps [#next-steps]

* [Data Masking](/features/security/data-masking)

See Also [#see-also]

* [Data Access API](/api/configuration-and-development/data-access)
* [Data Masking](/features/security/data-masking)
* [Role-Based Access Controls](/features/security/roles-and-permissions)


## API Reference

DataAccessControlRef
Properties:
  enabled (boolean, required)
  dataMasking (boolean, required)
  account (DataAccessControlFieldRef, required)
  policy (DataAccessControlFieldRef, required)

UserDataAccessRequest
Properties:
  maskingLevel (Enum none | level1 | level2, required)
  accessControlFields (map<string, map<string, string[]>>, required)

# Data Anonymization



<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

Data anonymization is the process of permanently removing personally identifiable information (PII) from a software system to protect an individual's identity. This process is often necessary to comply with regulations such as the General Data Protection Regulation (GDPR) and the California Delete Act. Currently, only [extension](/configuration/data-extensions/overview) `data` fields can be anonymized.

Data anonymization permanently removes PII from a software system, unlike [data masking](/features/security/data-masking), which hides PII from users without permanently removing the data.

<span id="anonymization-rules" />

Rules [#rules]

Socotra enforces a set of rules when processing data anonymization requests to maintain operational integrity. Data anonymization requests may be partially processed. This means that any entities that can't be anonymized as a result of a rule violation will not be anonymized, while all other entities in the request will be successfully anonymized.

Anonymization rules are evaluated using an entity hierarchy. [Accounts](/features/accounts) are top-level parent entities. Accounts can have one or more child entities, such as policies, and child entities can have their own child entities, forming a [tree structure ](https://en.wikipedia.org/wiki/Tree_%28abstract_data_type%29).

When an anonymization request is processed, the system will attempt to anonymize data in the specified entities in addition to all of their child entities and their descendants.

Accounts can only be anonymized if all of their child entities and descendants have already been successfully anonymized. Accounts can't be anonymized if they have at least one policy in the `onRisk` state.

Policies in the `onRisk` state can't be anonymized. Only policies in the `expired` or `cancelled` state can be anonymized.

Quotes in the issued state can't be anonymized if the resulting policy is still in the `onRisk` state. Quotes in the `accepted` state can be anonymized by default. The `includeAcceptedQuotes` flag can be set to `false` in the [anonymization request](#submitting-anonymization-request) to prevent the anonymization of quotes in the `accepted` state. Quotes can bypass all anonymization rules if the quotes are specified explicitly in the anonymization request.

If a parent entity can't be anonymized, then its child entities and their descendants also can't be anonymized.

Configuration [#configuration]

Data anonymization can be enabled at the tenant level by setting the `enableEntityAnonymization` flag to `true` at the top level of the tenant [configuration](/configuration/general-topics/deployment). Anonymization [requests](#submitting-anonymization-request) will fail if the `enableEntityAnonymization` flag is set to `false` or if this configuration is not provided.

For example:

```json
{
	"enableEntityAnonymization": true
}
```

Data anonymization can be enabled for each [extension](/configuration/data-extensions/overview) `data` field in the tenant configuration by setting the `anonymizable` flag to `true` in the <ApiLink name="RestrictedDataRef" /> configuration object for the target `data` field.

For example:

```json
{
	"data": {
		"ssn": {
			"type": "string?",
			"restrictedData": {
				"anonymizable": true
			}
		}
	}
}
```

<Callout type="warn">
  Anonymization only affects policies and accounts created after an anonymization configuration has been deployed. Contact your Socotra representative if pre-existing entities need to be anonymized.
</Callout>

Formatting Anonymized Values [#formatting-anonymized-values]

By default, the appearance of anonymized values depends on the field type:

```
string -> *****
guid -> *****
int -> -2147483648,
long -> -9223372036854775808,
date -> -999999999-01-01T00:00:00
datetime -> -999999999-01-01T00:00:00+18:00
```

Anonymized values of the same type will always be displayed the same way, regardless of how long the value is. For instance, two different anonymized integers, `1` and `1000`, will both be displayed as `-2147483648` by default.

The `value` field in the <ApiLink name="RestrictedDataRef" /> object can be used to override the default appearance of anonymized values. This configuration overrides the appearance of both anonymized values and [masked values](/features/security/data-masking).

For example:

```json
{
	"data": {
		"ssn": {
			"type": "string?",
			"restrictedData": {
				"anonymizable": true,
				"value": {
					"string": "***-**-****"
				}
			}
		}
	}
}
```

<span id="submitting-anonymization-request" />

Submitting an Anonymization Request [#submitting-an-anonymization-request]

Submit an anonymization request using the <ApiLink name="anonymizeData" /> API endpoint to anonymize entity data based on the anonymization [rules](#anonymization-rules) and the currently [deployed configuration](/api/configuration-and-development/deployments) for the tenant associated with the target entities. Only [admins](/features/security/roles-and-permissions#special_roles) can submit an anonymization request.

Make sure to deploy any necessary configuration changes before submitting an anonymization request.

<Callout type="warn">
  Data anonymization is an irreversible process. Please exercise caution before anonymizing data.
</Callout>

The `references` field can be used to specify one or more entity locators to anonymize. The `includeAcceptedQuotes` flag can be set to `false` to prevent the anonymization of quotes in the `accepted` state. The `policyStatuses` field can be used to restrict the anonymization of policies to policies with one of the specified statuses.

<ApiSchema name="AnonymizationRequest" />

For example:

```json
{
	"references": {
		"policy": ["1E9MFx5h9DGw1H"]
	},
	"includeAcceptedQuotes": true,
	"policyStatuses": ["expired", "cancelled"]
}
```

Preview the effects of your anonymization request through the <ApiLink name="previewAnonymization" /> API endpoint.

<Callout>
  There may be a delay before the [Anonymization API](/api/configuration-and-development/anonymization) recognizes newly created entities.
</Callout>

Data Lake [#data-lake]

Anonymized data will appear in anonymized form in [Data Lake](/features/reporting/datalake). The time of anonymization will be recorded in the `anonymized_time_utc` column for each applicable record in the corresponding entity and parent entity tables.

Next Steps [#next-steps]

* [Audit Logging](/features/security/audit-logging)

See Also [#see-also]

* [Anonymization API](/api/configuration-and-development/anonymization)
* [Data Access Controls](/features/security/data-access-controls)
* [Data Masking](/features/security/data-masking)
* [Configuration Deployment](/configuration/general-topics/deployment)
* [Configuration Deployments API](/api/configuration-and-development/deployments)


## API Reference

AnonymizationRequest
Properties:
  references (map<string, ulid[]>, required)
  includeAcceptedQuotes (boolean)
  policyStatuses (Enum[])

# Data Masking



import Image from 'next/image';

<Callout type="warn">
  This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.
</Callout>

Overview [#overview]

Data masking prevents users from viewing and editing specific fields within entities based on a masking level assigned to each field. Policies, quotes, and accounts are the only entity types that currently support data masking. Policies and quotes share the same data masking configuration. Currently, only extension `data` fields support data masking.

Data masking prevents users from accessing specific fields within an entity, unlike [data access controls](/features/security/data-access-controls), which prevent users from accessing entire entities.

By default, data masking is disabled, but users will still be prevented from accessing entities if they don't possess the necessary [permissions](/features/security/roles-and-permissions).

Masking Levels [#masking-levels]

Fields can be assigned one of the following masking levels, in order from least restrictive to most restrictive:

* `none` - No masking
* `level1` - Sensitive information
* `level2` - Confidential information

Users with a masking level of `none` can access fields with a masking level of `none`. By default, all users have a masking level of `none`, and all fields have a masking level of `none`.

Users with a masking level of `level1` can access fields with a masking level of `level1` and `none`.

Users with a masking level of `level2` can access fields with a masking level of `level2`, `level1`, and `none`.

Enabling Data Masking [#enabling-data-masking]

Data masking can be enabled through the <ApiLink name="DataAccessControlRef" /> object in the tenant [configuration](/configuration/general-topics/deployment).

<ApiSchema name="DataAccessControlRef" />

To enable data masking, set the `dataMasking` flag to `true`.

For example:

```json
{
	"dataAccessControl": {
		"dataMasking": true
	}
}
```

Assigning a Masking Level to Fields [#assigning-a-masking-level-to-fields]

A masking level can be assigned to each extension `data` field through the <ApiLink name="RestrictedDataRef" /> object in the tenant [configuration](/configuration/general-topics/deployment).

<ApiSchema name="RestrictedDataRef" />

The `maskingLevel` property can be used to assign a masking level to an extension `data` field.

For example:

```json
{
	"data": {
		"ssn": {
			"type": "string",
			"restrictedData": {
				"maskingLevel": "level2"
			}
		}
	}
}
```

Formatting Masked Values [#formatting-masked-values]

By default, the appearance of masked values depends on the field type:

```
string -> *****
guid -> *****
int -> -2147483648,
long -> -9223372036854775808,
date -> -999999999-01-01T00:00:00
datetime -> -999999999-01-01T00:00:00+18:00
```

Masked values of the same type will always be displayed the same way, regardless of how long the value is. For instance, two different masked integers, `1` and `1000`, will both be displayed as `-2147483648` by default.

The `value` field in the <ApiLink name="RestrictedDataRef" /> object can be used to override the default appearance of masked values. This configuration overrides the appearance of both masked values and [anonymized values](/features/security/data-anonymization).

For example:

```json
{
	"data": {
		"dob": {
			"type": "date",
			"restrictedData": {
				"maskingLevel": "level2",
				"value": "-11111111-01-01"
			}
		}
	}
}
```

Assigning a Masking Level to Users [#assigning-a-masking-level-to-users]

Users can be assigned a masking level, which allows a user to access all fields with a masking level equal to or less restrictive than the masking level assigned to the user. If a user attempts to access a field with a more restrictive masking level than the masking level assigned to the user, the user will be prevented from accessing the field and will receive a `403 Forbidden` response.

The <ApiLink name="addUserDataAccess" /> API endpoint can be used to assign a masking level to a user in relation to a specific tenant. Only [admins](/features/security/roles-and-permissions#special_roles) can assign a masking level to users.

The `maskingLevel` property in the <ApiLink name="UserDataAccessRequest" /> can be used to specify a masking level.

<ApiSchema name="UserDataAccessRequest" />

For example:

```json
{
	"maskingLevel": "level2"
}
```

Data Masking Demonstration [#data-masking-demonstration]

Refer to the following diagram for a demonstration of data masking in action:

<Image src="/images/security-guide/data-masking.png" alt="data masking" width={2274} height={1246} unoptimized />

Next Steps [#next-steps]

* [Data Anonymization](/features/security/data-anonymization)

See Also [#see-also]

* [Data Access API](/api/configuration-and-development/data-access)
* [Data Access Controls](/features/security/data-access-controls)


## API Reference

DataAccessControlRef
Properties:
  enabled (boolean, required)
  dataMasking (boolean, required)
  account (DataAccessControlFieldRef, required)
  policy (DataAccessControlFieldRef, required)

RestrictedDataRef
Properties:
  anonymizable (boolean, required)
  maskingLevel (Enum none | level1 | level2, required)
  value (Values, required)

UserDataAccessRequest
Properties:
  maskingLevel (Enum none | level1 | level2, required)
  accessControlFields (map<string, map<string, string[]>>, required)

# Encryption



Encryption is the process of preventing unauthorized individuals and software systems from reading data by converting it into an unreadable format that can only be read using a decryption key.\
Enforcing encryption standards is an essential part of securely storing and transporting data managed by software systems, including the Socotra Insurance Suite.

This guide outlines encryption best practices we follow here at Socotra, and we highly recommend our customers follow these same guidelines.

Best Practices [#best-practices]

* Encrypt data using [HTTPS ](https://www.cloudflare.com/learning/ssl/what-is-https/) and [TLS ](https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/) version 1.3 for network communications.
* Encrypt data using [AES-256 ](https://www.progress.com/blogs/use-aes-256-encryption-secure-data) when storing data.
* Store credentials, API keys, and encryption keys within a secure secrets management system such as HashiCorp Vault or AWS Secrets Manager.
* Stay up to date with the latest encryption protocols, and replace legacy protocols such as SSL and older versions of TLS with current industry-standard protocols.

For more details on encryption, visit our [Trust Center ](https://trust.socotra.com).

Next Steps [#next-steps]

* [Password Policies](/features/security/password-policies)

See Also [#see-also]

* [Secure Deployment](/features/security/secure-deployment)
* [Trust Center ](https://trust.socotra.com)


# Password Policies



Password policies require users to comply with a set of rules when creating or changing passwords.

The following guide outlines configurable password policies, mandatory password policies, and best practices for password management.\
The sections detailing configurable policies and mandatory policies only apply to [native logins](/features/security/authentication), since password policies for SSO logins are managed through identity providers.

Configurable Policies [#configurable-policies]

Password policies can be configured through the [Passwords API](/api/configuration-and-development/passwords) and the [Socotra Insurance Suite ](https://ui-ec-sandbox.socotra.com/en/login) UI by navigating to `System Manager > Settings > Password Policy`.\
By default, password policies are set to the following values:

* Minimum number of uppercase characters: 1
* Minimum number of lowercase characters: 1
* Minimum number of numbers: 1
* Minimum number of special characters: 1
* Minimum password length: 16
* Maximum password length: 64
* Password expiration duration: 90 days
* Number of recently used passwords that cannot be reused: 4

Mandatory Policies [#mandatory-policies]

The following password policies are mandatory and are not configurable:

* Passwords cannot be the same as the user's email address or username.
* Commonly used or easily guessed passwords may be automatically rejected.

Best Practices [#best-practices]

For maximum security, Socotra highly recommends observing the following best practices for password management:

* Avoid using commonly used or easily guessed passwords. Some examples include:
  * 123456
  * Password
  * Password123
  * 111111
  * qwerty
  * Dictionary words
  * Names
  * Dates
  * Companies

* Passwords should include uppercase letters, lowercase letters, numbers, and special characters.

* Passwords should be a minimum of 12 to 16 characters.

* Require users to change their passwords every 30 to 90 days.

* Never share your password with anyone.

* Never write your password down.

* Never reuse passwords, even across multiple websites.

* If you suspect someone has access to your account, change your password immediately.

* Consider using a secure password manager to help you adhere to these guidelines.

Next Steps [#next-steps]

* [Security Standards and Regulations](/features/security/regulations)

See Also [#see-also]

* <ApiLink name="updatePasswordPolicy">
    Update Password Policy
  </ApiLink>
* <ApiLink name="fetchPasswordPolicy">
    Fetch Password Policy
  </ApiLink>
* <ApiLink name="resetUserPassword">
    Reset Password
  </ApiLink>


# PCI Compliance Position Statement



Overview [#overview]

Socotra does not currently maintain an independent PCI-DSS certification or compliance validation. Customers are solely responsible for ensuring their entire operational environment, including all third-party services and integrations, meets their PCI compliance requirements.

Customer Responsibility [#customer-responsibility]

Compliance Validation [#compliance-validation]

* **Primary Responsibility**: Customers must validate their complete operational ecosystem for PCI compliance, including their use of Socotra services
* **Audit Requirements**: Customers are responsible for including Socotra as part of their overall PCI compliance audit and validation process
* **Third-Party Assessment**: Any PCI compliance assertions must be made by the customer based on their comprehensive assessment of their entire environment

Socotra's Position [#socotras-position]

Service Provision [#service-provision]

* Socotra provides technology services and infrastructure to support customer operations
* Customers retain full control over their implementation, configuration, and operational practices
* Security features and capabilities are made available to customers to support their compliance efforts

Compliance Assertions [#compliance-assertions]

* **No Independent Claims**: Socotra does not make independent PCI-DSS compliance assertions
* **Customer-Driven Validation**: All compliance determinations must be made by customers through their own assessment processes
* **Audit Participation**: Socotra will cooperate with customer-led compliance audits and assessments as needed

Documentation and Support [#documentation-and-support]

Available Resources [#available-resources]

* Technical documentation regarding security features and implementation guidelines
* Architectural information to support customer compliance assessments
* Support for customer-initiated compliance review processes

Limitations [#limitations]

* Socotra does not provide compliance consulting or certification services
* Customers should engage qualified PCI compliance professionals for validation and certification
* Implementation-specific compliance questions should be addressed through customer-led assessment processes

Key Principles [#key-principles]

1. **Customer Ownership**: Customers own their complete compliance posture and validation process
2. **Comprehensive Assessment**: PCI compliance must be evaluated across the entire operational environment
3. **Professional Validation**: Qualified compliance professionals should be engaged for certification processes
4. **Clear Boundaries**: Socotra's role is service provision, not compliance validation or certification

***

<Callout>
  This position statement is designed to provide clarity on PCI compliance responsibilities and should be reviewed with qualified legal and compliance professionals as part of your overall compliance strategy.
</Callout>


# Comprehensive Permissions Listing



{/* This file is auto-generated by scripts/generate-derived-docs.ts. Do not edit manually. */}

The following is a complete list of permissions available in Socotra. Our API documentation specifies the permissions required to access each API endpoint.

For example, the <ApiLink name="createQuote">Create a Quote</ApiLink> endpoint requires the `quotes.write` or `quotes.create` permission.

Refer to our documentation on [Role-Based Access Control](./roles-and-permissions.mdx) for more details.

| Resource                     | Action                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account-balances`           | `account-balances.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `accounting`                 | `accounting.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `accounts`                   | `accounts.list`, `accounts.read`, `accounts.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `assignments`                | `assignments.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `auto-renewals`              | `auto-renewals.read`, `auto-renewals.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `automation`                 | `automation.execute`, `automation.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `auxdata`                    | `auxdata.list`, `auxdata.read`, `auxdata.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `charges`                    | `charges.list`, `charges.read`, `charges.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `compliance`                 | `compliance.read`, `compliance.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `constraints`                | `constraints.read`, `constraints.upload`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `contacts`                   | `contacts.read`, `contacts.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `credit-distributions`       | `credit-distributions.list`, `credit-distributions.read`, `credit-distributions.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `credits`                    | `credits.list`, `credits.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `delinquencies`              | `delinquencies.list`, `delinquencies.read`, `delinquencies.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `delta-files`                | `delta-files.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `deployments`                | `deployments.cloneProduction`, `deployments.cloneTest`, `deployments.datamodel`, `deployments.deploy`, `deployments.read`, `deployments.retire-version`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `deserializeJobs`            | `deserializeJobs.list`, `deserializeJobs.read`, `deserializeJobs.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `developer`                  | `developer.build`, `developer.download`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `diary`                      | `diary.list`, `diary.read`, `diary.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `disbursements`              | `disbursements.list`, `disbursements.read`, `disbursements.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `diverted-events`            | `diverted-events.delete`, `diverted-events.list`, `diverted-events.read`, `diverted-events.resend`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `documents`                  | `documents.delete-external`, `documents.read`, `documents.render-external`, `documents.replace-external`, `documents.soft-remove`, `documents.trigger`, `documents.update`, `documents.upload`, `documents.upload-external`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `events`                     | `events.list`, `events.read`, `events.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `external-cash-transactions` | `external-cash-transactions.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `financial-instruments`      | `financial-instruments.list`, `financial-instruments.read`, `financial-instruments.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `fnols`                      | `fnols.list`, `fnols.read`, `fnols.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `fonts`                      | `fonts.read`, `fonts.update`, `fonts.upload`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `holds`                      | `holds.list`, `holds.read`, `holds.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `identity`                   | `identity.add`, `identity.custom`, `identity.delete`, `identity.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `installment-lattices`       | `installment-lattices.list`, `installment-lattices.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `installments`               | `installments.list`, `installments.read`, `installments.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `invoices`                   | `invoices.list`, `invoices.read`, `invoices.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `jobs`                       | `jobs.list`, `jobs.read`, `jobs.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `logs`                       | `logs.list`, `logs.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `mediadata`                  | `mediadata.list`, `mediadata.read`, `mediadata.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `metrics`                    | `metrics.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `migration`                  | `migration.list`, `migration.read`, `migration.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `moratoriums`                | `moratoriums.deploy`, `moratoriums.fetch`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `payment-providers`          | `payment-providers.list`, `payment-providers.read`, `payment-providers.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `payments`                   | `payments.list`, `payments.read`, `payments.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `policies`                   | `policies.create-quote`, `policies.list`, `policies.moratoriums`, `policies.read`, `policies.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `producers`                  | `producers.list`, `producers.read`, `producers.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `public`                     | `public.public`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `qualifications`             | `qualifications.read`, `qualifications.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `quick-quotes`               | `quick-quotes.list`, `quick-quotes.read`, `quick-quotes.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `quotes`                     | `quotes.accept`, `quotes.approve-add`, `quotes.approve-clear`, `quotes.block-add`, `quotes.block-clear`, `quotes.create`, `quotes.decline-add`, `quotes.decline-clear`, `quotes.discard`, `quotes.elements-add`, `quotes.elements-delete`, `quotes.info-add`, `quotes.info-clear`, `quotes.issue`, `quotes.list`, `quotes.moratoriums`, `quotes.precommit`, `quotes.price`, `quotes.read`, `quotes.refuse`, `quotes.reject-add`, `quotes.reject-clear`, `quotes.reserve-policy-number-set`, `quotes.reset`, `quotes.schedule-add`, `quotes.schedule-delete`, `quotes.schedule-read`, `quotes.schedule-update`, `quotes.static-data-add`, `quotes.static-data-update`, `quotes.underwrite`, `quotes.update`, `quotes.validate`, `quotes.write`                                                                                                                                                                                                                              |
| `ratingregistries`           | `ratingregistries.list`, `ratingregistries.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `resource-groups`            | `resource-groups.list`, `resource-groups.read`, `resource-groups.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `resources`                  | `resources.list`, `resources.read`, `resources.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `retry-jobs`                 | `retry-jobs.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `riskAssessmentCriteria`     | `riskAssessmentCriteria.read`, `riskAssessmentCriteria.update`, `riskAssessmentCriteria.upload`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `roles`                      | `roles.add`, `roles.delete`, `roles.list`, `roles.read`, `roles.update`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `search`                     | `search.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `secrets`                    | `secrets.read`, `secrets.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `settings`                   | `settings.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `shortfall-credits`          | `shortfall-credits.list`, `shortfall-credits.read`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `tables`                     | `tables.read`, `tables.upload`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `tasks`                      | `tasks.list`, `tasks.read`, `tasks.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `templates`                  | `templates.read`, `templates.upload`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `tenantEvents`               | `tenantEvents.tenant-events`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `tenants`                    | `tenants.create-tenant`, `tenants.custom`, `tenants.list`, `tenants.read`, `tenants.retire`, `tenants.validate-config`, `tenants.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `terms`                      | `terms.list`, `terms.read`, `terms.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `transactions`               | `transactions.accept`, `transactions.approve-add`, `transactions.approve-clear`, `transactions.block-add`, `transactions.block-clear`, `transactions.change-instruction-add`, `transactions.change-instruction-delete`, `transactions.change-instruction-update`, `transactions.decline-add`, `transactions.decline-clear`, `transactions.discard`, `transactions.elements-add`, `transactions.elements-delete`, `transactions.elements-update`, `transactions.info-add`, `transactions.info-clear`, `transactions.initialize`, `transactions.issue`, `transactions.precommit`, `transactions.price`, `transactions.read`, `transactions.refuse`, `transactions.reject-add`, `transactions.reject-clear`, `transactions.reset`, `transactions.schedule-add`, `transactions.schedule-delete`, `transactions.schedule-read`, `transactions.schedule-update`, `transactions.transaction-data-patch`, `transactions.underwrite`, `transactions.validate`, `transactions.write` |
| `uiConfigs`                  | `uiConfigs.read`, `uiConfigs.update`, `uiConfigs.upload`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `user-associations`          | `user-associations.read`, `user-associations.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `users`                      | `users.add`, `users.custom`, `users.delete`, `users.enable`, `users.list`, `users.password-reset`, `users.read`, `users.revoke`, `users.token`, `users.update`, `users.update-roles`, `users.update-tenants`, `users.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `webhooks`                   | `webhooks.list`, `webhooks.read`, `webhooks.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `workgroups`                 | `workgroups.list`, `workgroups.read`, `workgroups.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `workplans`                  | `workplans.read`, `workplans.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `write-offs`                 | `write-offs.list`, `write-offs.read`, `write-offs.write`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

Next Steps [#next-steps]

* [Personal Access Tokens](./personal-access-tokens.mdx)

See Also [#see-also]

* [Role-Based Access Control (RBAC)](./roles-and-permissions.mdx)


# Personal Access Tokens



A Personal Access Token (PAT) is a sequence of characters that can be used to authenticate a user instead of a password.\
PATs don't support [role-based access control](/features/security/roles-and-permissions), meaning they can only be assigned permissions and tenants, not roles.

Users can [create their own PATs](/getting-started/use-the-config-sdk-for-tenant-configuration#part-1---create-a-personal-access-token-), but can only assign permissions that they currently possess to a PAT.
Similarly, users can only assign tenants to a PAT if the tenants are currently assigned to the user's tenant scope.

If a user loses permissions or tenant assignments, and those permissions and tenants were previously assigned to a PAT, the PAT will also lose those permissions and tenant assignments, even if they're still present in the PAT.

Users can [authenticate](/features/security/authentication) API requests using a PAT instead of login credentials.\
PATs function similarly to JWTs, which are created when users authenticate through native login or SSO login, but users can configure PAT details, including permissions, tenants, and token expiration date.

<Callout>
  PATs can be configured to never expire, but we strongly recommend specifying an expiration date for PATs in production environments.
</Callout>

Managing Personal Access Tokens [#managing-personal-access-tokens]

Users can create PATs through the UI by navigating to `User Settings > Personal Access Tokens > Create Token`.

PATs cannot be modified once created. Users can only replace a PAT by first deleting it, then creating a new PAT.

Each user can have up to 3 PATs at a time.\
Users can submit a request to their Socotra representative to increase this limit to 10.

Users can view PAT details through the UI by navigating to `User Settings > Personal Access Tokens`, then selecting a PAT.

<Callout>
  Token values can only be viewed immediately after creating a PAT, so make sure to save your token value in a secure [password manager ](https://en.wikipedia.org/wiki/Password_manager).
</Callout>

Refer to the [Authentication API](/api/business-accounts/authentication) documentation for more details on managing PATs.

Using Personal Access Tokens in Postman [#using-personal-access-tokens-in-postman]

PATs can be used to authenticate requests in Postman by selecting a sample request from our [Postman sample collection](/getting-started/socotra-sample-postman-collection-and-environment), such as the Describe Current User request located in `Socotra Sample Collection > Auth > Users`.\
Navigate to the Authorization tab, select Bearer Token from the Auth Type drop-down list, and then paste your token value in the Token field.

Next, select Socotra Sample Environment from the environment drop-down list in the upper right corner of the request window.

Finally, click the Send button.\
As long as your PAT has the necessary permissions and tenant assignments to access the API endpoint used in the sample request, you should be able to successfully submit the request and receive a `200 OK` response.

Best Practices [#best-practices]

Software integrations, scripts, and AI agents should only use PATs for authentication.
Native login and SSO should only be used by humans logging in through the [Socotra Insurance Suite ](https://ui-ec-sandbox.socotra.com/en/login) UI or authenticating API requests through Postman.

Permissions should be assigned based on the [principle of least privilege ](https://en.wikipedia.org/wiki/Principle_of_least_privilege).\
This means that PATs should only be assigned permissions that are strictly necessary for the user to complete their work.

Next Steps [#next-steps]

* [Data Access Controls](/features/security/data-access-controls)

See Also [#see-also]

* [Create a Personal Access Token](/getting-started/use-the-config-sdk-for-tenant-configuration#part-1---create-a-personal-access-token-)
* [Authentication API](/api/business-accounts/authentication)
* [Set up Postman to use the Socotra API](/getting-started/set-up-postman-to-use-the-socotra-api)
* [Postman Sample Collection](/getting-started/socotra-sample-postman-collection-and-environment)


# Security Standards and Regulations



Socotra upholds a high standard of security to protect our platform, your data, and your business.\
We maintain [ISO 27001 ](https://www.iso.org/standard/27001) certification and SOC 1 Type 2 certification, fulfilling the strict requirements of information security management systems.
Socotra is fully compliant with GDPR and HIPAA.

Additional information on security, privacy, and regulations can be found in our [Trust Center ](https://trust.socotra.com).

Next Steps [#next-steps]

* [PCI Compliance Position Statement](/features/security/pci-compliance-statement)

See Also [#see-also]

* [Secure Deployment](/features/security/secure-deployment)
* [Trust Center ](https://trust.socotra.com)


# Role-Based Access Control (RBAC)



Role-Based Access Control (RBAC) is a security model that authorizes user actions within a software system based on roles assigned to each user.\
Each role grants a set of permissions to a user.\
Users can be assigned multiple roles.

The [Socotra Insurance Suite ](https://ui-ec-sandbox.socotra.com/en/login) UI and API endpoints require users to possess specific permissions to perform certain actions.\
Most API endpoints require a tenant to be assigned to a user's [tenant scope](#tenant_scope) to perform actions specific to that tenant.

<span id="roles" />

Roles [#roles]

Roles can be created through the UI by navigating to `System Manager > Roles > Create Role`.\
Only [admins](#special_roles) can create new roles.

Roles can be assigned to users through the UI by navigating to `System Manager > Users`, then selecting a user and navigating to `Roles > Add New`.

Refer to the [User Management API](/api/business-accounts/user-management) documentation for more details on the user and role management API endpoints.

Permissions [#permissions]

Permissions have the following structure: `resource.action`

For example: `policies.list`

Each API endpoint listed in our documentation specifies the resource and action required to access the endpoint.

For example, the <ApiLink name="createQuote">Create a Quote</ApiLink> endpoint requires the `quotes.write` permission.

Refer to the [Comprehensive Permissions Listing](/features/security/permissions-listing) for a complete overview of all available permissions.

Wildcard Formatting [#wildcard-formatting]

Roles can be assigned all actions performed on a given resource by using the following wildcard permissions format: `resource.*`

For example: `invoices.*`

Roles can be assigned all actions performed on all resources using the following wildcard permissions format: `*.*`

However, roles cannot be assigned to an action performed on all resources.

For example: `*.write`

<Callout>
  Avoid assigning all permissions to roles in production environments unless strictly necessary.  Doing so may violate the [principle of least privilege ](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
</Callout>

<span id="special_roles" />

Special Roles [#special-roles]

Users can be assigned two special roles:

* `admin` - Grants all permissions and access to all tenants within the same [Business Account](/features/business-accounts). Allows the user to assign the `admin` role to other users.
* `read-only` - Grants `read` permissions for all API endpoints.

<span id="tenant_scope" />

Tenant Scope [#tenant-scope]

Users can only perform actions on a tenant if the tenant has been assigned to the user's tenant scope and the user possesses the required permissions.

Tenants can be assigned to users through the UI by navigating to `System Manager > Users`, then selecting a user and navigating to `Tenants > Add New`.

Refer to the [User Management API](/api/business-accounts/user-management) documentation for more details on tenant assignment.

Special Tenant Values [#special-tenant-values]

Users can be assigned two special tenant values:

* `any` - Allows the user to access all API endpoints across all tenants within the same [Business Account](/features/business-accounts), as long as the user possesses the required permissions for an API endpoint.
* `type:test` - Allows the user to access all API endpoints across all tenants of type “TEST” within the same [Business Account](/features/business-accounts), as long as the user possesses the required permissions for an API endpoint.

<Callout>
  For both `any` and `type:test`, if new tenants are added to the user's Business Account later on, the user will automatically have access to those tenants as well.
</Callout>

<span id="tenant_roles" />

Tenant Roles [#tenant-roles]

Tenant roles grant tenant-specific permissions to users. By default, users possess the same permissions for all tenants assigned to a user based on the [roles](#roles) assigned to the user. Tenant roles override roles assigned to a user for a specific tenant.

To create a tenant role, first identify the target `tenantLocator` and the `roleLocator` of the role that the tenant role will override, then call the <ApiLink name="createTenantRole">Create a Tenant Role</ApiLink> API endpoint.

For example:

```json
{
	"permissions": ["quotes.read", "quotes.list"],
	"description": "Read-only quotes in PROD"
}
```

Once a tenant role is created, permissions assigned to users with the specified tenant assignment and role will be overridden for that tenant.

The <ApiLink name="updateTenantRole">Update a Tenant Role</ApiLink> API endpoint can be used to update the permissions for a tenant role. A version number must be specified in the request.

For example:

```json
{
	"version": 3,
	"addPermissions": ["accounts.read"],
	"removePermissions": ["quotes.list"]
}
```

Call the <ApiLink name="getTenantRole">Fetch a Tenant Role</ApiLink> API endpoint to verify that the new tenant-specific permissions have been created.

Tenant roles can be deleted using the <ApiLink name="deleteTenantRole">Delete a Tenant Role</ApiLink> API endpoint.

<Callout>
  Roles cannot be deleted if a tenant role is currently overriding the role.
</Callout>

Next Steps [#next-steps]

* [Comprehensive Permissions Listing](/features/security/permissions-listing)

See Also [#see-also]

* [User Management API](/api/business-accounts/user-management)


# Secure Deployment



Software development teams require secure processes for deploying code changes and managing infrastructure to protect software systems from security threats.
Secure deployment encompasses a wide range of topics, including [authentication](/features/security/authentication), vulnerability scanning, [encryption](/features/security/encryption), configuration management, and networking.

This guide provides a high-level overview of the most important secure deployment practices we follow here at Socotra, and we highly recommend our customers follow these same guidelines.

Automation [#automation]

* Automate code deployments using CI/CD tools like GitHub or Jenkins.
* Automate infrastructure deployments using Infrastructure as Code (IaC) tools like Terraform and AWS CloudFormation.
* Automate vulnerability scanning in build pipelines, including DAST, SAST, IAST, and SCA scans. Automatically block deployments if vulnerabilities are detected.

Authentication [#authentication]

* Require [authentication](/features/security/authentication) and [authorization](/features/security/roles-and-permissions) to access your application code, infrastructure, and CI/CD tools.
* Enforce [password](/features/security/password-policies) best practices.
* Enforce the [principle of least privilege ](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
* Implement [Role-Based Access Control (RBAC)](/features/security/roles-and-permissions).
* Store credentials, API keys, and encryption keys within a secure secrets management system like HashiCorp Vault or AWS Secrets Manager. Never store credentials in your GitHub repositories.

Administration [#administration]

* Identify and uphold [security standards](/features/security/regulations) relevant to your organization.
* Establish a Secure Development Life Cycle (SDLC).
* Perform continuous security testing using penetration testing, threat detection, threat modeling, IDS, IPS, and SIEM tools.
* Review deployment configurations on a regular basis.

Development [#development]

* Implement secure development best practices.
* Maintain separate development, QA, UAT, and production environments.
* Implement network security safeguards like firewalls, rate limiting, and DDoS protection.
* Implement [encryption](/features/security/encryption) best practices.
* Implement [cloud security best practices ](https://aws.amazon.com/architecture/security-identity-compliance/) for your cloud platform.
* Maintain a monitoring and alerting system using tools like Grafana and our [audit log](/features/security/audit-logging).

Next Steps [#next-steps]

* [Encryption](/features/security/encryption)

See Also [#see-also]

* [Security Overview](/features/security/security-overview)


# Security Overview



Socotra is committed to providing a secure platform for modern insurance operations.
Our security model is built to protect sensitive policyholder data, support enterprise governance, and align with industry best practices — all without compromising flexibility for development, configuration, and integration.

This section of the documentation provides a comprehensive look at the security architecture, features, and tools available to product owners, developers, and administrators across the platform.

Who Should Read This [#who-should-read-this]

This documentation is relevant to:

* Security and compliance teams
* Developers and system integrators
* IT administrators and tenant operators
* Product owners and data governance leads

Core Principles [#core-principles]

We approach security with the following principles in mind:

* **Least Privilege by Default** - Users should only be assigned permissions that are strictly necessary to complete their work.
* **Auditable and Transparent** - Every significant system action is logged and traceable.
* **Configurable and Enforceable** - Security controls are flexible enough to meet tenant-specific needs while maintaining baseline protections.
* **Defense in Depth** - Multiple layers of controls, from authentication and encryption to data masking and anonymization.

Topics Covered [#topics-covered]

This section includes detailed documentation on the following topics:

* [Authentication and Identity](/features/security/authentication) - Overview of supported authentication methods, including native login, SSO, and Personal Access Tokens.

* [Role-Based Access Control (RBAC)](/features/security/roles-and-permissions) - Tenant-specific roles and permissions to control access across UI, API, and data layers.

* [Comprehensive Permissions Listing](/features/security/permissions-listing) - A complete overview of all available permissions in the Socotra Insurance Suite.

* [Personal Access Tokens](/features/security/personal-access-tokens) - A secure alternative to password-based authentication for software integrations, scripts, and AI agents.

* [Data Access Controls](/features/security/data-access-controls) - Field-level and entity-level restrictions for visibility and editability of sensitive data, including examples and configuration.

* [Data Masking](/features/security/data-masking) - Mechanisms to ensure sensitive fields are redacted or hidden in API responses and the UI based on user role or data classification.

* [Data Anonymization](/features/security/data-anonymization) - Anonymization features for analytics, testing, and compliance with GDPR or CCPA data handling requirements.

* [Audit Logging](/features/security/audit-logging) - Full visibility into changes made by users and automated processes for traceability and governance.

* [Secure Deployment](/features/security/secure-deployment) - Guidance and tooling to ensure secure deployment of code and infrastructure across environments.

* [Encryption](/features/security/encryption) - Overview of encryption at rest and in transit, including encryption protocols and secrets management.

* [Password Policies](/features/security/password-policies) - Configurable password policies, mandatory password policies, and best practices for password management.

* [Security Standards and Regulations](/features/security/regulations) - Security standards, certifications, and regulatory requirements that support your security obligations.

* [PCI Compliance Position Statement](/features/security/pci-compliance-statement) - Socotra's position on PCI Compliance.

Next Steps [#next-steps]

Start with [Authentication and Identity](/features/security/authentication), or skip directly to the areas most relevant to your team.

For any security-related support or inquiries, reach out to your Socotra representative or email [security@socotra.com](mailto:security@socotra.com).

If you haven't already done so, make sure you're able to [log into Socotra](/getting-started/log-into-socotra) and [set up Postman](/getting-started/set-up-postman-to-use-the-socotra-api) to use the Socotra API.


# AccountForm



The `AccountForm` component is a dynamic form used for creating or
updating an account. It renders form fields based on a provided data
model, allowing for flexible account structures. The form can be toggled
between “create” and “update” modes based on the presence of an
`account` object.

Usage [#usage]

Integrate `AccountForm` by providing it with a resolved data model, an
account type, and a submit handler. The component is built on top of
`@jsonforms/react` and handles rendering and state management
internally.

```ts
import { AccountForm } from '@socotra/ec-react-components';
import { DataModel, AccountResponse } from '@socotra/ec-react-schemas';

// Example Usage
const MyComponent = ({ dataModel, account }: { dataModel: DataModel, account?: AccountResponse }) => {
  const handleSubmit = (data) => {
    console.log('Form submitted:', data);
    // Handle API call to create or update the account
  };

  return (
    <AccountForm
      dataModel={dataModel}
      accountType="personal"
      account={account}
      handleSubmit={handleSubmit}
      submitButtonText={account ? 'Update Account' : 'Create Account'}
    />
  );
};
```

Props [#props]

The component accepts the following props:

| Prop                         | Type                                                                                                | Description                                                                                                   | Default      |
| ---------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------ |
| `dataModel`                  | `DataModel`                                                                                         | The resolved data model object containing account configurations and data types.                              | **Required** |
| `accountType`                | `keyof AccountConfigRecord`                                                                         | The specific account type from the data model to render the form for.                                         | **Required** |
| `handleSubmit`               | `(data: AccountCreateRequest \| AccountUpdateRequest) => void`                                      | Callback function triggered on form submission. The argument type depends on whether `account` is provided.   | **Required** |
| `account`                    | `AccountResponse`                                                                                   | An optional account object. If provided, the form enters “update” mode.                                       | `undefined`  |
| `isSubmitting`               | `boolean`                                                                                           | When true, disables the form fields and submit button, indicating a submission is in progress.                | `false`      |
| `disabled`                   | `boolean`                                                                                           | When true, disables the entire form.                                                                          | `false`      |
| `preventFormResetOnDisabled` | `boolean`                                                                                           | If `false`, the form’s data will reset to initial values when `disabled` becomes true.                        | `true`       |
| `hideSubmitButton`           | `boolean`                                                                                           | If `true`, the submit button will not be rendered.                                                            | `false`      |
| `submitButtonText`           | `string`                                                                                            | Custom text for the submit button.                                                                            | `'Update'`   |
| `hideAdvancedFields`         | `boolean`                                                                                           | If `true`, hides the expandable “Advanced Fields” section.                                                    | `false`      |
| `validateOnSubmit`           | `boolean`                                                                                           | If `true`, validation is run on submit and submission is blocked if invalid.                                  | `false`      |
| `id`                         | `string`                                                                                            | A unique ID for the form wrapper element.                                                                     | `undefined`  |
| `titles`                     | `object`                                                                                            | An object to override default labels for advanced fields and other parts of the form.                         | `{}`         |
| `dependencyMap`              | `DependencyMapResponse`                                                                             | Optional map of field dependencies, required to enable constraint evaluation for the account form.            | `undefined`  |
| `getEvaluatedConstraints`    | `(request: AccountEvaluateConstraintsRequest) => Promise<EvaluateConstraintsResponse \| undefined>` | Optional async function to call the backend for constraint evaluation. Required for the feature to be active. | `undefined`  |

State Management [#state-management]

`AccountForm` manages its state internally using React’s `useState`
hook. It holds the form data in a state variable that is updated by the
underlying `JsonForms` component via its `onChange` callback. It
does not use an external form library like `react-hook-form`.

Constraint Evaluation [#constraint-evaluation]

This form supports a powerful constraint evaluation system to create
dynamic relationships between fields.

* **Purpose:** To automatically calculate or update the values of
  certain fields based on user input in other fields, without requiring
  a full form submission. For example, selecting a specific “Region”
  could automatically populate a “Tax Rate” field.
* **Activation:** The feature is enabled by providing both the
  `dependencyMap` and `getEvaluatedConstraints` props.
* **Mechanism:**
  1. The `dependencyMap` tells the form which fields depend on others.
  2. When a user changes a field that is a dependency for another, a
     `useEffect` hook is triggered.
  3. This hook calls the `getEvaluatedConstraints` function with a
     payload of the changed data.
  4. The backend service evaluates the data and returns a
     `EvaluateConstraintsResponse` containing the new values for any
     dependent fields.
  5. This response is stored in the `evaluatedConstraints` state,
     which triggers a re-render.
  6. The `dataModelToJSONSchema` utility uses this response to update
     the JSON Schema, making the calculated fields read-only and
     displaying their new values.

Validation [#validation]

Form validation is handled by [Ajv ](https://ajv.js.org/), a JSON
Schema validator.

* A JSON Schema is dynamically generated from the `dataModel` prop
  using the `dataModelToJSONSchema` utility.
* Custom validation formats and keywords are added to the Ajv instance.
* Validation can be configured to run when the user clicks the submit
  button by setting `validateOnSubmit={true}`.
* Error messages are translated into a user-friendly format using the
  `translateError` utility.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key                          | Description                                     | Default Value                     |
| ---------------------------- | ----------------------------------------------- | --------------------------------- |
| `seeAdvancedDetails`         | Title for the collapsible “Advanced” section.   | `'See Advanced Details'`          |
| `autoRenewalPlanName`        | Label for the “Auto-Renewal Plan” field.        | `'Auto-renewal Plan Name'`        |
| `delinquencyPlanName`        | Label for the “Delinquency Plan” field.         | `'Delinquency Plan Name'`         |
| `excessCreditPlanName`       | Label for the “Excess Credit Plan” field.       | `'Excess Credit Plan Name'`       |
| `shortfallTolerancePlanName` | Label for the “Shortfall Tolerance Plan” field. | `'Shortfall Tolerance Plan Name'` |
| `billingLevel`               | Label for the “Billing Level” field.            | `'Billing Level'`                 |
| `invoiceDocument`            | Label for the “Invoice Document” field.         | `'Invoice Document'`              |
| `installmentPlanName`        | Label for the “Installment Plan” field.         | `'Installment Plan Name'`         |
| `truthyLabel`                | Text for a “true” boolean value.                | `'Yes'`                           |
| `falsyLabel`                 | Text for a “false” boolean value.               | `'No'`                            |


# DataPropertyForm



The `DataPropertyForm` component is a dynamic form used for rendering
and editing data properties using a provided data model and property
schema.

Usage [#usage]

Integrate `DataPropertyForm` by providing it with a resolved data
model, a data property schema, and initial data. The component manages
form state internally and supports both read-only and editable modes.

```ts
import { DataPropertyForm } from '@socotra/ec-react-components';
import {
    DataModel,
    FieldConfigRecord,
    PropertyRef,
} from '@socotra/ec-react-schemas';

const MyComponent = ({
    dataModel,
    dataPropertySchema,
    data,
}: {
    dataModel: DataModel;
    dataPropertySchema: FieldConfigRecord;
    data: Record<string, PropertyRef>;
}) => {
    const handleSubmit = (formData: Record<string, PropertyRef>) => {
        console.log('Form submitted:', formData);
        // Handle API call or state update
    };

    return (
        <DataPropertyForm
            dataModel={dataModel}
            dataPropertySchema={dataPropertySchema}
            data={data}
            handleSubmit={handleSubmit}
            submitButtonText='Save Data'
        />
    );
};
```

Props [#props]

| Prop                 | Type                                                                 | Description                                                                                      | Default      |
| -------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------ |
| `dataModel`          | `DataModel`                                                          | The resolved data model object containing data types.                                            | **Required** |
| `dataPropertySchema` | `FieldConfigRecord`                                                  | The schema configuration for the data properties to render.                                      | **Required** |
| `data`               | `Record<string, PropertyRef>`                                        | The initial data to display in the form.                                                         | **Required** |
| `handleSubmit`       | `(data: Record<string, PropertyRef>) => void`                        | Callback triggered on form submission.                                                           | `() => {}`   |
| `isSubmitting`       | `boolean`                                                            | When true, disables the form fields and submit button, indicating a submission is in progress.   | `false`      |
| `disabled`           | `boolean`                                                            | Disables the entire form when true.                                                              | `false`      |
| `hideSubmitButton`   | `boolean`                                                            | Hides the submit button when true.                                                               | `false`      |
| `validateOnSubmit`   | `boolean`                                                            | Runs validation on submit and blocks submission if invalid.                                      | `false`      |
| `submitButtonText`   | `string`                                                             | Custom text for the submit button.                                                               | `'Submit'`   |
| `readonly`           | `boolean`                                                            | Renders the form in read-only mode.                                                              | `false`      |
| `id`                 | `string`                                                             | Unique ID for the form wrapper element.                                                          | `undefined`  |
| `titles`             | `{ formTitle?: string; truthyLabel?: string; falsyLabel?: string; }` | An object to override default labels for parts of the form. See “Labels and Translations” below. | `{}`         |

State Management [#state-management]

`DataPropertyForm` manages its state internally using React’s
`useState` hook. The form data is updated via the `onChange`
callback from the underlying `JsonForms` component. No external form
library is used.

Validation [#validation]

Form validation is handled by [Ajv ](https://ajv.js.org/), a JSON
Schema validator.

* A JSON Schema is dynamically generated from the `dataModel` prop
  using the `dataModelToJSONSchema` utility.
* Custom validation formats and keywords are added to the Ajv instance.
* Validation can be configured to run when the user clicks the submit
  button by setting `validateOnSubmit={true}`.
* Error messages are translated into a user-friendly format using the
  `translateError` utility.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key           | Description                      | Default Value |
| ------------- | -------------------------------- | ------------- |
| `formTitle`   | Title for the form               | `''`          |
| `truthyLabel` | Text for a `true` boolean value  | `'Yes'`       |
| `falsyLabel`  | Text for a `false` boolean value | `'No'`        |


# DraftTransactionForm



The `DraftTransactionForm` is a specialized component for updating a
policy transaction that is in a `draft` state. Unlike forms for
initialized transactions, its primary role is to generate
`ParamsChangeInstructionCreateRequest` and
`ModifyChangeInstructionCreateRequest` objects. These instructions
capture changes to the transaction’s parameters (like effective dates)
and its core data, respectively.

Usage [#usage]

To implement the `DraftTransactionForm`, you must provide the current
`transactionSnapshot`, the initial `paramsChangeInstruction`, the
relevant `productModel`, and a `handleSubmit` function. The form
then renders the fields defined in the product model and manages the
data to create the change instructions upon submission.

```ts
import { DraftTransactionForm } from '@socotra/ec-react-components';
import {
    ProductConfig,
    TransactionSnapshotResponse,
    ParamsChangeInstructionResponse,
} from '@socotra/ec-react-schemas';

// Example Usage
const MyEndorsementComponent = ({
    productModel,
    transactionSnapshot,
    paramsChangeInstruction,
}: {
    productModel: ProductConfig,
    transactionSnapshot: TransactionSnapshotResponse,
    paramsChangeInstruction: ParamsChangeInstructionResponse,
}) => {
    const handleSubmit = (changeRequests) => {
        const [paramsChange, modifyChange] = changeRequests;
        console.log('Params Change Request:', paramsChange);
        console.log('Modify Change Request:', modifyChange);
        // Handle API calls to apply the change instructions
    };

    return (
        <DraftTransactionForm
            productModel={productModel}
            transactionSnapshot={transactionSnapshot}
            paramsChangeInstruction={paramsChangeInstruction}
            handleSubmit={handleSubmit}
            submitButtonText='Apply Changes'
        />
    );
};
```

Props [#props]

| Prop                         | Type                                                                                           | Description                                                                                                         | Default      |
| ---------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------ |
| `transactionSnapshot`        | `TransactionSnapshotResponse`                                                                  | The snapshot object for the transaction being modified.                                                             | **Required** |
| `paramsChangeInstruction`    | `ParamsChangeInstructionResponse`                                                              | The initial parameter change instruction created with the transaction.                                              | **Required** |
| `productModel`               | `ProductConfig`                                                                                | The product configuration from the tenant data model that defines the transaction’s structure.                      | **Required** |
| `handleSubmit`               | `(data: [ParamsChangeInstructionCreateRequest, ModifyChangeInstructionCreateRequest]) => void` | Callback triggered on submit. It receives an array containing the two generated change instruction request objects. | **Required** |
| `coverageTerms`              | `CoverageTermsConfigRecord`                                                                    | The coverage terms configuration from the tenant data model.                                                        | `undefined`  |
| `dataTypes`                  | `DataTypeConfigRecord`                                                                         | Custom data types used in the product model.                                                                        | `undefined`  |
| `modifyChangeInstruction`    | `ModifyChangeInstructionResponse`                                                              | The most recent modify change instruction from the transaction’s stack, if one exists.                              | `undefined`  |
| `disabled`                   | `boolean`                                                                                      | When true, disables the entire form.                                                                                | `false`      |
| `isSubmitting`               | `boolean`                                                                                      | When true, disables form fields and the submit button to indicate a submission is in progress.                      | `false`      |
| `preventFormResetOnDisabled` | `boolean`                                                                                      | If `false`, the form’s data resets to initial values when `disabled` becomes true.                                  | `true`       |
| `validateOnSubmit`           | `boolean`                                                                                      | If `true`, validation runs on submit, blocking submission if invalid.                                               | `false`      |
| `hideSubmitButton`           | `boolean`                                                                                      | If `true`, the submit button is not rendered.                                                                       | `false`      |
| `submitButtonText`           | `string`                                                                                       | Custom text for the submit button.                                                                                  | `'Update'`   |
| `id`                         | `string`                                                                                       | A unique ID for the form wrapper element.                                                                           | `undefined`  |
| `titles`                     | `object`                                                                                       | An object to override default labels for form sections like “Coverage Terms”.                                       | `{}`         |

State Management [#state-management]

The form’s state is managed internally with React’s `useState` hook.

* The initial data is populated by the
  `getDefaultDraftTransactionValues` utility, which processes the
  input `transactionSnapshot` and change instructions.
* `useEffect` hooks are in place to re-calculate the form’s data if
  key props like `transactionSnapshot` or `modifyChangeInstruction`
  change, ensuring the form stays in sync.
* The underlying `JsonForms` component updates the state via its
  `onChange` handler.

Validation [#validation]

Validation is performed by [Ajv ](https://ajv.js.org/) against a
dynamically generated JSON Schema.

* The base schema is generated from the `productModel` using the
  `dataModelToJSONSchema` utility.
* It is then dynamically extended with definitions for default
  transaction fields (like effective date) and any coverage terms
  associated with the product.
* The `validateOnSubmit` prop controls whether to perform validation
  before calling `handleSubmit`.
* Error messages are translated using the `translateError` utility.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key             | Description                             | Default Value      |
| --------------- | --------------------------------------- | ------------------ |
| `formTitle`     | The main title for the entire form.     | `'Transaction'`    |
| `coverageTerms` | Title for the “Coverage Terms” section. | `'Coverage Terms'` |
| `truthyLabel`   | Text for a “true” boolean value.        | `'Yes'`            |
| `falsyLabel`    | Text for a “false” boolean value.       | `'No'`             |


# ElementForm



The `ElementForm` is a highly versatile component designed to create
or update any individual “element” within a quote, such as a vehicle,
driver, or insured property. It dynamically renders form fields based on
the provided `elementModel` and can handle complex data dependencies
through constraint evaluation, making it a cornerstone of the quoting
process.

Usage [#usage]

To render an `ElementForm`, you need to provide the specific
`elementModel` that defines its structure, the `element` object
being edited, the overall `dataModel`, and a `timezone`. For
advanced dependency-driven logic, a `dependencyMap` and a
`getEvaluatedConstraints` function are also required.

```ts
import { ElementForm } from '@socotra/ec-react-components';
import {
    ElementConfig,
    ElementResponse,
    DataModel,
    DependencyMapResponse,
    EvaluateConstraintsResponse,
    EvaluateConstraintsRequest,
} from '@socotra/ec-react-schemas';

// Example Usage
const MyElementEditor = ({
    elementModel,
    element,
    dataModel,
    dependencyMap,
}: {
    elementModel: ElementConfig,
    element: ElementResponse,
    dataModel: DataModel,
    dependencyMap: DependencyMapResponse,
}) => {
    const handleSubmit = (elementRequest) => {
        console.log('Element Update Request:', elementRequest);
        // Handle API call to update the element
    };

    const handleEvaluateConstraints = async (
        request: EvaluateConstraintsRequest,
    ): Promise<EvaluateConstraintsResponse | undefined> => {
        console.log('Evaluating constraints for:', request);
        // Replace with your actual API call
        return fetch(/*...- /constraints/evaluate ...*/).then(res => res.json());
    };

    return (
        <ElementForm
            elementModel={elementModel}
            element={element}
            dataModel={dataModel}
            timezone='America/New_York'
            handleSubmit={handleSubmit}
            dependencyMap={dependencyMap}
            getEvaluatedConstraints={handleEvaluateConstraints}
            submitButtonText='Update Element'
        />
    );
};
```

Props [#props]

| Prop                      | Type                                                                                     | Description                                                                                                    | Default      |
| ------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------ |
| `elementModel`            | `ElementConfig`                                                                          | The configuration object from the data model that defines this element’s fields and structure.                 | **Required** |
| `element`                 | `ElementResponse`                                                                        | The element object from the quote that is being edited.                                                        | **Required** |
| `dataModel`               | `DataModel`                                                                              | The entire resolved data model.                                                                                | **Required** |
| `timezone`                | `string`                                                                                 | The timezone for the quote or policy, essential for correct date/time handling.                                | **Required** |
| `handleSubmit`            | `(data: ElementRequest) => void`                                                         | An optional callback triggered on submit with the `ElementRequest` payload.                                    | `undefined`  |
| `dataTypes`               | `DataTypeConfigRecord`                                                                   | Custom data types referenced by the element model.                                                             | `undefined`  |
| `coverageTerms`           | `CoverageTermsConfigRecord`                                                              | The configuration for coverage terms available to this element.                                                | `undefined`  |
| `quote`                   | `QuoteResponse`                                                                          | The full quote object, used to enable conditional field rendering based on the state of other elements.        | `undefined`  |
| `dependencyMap`           | `DependencyMapResponse`                                                                  | An optional map of field dependencies. Required to enable the constraint evaluation feature.                   | `undefined`  |
| `getEvaluatedConstraints` | `(request, tenantLocator, locator) => Promise<EvaluateConstraintsResponse \| undefined>` | An optional async function that calls the backend to evaluate constraints. Required for constraint evaluation. | `undefined`  |
| `hideAllFields`           | `boolean`                                                                                | If `true`, hides all data fields in the form.                                                                  | `false`      |
| `hideCoverageTerms`       | `boolean`                                                                                | If `true`, hides the coverage terms section, even if they are defined in the model.                            | `false`      |
| `disabled`                | `boolean`                                                                                | When true, disables the entire form.                                                                           | `false`      |
| `isSubmitting`            | `boolean`                                                                                | When true, disables the form to indicate a submission is in progress.                                          | `false`      |
| `submitButtonText`        | `string`                                                                                 | Custom text for the submit button.                                                                             | `'Update'`   |

…and other standard form control props (`preventFormResetOnDisabled`,
`validateOnSubmit`, `hideSubmitButton`, `id`, `titles`).

State Management [#state-management]

`ElementForm` relies on internal state managed by `useState` and
`useEffect` hooks.

* **Data Initialization:** Form data is initialized using the
  `getDefaultElementValues` utility, which populates fields from the
  `element` response and its associated `coverageTerms`.
* **Constraint Evaluation:** The mechanism is identical to
  `InitializedTransactionForm`. When a user changes a field that other
  fields depend on (as defined in `dependencyMap`), a `useEffect`
  hook calls the `getEvaluatedConstraints` function. The response is
  stored in an `evaluatedConstraints` state variable, which triggers a
  schema regeneration to update and disable dependent fields. The
  `evaluatedConstraints` are cleared on any subsequent form change to
  allow for re-evaluation.
* **Prop Synchronization:** The component keeps a local copy of the
  `element` and `coverageTerms` props in state. A `useEffect` hook
  checks for differences between the incoming props and the local state.
  If a change is detected (e.g., after a parent component saves data),
  the form’s data is re-initialized to reflect the new state.

Validation [#validation]

Validation is performed client-side using [Ajv ](https://ajv.js.org/).

* The validation schema is dynamically constructed by the
  `dataModelToJSONSchema` utility. This function considers the
  `elementModel`, `dataTypes`, `timezone`, and, importantly, the
  current `quote` object.
* When constraint evaluation is active, the schema is augmented with the
  `dependencyMap` and the latest `evaluatedConstraints` response,
  which allows `Ajv` to enforce that dependent fields are read-only
  and have the correct calculated values.
* The visibility of fields (controlled by `hideAllFields` and
  `hideCoverageTerms`) is also reflected in the final schema
  structure.
* The `translateError` utility is used to convert validation errors
  into user-friendly messages.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key             | Description                             | Default Value      |
| --------------- | --------------------------------------- | ------------------ |
| `coverageTerms` | Title for the “Coverage Terms” section. | `'Coverage Terms'` |
| `truthyLabel`   | Text for a “true” boolean value.        | `'Yes'`            |
| `falsyLabel`    | Text for a “false” boolean value.       | `'No'`             |


# EC React Components



`@socotra/ec-react-components` is a powerful, schema-driven framework
for building enterprise-grade insurance applications. This library
provides a comprehensive suite of dynamic forms and UI components
designed to accelerate development and handle the full spectrum of
policy lifecycle operations with unparalleled flexibility.

Core Philosophy [#core-philosophy]

At its core, this library is engineered to translate Socotra’s flexible
data model directly into a rich, interactive user interface. By
leveraging your unique data model, we dynamically generate complex
forms, eliminating the need to manually build and maintain forms for
every product or data variation. This schema-driven approach ensures
that as your insurance products evolve, your UI adapts automatically,
dramatically reducing development overhead and increasing speed to
market.

Our components are built with modern, robust technologies including
**React**, **TypeScript**, **Shadcn UI**, and **Tailwind CSS**, ensuring
a developer-friendly, performant, and highly customizable experience.

Key Features [#key-features]

* **Schema-Driven UI**: Forms for quotes, policies, accounts, and
  transactions are generated dynamically from your data model, not
  hardcoded.
* **Complex Logic Handling**: Built-in support for sophisticated
  insurance workflows, including constraint evaluation for real-time
  field dependency updates.
* **Highly Customizable**: A powerful `tag` system allows for deep
  customization of field behavior directly from the data model—from
  conditional visibility to special UI controls like multi-select and
  currency inputs.
* **Enterprise-Ready**: Designed to handle the intricate details of
  policy administration, including endorsements, payments,
  disbursements, and renewals.
* **Modern Tech Stack**: A clean, modern, and performant codebase that
  is a pleasure to work with and extend.

***

Installation [#installation]

```sh
npm i @socotra/ec-react-components
```

***

Component Documentation [#component-documentation]

Dive into the detailed documentation for our core components to
understand their purpose, props, and advanced capabilities.

Core Forms [#core-forms]

| Component            | Description                                                                                                                                               |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **AccountForm**      | A dynamic form for creating and updating customer accounts based on configurable account types.                                                           |
| **QuoteForm**        | The cornerstone of the quoting process. A comprehensive, multi-section form for creating and updating quotes with full support for constraint evaluation. |
| **PolicyForm**       | A specialized, read-only view for displaying the complete data of an issued policy in a structured format.                                                |
| **ElementForm**      | A versatile and powerful form for rendering any sub-element of a policy or quote, such as a vehicle, driver, or location.                                 |
| **PaymentForm**      | A suite of components for handling all payment-related actions: creating new payments, applying existing credit, and reversing transactions.              |
| **DisbursementForm** | A specialized form for processing disbursements from an account, with dynamic fields based on disbursement type.                                          |
| **DataPropertyForm** | A dynamic form used for rendering and editing data properties using a provided data model and property schema.                                            |

Transaction Forms [#transaction-forms]

These forms are used for handling changes to policies post-issuance
(endorsements, renewals, etc.).

| Component                      | Description                                                                                                                                                                    |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **InitializedTransactionForm** | Handles transactions in an `initialized` state (e.g., a new business quote), with full support for constraint evaluation to manage complex field dependencies before issuance. |
| **DraftTransactionForm**       | A specialized form for midterm policy changes. It generates the necessary `param` and `modify` change instructions to accurately update a `draft` transaction.                 |

***

Custom Rendering (Tags for Fields) [#custom-rendering-tags-for-fields]

To unlock the full potential of this library, it’s essential to
understand the `tag` system. Our custom rendering guide provides a
detailed walkthrough of how to control form behavior directly from your
data model.

This guide covers:

* Conditional Field Hiding (`hidden|...`, `rootHidden|...`,
  `hidden`)
* Advanced UI Controls (`multiselect`, `horizontal-layout`)
* Data Formatting (`currency`)
* Field Disable (`readOnly`)

Theming [#theming]

To style the components, follow the instructions in the theming guide.

This guide covers:

* Theming with Tailwind CSS and `shadcn/ui`
* CSS Imports from the package
* Per-Component Style Overrides


# InitializedTransactionForm



The `InitializedTransactionForm` is used to update a transaction that
is in an `initialized` state, such as a change to a policy after it
has been issued. It renders a form based on the specified product model
and handles the data collection needed to update the transaction’s
underlying element. A key feature of this form is its ability to handle
complex field dependencies and recalculations by evaluating constraints.

Usage [#usage]

To use this form, you need to provide the `elementResponse` of the
transaction, the `productModel`, and a `handleSubmit` function. For
advanced functionality, such as automatic field updates based on user
input, you must also provide a `dependencyMap` and a
`getEvaluatedConstraints` async function.

```ts
import { InitializedTransactionForm } from './InitializedTransactionForm';
import {
    ProductConfig,
    ElementResponse,
    ParamsChangeInstructionResponse,
    DependencyMapResponse,
    EvaluateConstraintsResponse,
    EvaluateConstraintsRequest,
} from '@socotra/ec-react-schemas';

// Example Usage
const MyQuoteComponent = ({
    productModel,
    elementResponse,
    paramsChangeInstruction,
    dependencyMap,
}: {
    productModel: ProductConfig,
    elementResponse: ElementResponse,
    paramsChangeInstruction: ParamsChangeInstructionResponse,
    dependencyMap: DependencyMapResponse,
}) => {
    const handleSubmit = (elementRequest) => {
        console.log('Element Update Request:', elementRequest);
        // Handle API call to update the transaction element
    };

    const handleEvaluateConstraints = async (
        request: EvaluateConstraintsRequest,
    ): Promise<EvaluateConstraintsResponse | undefined> => {
        // API call to evaluate constraints and get back updated values
        console.log('Evaluating constraints for:', request);
        return Promise.resolve(undefined); // Replace with actual API call
    };

    return (
        <InitializedTransactionForm
            productModel={productModel}
            elementResponse={elementResponse}
            paramsChangeInstruction={paramsChangeInstruction}
            timezone='America/New_York'
            handleSubmit={handleSubmit}
            dependencyMap={dependencyMap}
            getEvaluatedConstraints={handleEvaluateConstraints}
            submitButtonText='Update Quote'
        />
    );
};
```

Props [#props]

| Prop                         | Type                                                                                     | Description                                                                                                                   | Default      |
| ---------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------ |
| `elementResponse`            | `ElementResponse`                                                                        | The element object for the initialized transaction.                                                                           | **Required** |
| `paramsChangeInstruction`    | `ParamsChangeInstructionResponse`                                                        | The parameter change instruction associated with the transaction.                                                             | **Required** |
| `productModel`               | `ProductConfig`                                                                          | The product configuration that defines the form’s structure.                                                                  | **Required** |
| `timezone`                   | `string`                                                                                 | The timezone for the policy, used for date/time field handling.                                                               | **Required** |
| `handleSubmit`               | `(data: ElementRequest) => void`                                                         | Callback triggered on submit, receiving the `ElementRequest` payload for updating the transaction.                            | **Required** |
| `coverageTerms`              | `CoverageTermsConfigRecord`                                                              | Configuration for any coverage terms associated with the product.                                                             | `undefined`  |
| `dataTypes`                  | `DataTypeConfigRecord`                                                                   | Custom data types used within the product model.                                                                              | `undefined`  |
| `dependencyMap`              | `DependencyMapResponse`                                                                  | An optional map defining the dependencies between fields for constraint evaluation. Required to enable constraint evaluation. | `undefined`  |
| `getEvaluatedConstraints`    | `(request, tenantLocator, locator) => Promise<EvaluateConstraintsResponse \| undefined>` | An optional async function to call the backend to evaluate constraints. Required to enable constraint evaluation.             | `undefined`  |
| `disabled`                   | `boolean`                                                                                | When true, disables the entire form.                                                                                          | `false`      |
| `isSubmitting`               | `boolean`                                                                                | When true, disables the form to indicate a submission is in progress.                                                         | `false`      |
| `preventFormResetOnDisabled` | `boolean`                                                                                | If `false`, the form’s data resets to initial values when `disabled` becomes true.                                            | `true`       |
| `validateOnSubmit`           | `boolean`                                                                                | If `true`, validation runs on submit, blocking submission if invalid.                                                         | `false`      |
| `hideSubmitButton`           | `boolean`                                                                                | If `true`, the submit button is not rendered.                                                                                 | `false`      |
| `submitButtonText`           | `string`                                                                                 | Custom text for the submit button.                                                                                            | `'Update'`   |
| `id`                         | `string`                                                                                 | A unique ID for the form wrapper element.                                                                                     | `undefined`  |
| `titles`                     | `object`                                                                                 | An object to override default labels for form sections.                                                                       | `{}`         |

State Management [#state-management]

The form state is managed internally using `useState` and
`useEffect` hooks.

* Form data is initialized using the
  `getDefaultInitializedTransactionValues` utility.
* **Constraint Evaluation:** When `dependencyMap` and
  `getEvaluatedConstraints` are provided, the form watches for data
  changes. A `useEffect` hook triggers the `getEvaluatedConstraints`
  function when a field that others depend on is modified. The results
  are stored in an `evaluatedConstraints` state variable, which is
  then used to update the JSON schema and disable the modified fields.
* **Data Syncing:** A `useEffect` hook compares the incoming
  `elementResponse` prop with a local copy in state. If they differ
  (e.g., after a save), the form data is recalculated to reflect the
  latest updates.
* The `JsonForms` `onChange` handler updates the form data state and
  clears any existing `evaluatedConstraints` to allow for
  re-evaluation.

Validation [#validation]

Validation is handled by [Ajv ](https://ajv.js.org/).

* A JSON schema is dynamically built by `dataModelToJSONSchema` based
  on the `productModel`, `dataTypes`, and current `timezone`.
* If constraint evaluation is active, the schema is updated with
  information from the `dependencyMap` and `evaluatedConstraints`
  response to make dependent fields read-only and update their values.
* The schema is also extended with definitions for any
  `coverageTerms`.
* The `validateOnSubmit` prop controls whether to block form
  submission if the data is invalid.
* The `translateError` utility provides user-friendly validation
  messages.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key             | Description                             | Default Value      |
| --------------- | --------------------------------------- | ------------------ |
| `formTitle`     | The main title for the entire form.     | `'Transaction'`    |
| `coverageTerms` | Title for the “Coverage Terms” section. | `'Coverage Terms'` |
| `truthyLabel`   | Text for a “true” boolean value.        | `'Yes'`            |
| `falsyLabel`    | Text for a “false” boolean value.       | `'No'`             |


# NewDisbursementForm



The `NewDisbursementForm` component provides a user interface for
creating a new disbursement. It’s a specialized form that captures all
necessary details for a disbursement, such as amount, type, and payment
method. The form fields dynamically adjust based on the selected
disbursement type defined in the data model.

Usage [#usage]

To use the `NewDisbursementForm`, you must provide context about the
account, such as its locator, balance, and currency, along with a
`dataModel` and a submit handler. The component wraps the
`JsonForms` library to render the form structure.

```ts
import { NewDisbursementForm } from '@socotra/ec-react-components';
import { DataModel, CurrencyType } from '@socotra/ec-react-schemas';

// Example Usage
const MyDisbursementComponent = ({ dataModel }: { dataModel: DataModel }) => {
  const handleSubmit = (disbursementData) => {
    console.log('Disbursement created:', disbursementData);
    // Handle API call to create the disbursement
  };

  return (
    <NewDisbursementForm
      accountLocator="123-abc"
      accountBalance={5000}
      currency={"USD" as CurrencyType}
      dataModel={dataModel}
      handleSubmit={handleSubmit}
      submitButtonText="Create Disbursement"
    />
  );
};
```

Props [#props]

The component accepts the following props:

| Prop               | Type                                        | Description                                                                                        | Default      |
| ------------------ | ------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------ |
| `accountLocator`   | `string`                                    | The unique locator for the account from which the disbursement will be made.                       | **Required** |
| `accountBalance`   | `number`                                    | The current balance of the account.                                                                | **Required** |
| `currency`         | `CurrencyType`                              | The currency for the disbursement transaction.                                                     | **Required** |
| `dataModel`        | `DataModel`                                 | The resolved data model object containing disbursement configurations and data types.              | **Required** |
| `handleSubmit`     | `(data: DisbursementCreateRequest) => void` | Callback function triggered on form submission with the fully formed disbursement request payload. | **Required** |
| `isSubmitting`     | `boolean`                                   | When true, disables the form fields and submit button.                                             | `false`      |
| `disabled`         | `boolean`                                   | When true, disables the entire form.                                                               | `false`      |
| `hideSubmitButton` | `boolean`                                   | If `true`, the submit button is not rendered.                                                      | `false`      |
| `validateOnSubmit` | `boolean`                                   | If `true`, validation is run on submit and submission is blocked if the data is invalid.           | `false`      |
| `submitButtonText` | `string`                                    | Custom text for the submit button.                                                                 | `'Update'`   |
| `id`               | `string`                                    | A unique ID for the form wrapper element.                                                          | `undefined`  |
| `titles`           | `object`                                    | An object to override default labels for the form title and other fields.                          | `{}`         |

State Management [#state-management]

`NewDisbursementForm` uses React’s `useState` hook to manage the
form’s data.

* The form’s entire data object is held in a single state variable.
* When the disbursement `type` is changed by the user, the component
  resets the `data` portion of the state to ensure no stale
  information is carried over, while preserving the selected `default`
  values.
* State is passed to and updated from the underlying `JsonForms`
  component.

Validation [#validation]

Validation is performed using [Ajv ](https://ajv.js.org) against a
dynamically generated JSON Schema.

* The JSON Schema is created based on the selected disbursement `type`
  from the `dataModel`. The `dataModelToJSONSchema` utility is used
  for this conversion.
* The form’s `ajv` instance is extended with custom formats and error
  handling.
* If `validateOnSubmit` is set to `true`, the `handleSubmit`
  function is blocked from being called if the form data is invalid.
* The `translateError` utility is used to provide user-friendly
  validation messages.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key                 | Description                               | Default Value          |
| ------------------- | ----------------------------------------- | ---------------------- |
| `formTitle`         | The main title for the form.              | `''`                   |
| `type`              | Label for the “Disbursement Type” field.  | `'Type'`               |
| `amount`            | Label for the “Amount” field.             | `'Amount'`             |
| `transactionMethod` | Label for the “Transaction Method” field. | `'Transaction Method'` |
| `transactionNumber` | Label for the “Transaction Number” field. | `'Transaction Number'` |
| `truthyLabel`       | Text for a “true” boolean value.          | `'Yes'`                |
| `falsyLabel`        | Text for a “false” boolean value.         | `'No'`                 |


# PaymentForms



This document details the three components related to payments:
`NewPaymentForm`, `ExistingPaymentForm`, and `ReversePaymentForm`.

***

1. NewPaymentForm [#1-newpaymentform]

Purpose [#purpose]

The `NewPaymentForm` is used to create a new payment from an external
source (e.g., credit card, bank transfer) and apply it to a specific
invoice. The form is dynamic, rendering different fields based on the
payment `type` selected, as defined in the data model.

Usage [#usage]

```ts
import { NewPaymentForm } from './NewPaymentForm';
import { DataModel, CurrencyType } from '@socotra/ec-react-schemas';

const MakePaymentComponent = ({ dataModel, invoice }: { dataModel: DataModel, invoice: any }) => {
  const handleSubmit = (paymentRequest) => {
    console.log('New Payment Request:', paymentRequest);
    // Handle API call to process the new payment
  };

  return (
    <NewPaymentForm
      accountLocator={invoice.accountLocator}
      invoiceLocator={invoice.locator}
      invoiceBalance={invoice.balance}
      currency={invoice.currency as CurrencyType}
      dataModel={dataModel}
      handleSubmit={handleSubmit}
    />
  );
};
```

Props [#props]

| Prop             | Type                             | Description                                                     | Required |
| ---------------- | -------------------------------- | --------------------------------------------------------------- | -------- |
| `accountLocator` | `string`                         | The locator of the account associated with the payment.         | Yes      |
| `invoiceLocator` | `string`                         | The locator of the invoice being paid.                          | Yes      |
| `invoiceBalance` | `number`                         | The outstanding balance of the invoice.                         | Yes      |
| `currency`       | `CurrencyType`                   | The currency of the payment.                                    | Yes      |
| `dataModel`      | `DataModel`                      | The resolved data model containing payment type configurations. | Yes      |
| `handleSubmit`   | `(data: PaymentRequest) => void` | Callback with the `PaymentRequest` payload.                     | Yes      |

State Management [#state-management]

* The component initializes its state with the `invoiceBalance`
  pre-filled as the default payment `amount`.
* It holds all form data in a single state object.
* When the payment `type` is changed, the component intelligently
  resets the nested `data` object to avoid sending stale data from the
  previously selected type, while preserving the top-level default
  values.

Validation [#validation]

Validation is handled by [Ajv ](https://ajv.js.org/). A JSON schema is
built dynamically based on the fields defined for the selected payment
`type` in `dataModel.payments`.

Labels and Translations [#labels-and-translations]

**UI Labels**

Labels are customized via the `titles` prop.

| Key                 | Description                               | Default Value          |
| ------------------- | ----------------------------------------- | ---------------------- |
| `formTitle`         | The main title for the form.              | `''`                   |
| `type`              | Label for the “Payment Type” dropdown.    | `'Type'`               |
| `amount`            | Label for the “Amount” field.             | `'Amount'`             |
| `transactionMethod` | Label for the “Transaction Method” field. | `'Transaction Method'` |
| `transactionNumber` | Label for the “Transaction Number” field. | `'Transaction Number'` |
| `truthyLabel`       | Text for a “true” boolean value.          | `'Yes'`                |
| `falsyLabel`        | Text for a “false” boolean value.         | `'No'`                 |

***

2. ExistingPaymentForm [#2-existingpaymentform]

<span id="purpose-1" />

Purpose [#purpose-1]

The `ExistingPaymentForm` is used to apply a credit that already
exists on an account to an outstanding invoice. It is not for new
payments, but rather for distributing existing, unapplied funds.

<span id="usage-1" />

Usage [#usage-1]

```ts
import { ExistingPaymentForm } from './ExistingPaymentForm';

const ApplyCreditComponent = ({ account, invoice }: { account: any, invoice: any }) => {
  const handleSubmit = (creditDistributionRequest) => {
    console.log('Credit Distribution Request:', creditDistributionRequest);
    // Handle API call to apply the credit
  };

  return (
    <ExistingPaymentForm
      accountLocator={account.locator}
      invoiceLocator={invoice.locator}
      balance={account.unappliedCredit}
      invoiceBalance={invoice.balance}
      currency={invoice.currency}
      handleSubmit={handleSubmit}
    />
  );
};
```

<span id="props-1" />

Props [#props-1]

| Prop             | Type                                        | Description                                            | Required |
| ---------------- | ------------------------------------------- | ------------------------------------------------------ | -------- |
| `accountLocator` | `string`                                    | The locator of the account holding the credit.         | Yes      |
| `invoiceLocator` | `string`                                    | The locator of the invoice to apply the credit to.     | Yes      |
| `balance`        | `number`                                    | The available credit/unapplied balance on the account. | Yes      |
| `invoiceBalance` | `number`                                    | The outstanding balance of the target invoice.         | Yes      |
| `currency`       | `CurrencyType`                              | The currency of the transaction.                       | Yes      |
| `handleSubmit`   | `(data: CreditDistributionRequest) => void` | Callback with the `CreditDistributionRequest` payload. | Yes      |

<span id="state-management-1" />

State Management [#state-management-1]

The form’s state is simple, primarily managing the `amount` the user
wishes to apply. The `balance` and `invoiceBalance` fields are
displayed as read-only.

<span id="validation-1" />

Validation [#validation-1]

Validation is handled by [Ajv ](https://ajv.js.org/). The schema is
defined directly within the component and ensures the `amount` to
apply is greater than zero and does not exceed the available account
`balance`.

<span id="labels-and-translations-1" />

Labels and Translations [#labels-and-translations-1]

**UI Labels**

Labels are customized via the `titles` prop.

| Key              | Description                              | Default Value       |
| ---------------- | ---------------------------------------- | ------------------- |
| `formTitle`      | The main title for the form.             | `''`                |
| `invoiceBalance` | Label for the read-only invoice balance. | `'Invoice Balance'` |
| `balance`        | Label for the read-only account balance. | `'Balance'`         |
| `amountToApply`  | Label for the input field.               | `'Amount to Apply'` |

***

3. ReversePaymentForm [#3-reversepaymentform]

<span id="purpose-2" />

Purpose [#purpose-2]

The `ReversePaymentForm` is a simple form used to initiate the
reversal of a previously applied payment. Its main function is to
capture the reason for the reversal.

<span id="usage-2" />

Usage [#usage-2]

```ts
import { ReversePaymentForm } from './ReversePaymentForm';
import { DataModel } from '@socotra/ec-react-schemas';

const ReversePaymentComponent = ({ payment, dataModel }: { payment: any, dataModel: DataModel }) => {
  const handleSubmit = (reverseRequest) => {
    console.log('Payment Reversal Request:', reverseRequest);
    // Handle API call to reverse the payment
  };

  return (
    <ReversePaymentForm
      amount={payment.amount}
      currency={payment.currency}
      reversalTypes={dataModel.reversalTypes}
      handleSubmit={handleSubmit}
    />
  );
};
```

<span id="props-2" />

Props [#props-2]

| Prop            | Type                                               | Description                                                   | Required |
| --------------- | -------------------------------------------------- | ------------------------------------------------------------- | -------- |
| `amount`        | `number`                                           | The amount of the payment being reversed.                     | Yes      |
| `currency`      | `CurrencyType`                                     | The currency of the reversed payment.                         | Yes      |
| `reversalTypes` | `ReversalTypeConfigRecord`                         | The reversal type configurations from the data model.         | Yes      |
| `handleSubmit`  | `(data: CreditDistributionReverseRequest) => void` | Callback with the `CreditDistributionReverseRequest` payload. | Yes      |

<span id="state-management-2" />

State Management [#state-management-2]

The component’s state manages the selected `reversalType`. The
`amount` is displayed as a read-only field. The list of reversal
reasons is filtered to only show types that are not for new payments.

<span id="validation-2" />

Validation [#validation-2]

Validation is handled by [Ajv ](https://ajv.js.org/). The schema,
defined within the component, simply requires that a `reversalType` be
selected from the list.

<span id="labels-and-translations-2" />

Labels and Translations [#labels-and-translations-2]

**UI Labels**

Labels are customized via the `titles` prop.

| Key               | Description                             | Default Value           |
| ----------------- | --------------------------------------- | ----------------------- |
| `formTitle`       | The main title for the form.            | `''`                    |
| `amountToReverse` | Label for the read-only amount field.   | `'Amount to Reverse'`   |
| `reversalType`    | Label for the reversal reason dropdown. | `'Reason for Reverse?'` |


# PolicyForm



The `PolicyForm` is a specialized, **read-only** component designed to
display the top-level data of an issued policy. Unlike the other forms,
it is not interactive and does not include a submit button or
validation. Its primary role is to present a structured, user-friendly
view of the policy’s core information, advanced settings, and coverage
terms.

This component is often used as the root of a policy view, rendered
alongside multiple `ElementForm` components (in their `readonly` or
`disabled` state) to display the policy’s full hierarchy of
sub-elements like vehicles, drivers, or locations.

Usage [#usage]

To use the `PolicyForm`, you must provide the `policy` response, the
relevant `segment` from that policy, and the complete `dataModel`.

```tsx
import {
	DataModel,
	PolicyResponse,
	SegmentResponse,
} from '@socotra/ec-react-schemas';

import { ElementForm } from '../ElementForm'; // Example of a sub-element
import { PolicyForm } from './PolicyForm';

const PolicyDetailsView = ({
	policy,
	dataModel,
}: {
	policy: PolicyResponse;
	dataModel: DataModel;
}) => {
	// Assuming the first segment holds the main policy data
	const primarySegment = policy.segments[0];

	return (
		<div>
			<h2>Policy Details</h2>
			<PolicyForm
				policy={policy}
				segment={primarySegment}
				dataModel={dataModel}
			/>

			{/* Example of rendering sub-elements alongside the policy form */}
			{policy.elements.map((element) => (
				<div key={element.locator}>
					<h3>{element.displayName}</h3>
					// Using disabled to make it read-only
					<ElementForm
						element={element}
						elementModel={dataModel.elements[element.type]}
						dataModel={dataModel}
						timezone={policy.timezone}
						disabled
						hideSubmitButton
					/>
				</div>
			))}
		</div>
	);
};
```

Props [#props]

| Prop            | Type              | Description                                                   | Required |
| --------------- | ----------------- | ------------------------------------------------------------- | -------- |
| `policy`        | `PolicyResponse`  | The full policy response object.                              | Yes      |
| `segment`       | `SegmentResponse` | The specific policy segment to display data from.             | Yes      |
| `dataModel`     | `DataModel`       | The complete, resolved data model.                            | Yes      |
| `id`            | `string`          | An optional ID for the form wrapper element.                  | No       |
| `hideAllFields` | `boolean`         | If `true`, hides all generated field sections.                | No       |
| `titles`        | `object`          | An object to override default labels for sections and fields. | No       |

State Management [#state-management]

The `PolicyForm` is effectively stateless from a user-interaction
perspective. It uses a `useMemo` hook to derive its display data by
calling the `getDefaultPolicyValues` utility function. This data is
calculated once based on the initial props (`policy`,
`productModel`, `element`, `dataModel`) and does not change.

Validation [#validation]

No validation is performed by this component. It is strictly for display
purposes, and all its fields are rendered as `readonly`.

Labels and Translations [#labels-and-translations]

The text for UI labels can be customized by passing a `titles` object
prop.

| Key                   | Description                                   | Default Value              |
| --------------------- | --------------------------------------------- | -------------------------- |
| `formTitle`           | The main title for the form.                  | `''`                       |
| `details`             | Title for the main “Details” section.         | `'Details'`                |
| `seeAdvancedDetails`  | Title for the collapsible “Advanced” section. | `'See Advanced Details'`   |
| `coverageTerms`       | Title for the “Coverage Terms” section.       | `'Coverage Terms'`         |
| `startTime`           | Label for the “Start Time” field.             | `'Start Time'`             |
| `endTime`             | Label for the “End Time” field.               | `'End Time'`               |
| `currency`            | Label for the “Currency” field.               | `'Currency'`               |
| `timezone`            | Label for the “Timezone” field.               | `'Timezone'`               |
| `billingLevel`        | Label for the “Billing Level” field.          | `'Billing Level'`          |
| `billingTrigger`      | Label for the “Billing Trigger” field.        | `'Billing Trigger'`        |
| `durationBasis`       | Label for the “Duration Basis” field.         | `'Duration Basis'`         |
| `delinquencyPlanName` | Label for the “Delinquency Plan” field.       | `'Delinquency Plan Name'`  |
| `autoRenewalPlanName` | Label for the “Auto-Renewal Plan” field.      | `'Auto-renewal Plan Name'` |
| `truthyLabel`         | Text for a “true” boolean value.              | `'Yes'`                    |
| `falsyLabel`          | Text for a “false” boolean value.             | `'No'`                     |


# QuoteForm



The `QuoteForm` is a comprehensive component for creating and updating
a quote. It serves as a primary interface during the quoting process,
dynamically assembling various sections—product-specific fields, general
policy details, advanced settings, and coverage terms—into a single,
cohesive form. It is designed to be highly configurable and supports
complex, backend-driven field dependencies through constraint
evaluation.

Usage [#usage]

To use the `QuoteForm`, you must provide the `quote` object to be
modified, the full `dataModel`, and a `handleSubmit` function. The
form’s appearance and behavior can be extensively customized through
various `hide...` props and by optionally enabling constraint
evaluation.

```ts
import { QuoteForm } from '@socotra/ec-react-components';
import {
    DataModel,
    QuoteResponse,
    EvaluateConstraintsRequest,
    EvaluateConstraintsResponse,
    DependencyMapResponse,
} from '@socotra/ec-react-schemas';

// Example Usage
const MyQuotePage = ({
    quote,
    dataModel,
    dependencyMap,
}: {
    quote: QuoteResponse,
    dataModel: DataModel,
    dependencyMap: DependencyMapResponse,
}) => {
    const handleSubmit = (quoteRequest) => {
        console.log('Quote Update Request:', quoteRequest);
        // Handle API call to update the quote
    };

    const handleEvaluateConstraints = async (
        request: EvaluateConstraintsRequest,
    ): Promise<EvaluateConstraintsResponse | undefined> => {
        console.log('Evaluating constraints:', request);
        // API call to the backend to get calculated values
        return fetch(/*...- /constraints/evaluate ...*/).then((res) => res.json());
    };

    return (
        <QuoteForm
            quote={quote}
            dataModel={dataModel}
            handleSubmit={handleSubmit}
            dependencyMap={dependencyMap}
            getEvaluatedConstraints={handleEvaluateConstraints}
            submitButtonText='Update Quote'
        />
    );
};
```

Props [#props]

| Prop                      | Type                                                                                     | Description                                                                                                   | Default      |
| ------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------ |
| `quote`                   | `QuoteResponse`                                                                          | The quote object being edited.                                                                                | **Required** |
| `dataModel`               | `DataModel`                                                                              | The entire resolved data model for the tenant.                                                                | **Required** |
| `handleSubmit`            | `(data: QuoteRequest) => void`                                                           | Callback triggered on submit, receiving the `QuoteRequest` payload.                                           | **Required** |
| `dependencyMap`           | `DependencyMapResponse`                                                                  | Optional map of field dependencies, required to enable constraint evaluation.                                 | `undefined`  |
| `getEvaluatedConstraints` | `(request, tenantLocator, locator) => Promise<EvaluateConstraintsResponse \| undefined>` | Optional async function to call the backend for constraint evaluation. Required for the feature to be active. | `undefined`  |
| `hideDefaultFields`       | `boolean`                                                                                | If `true`, hides the default “Details” section (e.g., currency, timezone).                                    | `false`      |
| `hideAdvancedFields`      | `boolean`                                                                                | If `true`, hides the collapsible “Advanced Fields” section.                                                   | `false`      |
| `hideCoverageTerms`       | `boolean`                                                                                | If `true`, hides the “Coverage Terms” section.                                                                | `false`      |
| `hideAllFields`           | `boolean`                                                                                | If `true`, hides all dynamically generated sections (Default, Advanced, Coverage Terms, and Product data).    | `false`      |
| `hiddenExceptions`        | `string[]`                                                                               | When `hideAllFields` is true, provide an array of field names from the product model to still display.        | `[]`         |
| `titles`                  | `object`                                                                                 | An object to override default labels for form sections and fields. See “Labels and Translations” below.       | `{}`         |

…plus other standard form props (`isSubmitting`, `disabled`,
`submitButtonText`, etc.).

State Management [#state-management]

The form manages its state internally using `useState` and
`useEffect`.

* **Data Initialization:** The form’s data is initialized by
  `getDefaultQuoteValues`, which combines data from the `quote`
  object, the relevant `productModel`, and the overall `dataModel`.
* **Prop Synchronization:** A `useEffect` hook tracks changes to the
  incoming `quote` prop. If the prop is updated externally (e.g.,
  after a save operation), the form’s internal state is re-initialized
  to reflect the latest data.
* **Constraint State:** The component maintains an
  `evaluatedConstraints` state. This state is populated by the
  response from the `getEvaluatedConstraints` function and is cleared
  whenever the user modifies the form data, ensuring that constraints
  are re-evaluated on the next relevant change.

Constraint Evaluation [#constraint-evaluation]

This form supports a powerful constraint evaluation system to create
dynamic relationships between fields.

* **Purpose:** To automatically calculate or update the values of
  certain fields based on user input in other fields, without requiring
  a full form submission. For example, selecting a specific “Region”
  could automatically populate a “Tax Rate” field.
* **Activation:** The feature is enabled by providing both the
  `dependencyMap` and `getEvaluatedConstraints` props.
* **Mechanism:**
  1. The `dependencyMap` tells the form which fields depend on others.
  2. When a user changes a field that is a dependency for another, a
     `useEffect` hook is triggered.
  3. This hook calls the `getEvaluatedConstraints` function with a
     payload of the changed data.
  4. The backend service evaluates the data and returns a
     `EvaluateConstraintsResponse` containing the new values for any
     dependent fields.
  5. This response is stored in the `evaluatedConstraints` state,
     which triggers a re-render.
  6. The `dataModelToJSONSchema` utility uses this response to update
     the JSON Schema, making the calculated fields read-only and
     displaying their new values.

Validation [#validation]

Client-side validation is handled by [Ajv ](https://ajv.js.org/). The
schema used for validation is highly dynamic, built on the fly by the
`dataModelToJSONSchema` utility. It combines definitions for default
fields, advanced fields, coverage terms, and product-specific fields.
The `hide...` props directly affect which sections are included in the
schema. When constraint evaluation is active, the schema is further
modified to reflect the calculated values.

Labels and Translations [#labels-and-translations]

The text for UI labels and validation messages can be customized.

**UI Labels**

Labels for sections and fields can be overridden by passing a `titles`
object prop.

| Key                   | Description                                   | Default Value            |
| --------------------- | --------------------------------------------- | ------------------------ |
| `details`             | Title for the main “Details” section.         | `'Details'`              |
| `seeAdvancedDetails`  | Title for the collapsible “Advanced” section. | `'See Advanced Details'` |
| `coverageTerms`       | Title for the “Coverage Terms” section.       | `'Coverage Terms'`       |
| `currency`            | Label for the “Currency” field.               | `'Currency'`             |
| `timezone`            | Label for the “Timezone” field.               | `'Timezone'`             |
| `billingLevel`        | Label for the “Billing Level” field.          | `'Billing Level'`        |
| `billingTrigger`      | Label for the “Billing Trigger” field.        | `'Billing Trigger'`      |
| `durationBasis`       | Label for the “Duration Basis” field.         | `'Duration Basis'`       |
| `delinquencyPlanName` | Label for the “Delinquency Plan” field.       | `'Delinquency Plan'`     |
| `autoRenewalPlanName` | Label for the “Auto-Renewal Plan” field.      | `'Auto-renewal Plan'`    |
| `installmentPlanName` | Label for the “Installment Plan” field.       | `'Installment Plan'`     |
| `truthyLabel`         | Text for a “true” boolean value.              | `'Yes'`                  |
| `falsyLabel`          | Text for a “false” boolean value.             | `'No'`                   |


# Rendering Customizations



This guide explains how to use the `tag` property on a field within
the data model to customize its behavior in the UI when using
`@socotra/ec-react-components`.

Hiding Fields [#hiding-fields]

For fields that should be part of the data model but should almost never
be shown in the UI, you can use the simple `hidden` tag. This tag
removes the field from the form schema during generation, ensuring it
does not render.

This provides a way to control field visibility at the data-model level,
rather than passing a prop to every form instance. The only way to make
a `hidden` field appear is to pass its name in the
`hiddenExceptions` array prop on the form component, making it a
deliberate choice to show it.

* **Tag Format:** `hidden`

Example [#example]

Imagine you have an `internalNotes` field on your `Quote` data
model. This field should be saved with the quote data but should not be
visible on the standard quote form.

**Data Model Configuration:**

```json
{
	"internalNotes": {
		"type": "string",
		"displayName": "Internal Notes",
		"tag": ["hidden"]
	},
	"premiumAmount": {
		"type": "decimal",
		"displayName": "Premium Amount",
		"tag": ["currency.USD"]
	}
}
```

**Result:**

* By default, the `QuoteForm` will **not** display the “Internal
  Notes” field. It is completely removed from the generated schema.

* If you have a special administrative view where you *do* want to show
  this field, you would render the `QuoteForm` with the
  `hiddenExceptions` prop:

```tsx
<QuoteForm hiddenExceptions={['internalNotes']} />
```

Only in this specific instance would the “Internal Notes” field
appear.

Hiding Fields Conditionally [#hiding-fields-conditionally]

The forms support two distinct methods for hiding fields based on the
values of other fields:

1. **Dynamic Client-Side Hiding:** Hides a field based on the value of
   another field *within the same form*. This is ideal for dynamic UIs
   where you want a field to appear or disappear immediately as the user
   makes selections.
2. **Static Schema-Level Hiding:** Hides a field based on a value from
   the root `quote` object. This is useful when a field’s visibility
   depends on a more global state that doesn’t change within the context
   of the current form.

Dynamic Client-Side Hiding (hidden|...) [#dynamic-client-side-hiding-hidden]

This method uses a UI schema rule to show or hide a field. The change
happens instantly on the client-side without a backend call.

* **Tag Format:** `hidden|{fieldName}{operator}{value}`
  * `fieldName`: The name of the field *within the same data model
    level* whose value will be checked.
  * `operator`: Must be either `==` (equals) or `!=` (not equals).
  * `value`: The value to check against (e.g., `true`, `CAR`,
    `123`).

<span id="example-1" />

Example [#example-1]

Imagine you have a `vehicleType` field and you only want to show the
`vin` field if the `vehicleType` is “CAR”.

**Data Model Configuration:**

On your `vin` field, you would add the following tag:

```json
{
	"vin": {
		"type": "string",
		"displayName": "VIN",
		"tag": ["hidden|vehicleType!=CAR"]
	},
	"vehicleType": {
		"type": "string",
		"displayName": "Vehicle Type",
		"options": ["CAR", "MOTORCYCLE", "BOAT"]
	}
}
```

**Result:**

* The “VIN” field will be hidden by default.
* If the user selects “CAR” from the “Vehicle Type” dropdown, the “VIN”
  field will instantly appear.
* If the user selects “MOTORCYCLE” or “BOAT”, the “VIN” field will
  remain hidden.

Static Schema-Level Hiding (rootHidden|...) [#static-schema-level-hiding-roothidden]

This method filters a field out of the JSON Schema itself during its
creation. This is best when the condition for hiding is based on data
outside the immediate form’s scope, specifically from the root quote’s
element data.

* **Tag Format:** `rootHidden|{fieldName}{operator}{value}`
  * `fieldName`: The name of a field located at the
    `quote.element.data` path.
  * `operator`: Must be either `==` or `!=`.
  * `value`: The value to check against.

<span id="example-2" />

Example [#example-2]

Suppose you have an `additionalInsured` element on your quote. You
want to hide the `relationshipToPrimary` field within that element if
the `policyHolderType` (a field on the root quote’s element) is
“INDIVIDUAL”.

**Data Model Configuration:**

On your `relationshipToPrimary` field (inside the
`additionalInsured` element’s model), you would add the following tag:

```json
{
	"relationshipToPrimary": {
		"type": "string",
		"displayName": "Relationship to Primary Insured",
		"tag": ["rootHidden|policyHolderType==INDIVIDUAL"]
	}
}
```

**Result:**

* When the `ElementForm` for the `additionalInsured` element is
  rendered, the system checks the value of
  `quote.element.data.policyHolderType`.
* If the value is “INDIVIDUAL”, the `relationshipToPrimary` field will
  be completely omitted from the form’s schema and will not be rendered.
* If the value is anything else (e.g., “CORPORATION”), the field will be
  included in the schema and rendered in the form.

Horizontal Layout for Custom Data Types [#horizontal-layout-for-custom-data-types]

When working with custom data types (repeatable sets of fields like a
“Driver” or “Vehicle”), you can control how the fields are displayed. By
default, fields are rendered in a two-column layout. By using the
`horizontal-layout` tag, you can force the fields within that custom
data type to render in a single-column layout, where each field takes up
the full width of its row.

* **Tag Format:** `horizontal-layout`

<span id="example-3" />

Example [#example-3]

Imagine you have a `Driver` custom data type that contains
`driverName` and `licenseNumber` fields. You want to add a list of
drivers to a quote, but you want each driver’s fields to be laid out
horizontally for better readability.

**Data Model Configuration:**

1. Define your `Driver` custom data type.
2. On the field in your product model that *references* the `Driver`
   type, add the `horizontal-layout` tag.

```json
// In your product's data model
{
  "drivers": {
    "type": "Driver*", // This is an array of the "Driver" custom data type
    "displayName": "Drivers",
    "tag": ["horizontal-layout"] // Apply the tag here
  }
}

// In your dataTypes configuration
{
  "Driver": {
    "displayName": "Driver",
    "data": {
      "driverName": {
        "type": "string",
        "displayName": "Driver Name"
      },
      "licenseNumber": {
        "type": "string",
        "displayName": "License Number"
      }
    }
  }
}
```

**Result:**

When the form renders the “Drivers” section, instead of stacking the
“Driver Name” and “License Number” fields in a two-column grid, each
driver entry will be displayed in its own row, with the “Driver Name”
label and input field appearing next to each other, taking up the full
available width. This provides a more compact and linear layout for
nested data.

Multi-Select Dropdown for Arrays [#multi-select-dropdown-for-arrays]

For fields that are an array of primitive values (like `string*` or
`int+`) and have a predefined list of choices, you can use the
`multiselect` tag to render the input as a multi-select dropdown or
checkbox group instead of the default array input UI.

* **Tag Format:** `multiselect`
* **Prerequisites:**
  * The field `type` must be an array of primitives (e.g.,
    `string*`, `string+`, `int*`).
  * The field definition must include an `options` array containing
    the list of choices.

<span id="example-4" />

Example [#example-4]

Imagine you want users to select multiple “coverage add-ons” from a list
for their policy.

**Data Model Configuration:**

On your `coverageAddOns` field, you define it as an array of strings,
provide the list of options, and add the tag.

```json
{
	"coverageAddOns": {
		"type": "string*",
		"displayName": "Coverage Add-ons",
		"tag": ["multiselect"],
		"options": [
			"Roadside Assistance",
			"Rental Reimbursement",
			"Towing and Labor",
			"Glass Coverage"
		]
	}
}
```

**Result:**

* **Without the tag:** The UI would render a label “Coverage Add-ons”
  with an “Add” button. Clicking “Add” would create a new select input
  field, forcing the user to select 1 option at a time.
* **With the `multiselect` tag:** The UI renders a single multi-select
  dropdown or a group of checkboxes with all the options listed,
  allowing the user to easily select multiple items from the predefined
  list.

Rendering as a Radio Group [#rendering-as-a-radio-group]

For fields that have a small, fixed set of options, you can use the
`radio-group` tag to display them as a set of radio buttons instead of
a dropdown. This is often more user-friendly when there are only a few
choices.

* **Tag Format:** `radio-group`
* **Prerequisites:**
  * The field `type` must be `string`.
  * The field definition must include an `options` array with the
    available choices.

<span id="example-5" />

Example [#example-5]

Suppose you have a `region` field where the user must select either
“West” or “East”.

**Data Model Configuration:**

On your `region` field, you define it as a string, provide the list of
options, and add the tag.

```json
{
	"region": {
		"type": "string",
		"displayName": "Region",
		"options": ["West", "East"],
		"tag": ["radio-group"]
	}
}
```

**Result:**

* **Without the tag:** The UI would render a standard dropdown menu with
  “West” and “East” as options.
* **With the `radio-group` tag:** The UI will render two radio
  buttons, one for “West” and one for “East”, allowing the user to see
  all options at a glance and select one.

Displaying Currency Fields [#displaying-currency-fields]

To ensure that number fields are correctly formatted and displayed as
currency in the UI, you need to add a specific `currency` tag. This
tag tells the renderer to apply currency formatting, such as adding a
currency symbol (e.g., “$”) and appropriate delimiters.

* **Tag Format:** `currency.{CURRENCY_CODE}`
  * `CURRENCY_CODE`: The standard three-letter ISO 4217 currency code
    (e.g., `USD`, `EUR`, `JPY`).

<span id="example-6" />

Example [#example-6]

You have a field for `premiumAmount` that should be treated as US
Dollars.

**Data Model Configuration:**

On your `premiumAmount` field, you add the `currency.USD` tag.

```json
{
	"premiumAmount": {
		"type": "decimal",
		"displayName": "Premium Amount",
		"tag": ["currency.USD"]
	}
}
```

**Result:**

The UI will render the “Premium Amount” field as a currency input. As
the user types, it will automatically be formatted with a dollar sign,
commas for thousands separators, and will handle decimal places
appropriately, for example, displaying `$1,234.50`.

Disable Fields [#disable-fields]

For fields that should be visible in the UI but should not be editable
by users, you can use the `readOnly` tag. This tag renders the field
as a read-only input, displaying the current value but preventing user
interaction. This is useful for displaying calculated values,
system-generated data, or fields that should only be modified under
specific conditions.

* **Tag Format:** `readOnly`

<span id="example-7" />

Example [#example-7]

Imagine you have a `policyNumber` field that is automatically
generated by the system and should not be editable by users, but they
should be able to see it.

**Data Model Configuration:**

On your `policyNumber` field, you add the `readOnly` tag.

```json
{
	"policyNumber": {
		"type": "string",
		"displayName": "Policy Number",
		"tag": ["readOnly"]
	},
	"premiumAmount": {
		"type": "decimal",
		"displayName": "Premium Amount",
		"tag": ["currency.USD"]
	}
}
```

**Result:**

* The “Policy Number” field will be rendered as a disabled input field,
  showing the current value but preventing the user from typing or
  modifying it.
* The field will appear grayed out or with a different visual style to
  indicate it’s read-only.
* The value will still be included in form submissions and data
  validation.


# Theming



This guide details the two primary methods for customizing the visual
appearance (colors, fonts, border radius, etc.) of the
`@socotra/ec-react-components` library.

***

Method 1: Theming with Tailwind CSS and shadcn/ui (Recommended) [#method-1-theming-with-tailwind-css-and-shadcnui-recommended]

The most powerful and recommended method for customization is to
integrate the components directly into a project that uses Tailwind CSS
and has `shadcn/ui` initialized. Because our components are built with
these tools, they will automatically adopt the theme you define in your
application.

This approach gives you complete control over the library’s look and
feel, ensuring it seamlessly matches your application’s design system.

Step 1: Install shadcn/ui [#step-1-install-shadcnui]

If you haven’t already, install `shadcn/ui` in your host application
by following the official guide on the `shadcn/ui
website <https://ui.shadcn.com/docs/installation>`\_\_. This process will
create a `components.json` file and set up your project to use CSS
variables for theming.

Step 2: Configure tailwind.config.js [#step-2-configure-tailwindconfigjs]

Ensure your project’s `tailwind.config.js` is configured to scan the
`@socotra/ec-react-components` library for Tailwind classes. This
allows Tailwind to include the necessary styles in its build process.

```js
// tailwind.config.js
module.exports = {
	//...
	content: [
		'./app/**/*.{ts,tsx}',
		'./components/**/*.{ts,tsx}',
		'./node_modules/@socotra/ec-react-components/dist/**/*.js', // Add this line
	],
	//...
};
```

Step 3: Customize Your Theme [#step-3-customize-your-theme]

Now, you can customize your theme by modifying the CSS variables that
`shadcn/ui` uses. These are typically located in your main CSS file
(e.g., `app/globals.css`). By changing these variables, you can alter
colors, border radii, fonts, and more across your entire application
*and* within the Socotra components.

For example, to change the primary brand color:

```css
/* app/globals.css */
@layer base {
	:root {
		/* ... other variables */
		--primary: 222.2 84% 4.9%; /* Change this value */
		--primary-foreground: 210 40% 98%; /* And this one */
		--radius: 0.5rem; /* Change border radius */
		/* ... etc. */
	}
}
```

You can use the [theme creator ](https://ui.shadcn.com/themes) on the
`shadcn/ui` website to easily generate your desired color palette.

Step 4: Do Not Import the Pre-built CSS [#step-4-do-not-import-the-pre-built-css]

**Important:** When using this method, **do not** import the library’s
pre-built stylesheet (`@socotra/ec-react-components/dist/style.css`).
Your project’s Tailwind build process will handle all styling, and
importing the CSS file will lead to style conflicts.

***

Method 2: Basic CSS Import (Without Tailwind) [#method-2-basic-css-import-without-tailwind]

If your project does not use Tailwind CSS, you can still use the
components by importing the compiled stylesheet. This method is simpler
but offers no customization options.

Usage [#usage]

In the root of your application (e.g., `main.tsx` or `_app.tsx`),
import the `style.css` file directly from the package:

```js
import '@socotra/ec-react-components/dist/style.css';
```

This will apply the default, pre-packaged Socotra theme to the
components. With this method, you cannot change colors, fonts, or other
themeable properties without manually overriding CSS classes, which is
not recommended.

***

Method 3: Per-Component Style Overrides (Advanced) [#method-3-per-component-style-overrides-advanced]

For the most granular level of control, you can pass a `styles` prop
directly to a form component. This allows you to override the styles for
specific UI elements within that single form instance, without affecting
any other forms in your application.

This method is ideal when you need to make a one-off adjustment to a
particular form’s layout or appearance. The `styles` prop accepts an
array of `StyleDefinition` objects. Each object targets a specific
part of the form’s UI and applies one or more CSS or Tailwind classes.

<span id="usage-1" />

Usage [#usage-1]

Pass an array to the `styles` prop of a form component like
`QuoteForm`, `ElementForm`, etc.

```tsx
<QuoteForm
	styles={[
		{ name: 'control.label', classNames: ['font-bold', 'text-blue-600'] },
		{ name: 'control.input', classNames: ['bg-gray-50'] },
	]}
/>
```

Supported Style Targets [#supported-style-targets]

The `name` property of the `StyleDefinition` object can be one of
the following values, each targeting a specific part of the UI generated
by `@jsonforms`.

| Style Name                     | Target Element                                              |
| ------------------------------ | ----------------------------------------------------------- |
| `control`                      | The main wrapper for a single form control (label + input). |
| `control.label`                | The `<label>` element for a control.                        |
| `control.input`                | The input element itself (`<input>`, `<select>`, etc.).     |
| `control.checkbox`             | Specific styling for a checkbox input.                      |
| `control.validation`           | The container for a control’s validation message.           |
| `control.validation.error`     | The specific error message text.                            |
| `input.description`            | The description text that appears below an input.           |
| `group.layout`                 | The container (`<fieldset>`) for a group of fields.         |
| `group.label`                  | The label (`<legend>`) for a field group.                   |
| `vertical.layout`              | The main container for a form with a vertical layout.       |
| `vertical.layout.item`         | An individual item within a vertical layout.                |
| `horizontal.layout`            | The container for a `HorizontalLayout`.                     |
| `horizontal.layout.item`       | An individual item within a horizontal layout.              |
| `array.layout`                 | The main container for an array of items.                   |
| `array.button`                 | The “Add” button for array fields.                          |
| `array.table`                  | The container for a table-based array renderer.             |
| `array.table.table`            | The `<table>` element itself.                               |
| `array.table.label`            | The label/header for the table array.                       |
| `array.table.button`           | The “Add” button within the table array.                    |
| `array.table.validation`       | The validation message container for the table.             |
| `array.table.validation.error` | A specific error message in a table.                        |
| `categorization`               | The root element for a categorized layout.                  |
| `categorization.master`        | The master list (e.g., tabs) in a master-detail view.       |
| `categorization.detail`        | The detail panel in a master-detail view.                   |


# Data Lake Table Reference



This page is the complete field-level reference for every table in the Socotra [Data Lake](/features/reporting/datalake).

<Callout>
  The order of fields shown in this reference is for informational purposes only
  and may differ from the order in the underlying [Data Lake
  Database](/features/reporting/datalake) schema or [Delta
  Files](/features/reporting/delta-files). The exact schema may also vary
  between the two. To view the authoritative schema, connect directly to the
  Data Lake Database using your provided credentials or download the
  `createTableFile` provided by the{' '}
  <ApiLink name="DeltaFilesGetResponse">Delta Files API</ApiLink>.
</Callout>

Contents [#contents]

* [Schema Conventions](#schema-conventions)
* [Attribute Labels](#attribute-labels)
* [Policy Tables](#policy-tables)
* [Billing Tables](#billing-tables)
* [Claims Tables](#claims-tables)
* [Producer Management Tables](#producer-management-tables)
* [Work Management Tables](#work-management-tables)
* [Auxiliary Data Tables](#auxiliary-data-tables)
* [Moratoriums Tables](#moratoriums-tables)

Schema Conventions [#schema-conventions]

The Data Lake adheres to these schema conventions:

* **Locators**: Locators are unique identifiers in the Socotra platform; most tables have a `locator` column that represents the unique identifier for each record. They are stored in `ULID` format.
* **Tenant Locators**: All tables have a `tenant_locator` column referencing the record's corresponding tenant. They are stored in `UUID` format.
* **User Locators**: User locators are persisted as either a `user_locator` or for certain user actions using the `_by` format (e.g. `created_by`, `updated_by`, `completed_by`). They are stored in `UUID` format.
* **Primary Keys**: All tables have a composite primary key, each containing a `tenant_locator` and either a `locator` or other column(s).
* **Foreign Keys**: No tables have explicit foreign keys established, but many foreign relationships exist. Fields named `_locator` are typically implicit foreign keys, with the prefix indicating the referenced entity (e.g. `account_locator` -> `accounts.locator`).
* **Polymorphic Relationships**: Some table relationships follow a polymorphic pattern, with a discriminator `_type` column paired with a `_locator` column where the target table depends on the type value (e.g. `reference_type` = `policy` -> `reference_locator` = `policies.locator`).
* **Indexes**: Primary keys and the `datalake_updated_timestamp` are indexed on all tables, with minimal indexes beyond that.
* **Timestamps**: All timestamps are in Coordinated Universal Time (UTC) unless otherwise indicated.
* **Data Lake Timestamps**: The `datalake_created_timestamp` and `datalake_updated_timestamp` are on all tables. These reflect when the record was written or updated in the Data Lake, rather than when the business event occurred. Use domain-specific timestamps (e.g. `created_time_utc`, `updated_time_utc`) for understanding business or operational events.
* **Monetary Amounts**: Monetary amounts are typically stored as `decimal(19,3)` and are in the currency indicated by the `currency` column on that record or parent entity.
* **Soft Deletion**: Records are never hard-deleted. Any tables with records subject to deletion in the platform have a `deleted` property that provides a soft indication of whether or not the record has been deleted. A value of `1` (`true`) indicates that the record has been deleted.
* **Data Extensions**: All tables ending in `_data_extensions` reflect configuration-defined fields and their values, persisted as key-value pairs of `field_name` / `field_value`.
* **Possible Values**: The list of possible values enumerated for system properties listed reflects the latest set of values as defined by the platform; as such, it may not reflect all possible values that existed historically. Columns marked with `defined in configuration` indicate that the list of possible values may be dependent on the tenant configuration, which is also subject to change over redeployments.

Attribute Labels [#attribute-labels]

The following labels are provided in the **Attributes** column for applicable table columns in the reference:

* `PK`: Column is part of the table's primary key.
* `Index`: Column is indexed.
* `Relationship`: Column has a known connection to another table, documented in the **Relationships** section below each table; relationships are not enforced as database foreign keys. Cardinality is provided for each relationship — `many-to-one`/`one-to-one` means a safe single-row lookup, `one-to-many`/`many-to-many` means the join can return multiple rows. Some relationship columns depend on a companion `Discriminator` column to know which table they resolve to.
* `Discriminator`: Column determines how another column's `Relationship` value should be interpreted.

Policy Tables [#policy-tables]

* [accounts](#accounts)
* [account\_data\_extensions](#account_data_extensions)
* [quotes](#quotes)
* [quote\_elements](#quote_elements)
* [quote\_element\_tree](#quote_element_tree)
* [quote\_element\_charges](#quote_element_charges)
* [quote\_coverage\_terms](#quote_coverage_terms)
* [quote\_element\_underwriting\_flags](#quote_element_underwriting_flags)
* [quote\_data\_extensions](#quote_data_extensions)
* [quote\_preferences](#quote_preferences)
* [policies](#policies)
* [terms](#terms)
* [transactions](#transactions)
* [affected\_transactions](#affected_transactions)
* [segments](#segments)
* [policy\_segment\_elements](#policy_segment_elements)
* [policy\_element\_tree](#policy_element_tree)
* [policy\_element\_charges](#policy_element_charges)
* [policy\_coverage\_terms](#policy_coverage_terms)
* [policy\_element\_underwriting\_flags](#policy_element_underwriting_flags)
* [policy\_data\_extensions](#policy_data_extensions)
* [policy\_auto\_renewals](#policy_auto_renewals)
* [policy\_transaction\_change\_instructions](#policy_transaction_change_instructions)
* [policy\_preferences](#policy_preferences)
* [policy\_status](#policy_status)

<span id="accounts" />

accounts [#accounts]

**API Reference:** [Accounts API](/api/accounts)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                     | Type           | Nullable | Attributes | Description                                                                                                     | Possible Values                   |
| ------------------------------- | -------------- | -------- | ---------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `tenant_locator`                | `char(36)`     | **no**   | `PK`       | Unique identifier of the tenant (UUID)                                                                          |                                   |
| `locator`                       | `char(26)`     | **no**   | `PK`       | Unique identifier of the account (ULID)                                                                         |                                   |
| `account_state`                 | `varchar(32)`  | **no**   |            | Current [state of the account ](/features/accounts#account-states)                                              | `draft`, `validated`, `discarded` |
| `billing_level`                 | `varchar(50)`  | **no**   |            | Level at which billing within the account takes place. Value may be `policy` or `account`                       | `account`, `inherit`, `policy`    |
| `type`                          | `varchar(128)` | **no**   |            | The [account type ](/features/accounts#accounts) per the tenant configuration                                   | *defined in configuration*        |
| `region`                        | `varchar(128)` | yes      |            | The region assigned to the account (if any)                                                                     |                                   |
| `auto_renewal_plan_name`        | `varchar(128)` | yes      |            | Name of the account's [auto-renewal plan ](/features/policy-management/renewal-management#autorenewal) (if any) | *defined in configuration*        |
| `delinquency_plan_name`         | `varchar(128)` | yes      |            | Name of the account's [delinquency plan ](/features/billing/delinquency#configuration) (if any)                 | *defined in configuration*        |
| `excess_credit_plan_name`       | `varchar(128)` | yes      |            | Name of the account's [excess credit plan ](/features/billing/excess-credits#configuration) (if any)            | *defined in configuration*        |
| `shortfall_tolerance_plan_name` | `varchar(128)` | yes      |            | Name of the account's shortfall tolerance plan (if any)                                                         | *defined in configuration*        |
| `account_number`                | `varchar(128)` | yes      |            | The [custom number](/configuration/general-topics/entity-numbering) assigned to the account (if any)            |                                   |
| `datalake_created_timestamp`    | `datetime(6)`  | **no**   |            | Time in UTC the record was created                                                                              |                                   |
| `datalake_updated_timestamp`    | `datetime(6)`  | **no**   | `Index`    | Time in UTC the record was last updated                                                                         |                                   |

***

<span id="account_data_extensions" />

account_data_extensions [#account_data_extensions]

**API Reference:** [Accounts API](/api/accounts)

**Primary Key:** `tenant_locator`, `account_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                        | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------- | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                             |                            |
| `account_locator`            | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the [account the data ](/features/accounts#extension-data) is associated with (UULD) |                            |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                                   |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the extension data field                                                           | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                                             | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                                      |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                 |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                            |                            |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="quotes" />

quotes [#quotes]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type             | Nullable | Attributes     | Description                                                                                                   | Possible Values                                                                                                                                                  |
| ---------------------------- | ---------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`       | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                        |                                                                                                                                                                  |
| `locator`                    | `char(26)`       | **no**   | `PK`           | Unique identifier of the [quote ](/features/policy-quotation/quotes) (UULD)                                   |                                                                                                                                                                  |
| `account_locator`            | `char(26)`       | **no**   | `Relationship` | Unique identifier of the quote's parent account (UULD)                                                        |                                                                                                                                                                  |
| `group_locator`              | `char(26)`       | yes      |                | Unique identifier of the group the quote belongs to, if any (UULD)                                            |                                                                                                                                                                  |
| `product_name`               | `varchar(128)`   | **no**   |                | The name of the configured <ApiLink name="ProductRef">product</ApiLink> the quote is based on                 |                                                                                                                                                                  |
| `quote_state`                | `varchar(50)`    | **no**   |                | The [state ](/features/policy-quotation/quotes#quotes) in which the quote currently resides                   | `draft`, `validated`, `earlyUnderwritten`, `priced`, `underwritten`, `accepted`, `issued`, `underwrittenBlocked`, `declined`, `rejected`, `refused`, `discarded` |
| `billing_level`              | `varchar(50)`    | **no**   |                | Level at which billing within the account takes place `policy` or `account`                                   | `account`, `inherit`, `policy`                                                                                                                                   |
| `policy_locator`             | `char(26)`       | yes      | `Relationship` | The identifier of the resultant policy (if quote has been issued)                                             |                                                                                                                                                                  |
| `quick_quote_locator`        | `char(26)`       | yes      |                | The identifier of the originating [quick quote ](/features/policy-quotation/quick-quotes) (if any)            |                                                                                                                                                                  |
| `region`                     | `varchar(128)`   | yes      |                | The region assigned to the <ApiLink name="QuoteCreateRequest">quote</ApiLink> (if any)                        |                                                                                                                                                                  |
| `jurisdiction`               | `varchar(128)`   | yes      |                | The jurisdiction assigned to the <ApiLink name="QuoteCreateRequest">quote</ApiLink> (if any)                  |                                                                                                                                                                  |
| `producer_code`              | `varchar(128)`   | yes      |                | The producer code assigned to the <ApiLink name="QuoteCreateRequest">quote</ApiLink> (if any)                 |                                                                                                                                                                  |
| `auto_renewal_plan_name`     | `varchar(128)`   | yes      |                | Name of the quote's [auto-renewal plan ](/features/policy-management/renewal-management#autorenewal) (if any) | *defined in configuration*                                                                                                                                       |
| `delinquency_plan_name`      | `varchar(128)`   | yes      |                | Name of the quote's [delinquency plan ](/features/billing/delinquency#configuration) (if any)                 | *defined in configuration*                                                                                                                                       |
| `issued_time_utc`            | `datetime(6)`    | yes      |                | Timestamp the quote was issued                                                                                |                                                                                                                                                                  |
| `start_time_utc`             | `datetime(6)`    | yes      |                | Timestamp quote is effective as of                                                                            |                                                                                                                                                                  |
| `end_time_utc`               | `datetime(6)`    | yes      |                | Timestamp quote coverage ends                                                                                 |                                                                                                                                                                  |
| `accepted_time_utc`          | `datetime(6)`    | yes      |                | Timestamp the quote was moved to the accepted state                                                           |                                                                                                                                                                  |
| `created_at_utc`             | `datetime(6)`    | **no**   |                | Timestamp the quote was created                                                                               |                                                                                                                                                                  |
| `created_by`                 | `char(36)`       | **no**   |                | The identifier of the user that created the quote                                                             |                                                                                                                                                                  |
| `currency`                   | `varchar(128)`   | yes      |                | Currency the quote was written in                                                                             |                                                                                                                                                                  |
| `duration`                   | `decimal(19,15)` | yes      |                | The number of units of [duration\_basis ](/features/financials/durations) the quote spans                     |                                                                                                                                                                  |
| `duration_basis`             | `varchar(32)`    | yes      |                | The units of time that the [duration ](/features/financials/durations) of the quote is expressed in           | `years`, `months`, `weeks`, `days`, `hours`                                                                                                                      |
| `timezone`                   | `varchar(128)`   | yes      |                | The timezone the quote was written in                                                                         |                                                                                                                                                                  |
| `expiration_time_utc`        | `datetime(6)`    | yes      |                | The timestamp after which the quote can no longer be accepted or issued                                       |                                                                                                                                                                  |
| `underwriting_status`        | `varchar(50)`    | yes      |                | The outcome of the [underwriting process ](/features/underwriting) (if completed)                             |                                                                                                                                                                  |
| `quote_number`               | `varchar(128)`   | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the quote (if any)            |                                                                                                                                                                  |
| `invoice_fee_amount`         | `decimal(19,3)`  | yes      |                | Amount of the quote's invoice fee (if any)                                                                    |                                                                                                                                                                  |
| `anonymized_time_utc`        | `datetime(6)`    | yes      |                | Time in UTC the quote was anonymized                                                                          |                                                                                                                                                                  |
| `datalake_created_timestamp` | `datetime(6)`    | **no**   |                | Time in UTC the record was created                                                                            |                                                                                                                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`    | **no**   | `Index`        | Time in UTC the record was last updated                                                                       |                                                                                                                                                                  |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `policy_locator` → `policies.locator` (`many-to-one`)

***

<span id="quote_elements" />

quote_elements [#quote_elements]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type           | Nullable | Attributes     | Description                                                                                                              | Possible Values                                                  |
| ---------------------------- | -------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                                   |                                                                  |
| `locator`                    | `char(26)`     | **no**   | `PK`           | Unique identifier of the quote [element ](/getting-started/create-a-tenant-configuration-file#what-is-an-element) (ULID) |                                                                  |
| `quote_locator`              | `char(26)`     | **no**   | `Relationship` | Identifier of the quote the element is associated with (ULID)                                                            |                                                                  |
| `parent_locator`             | `char(26)`     | yes      | `Relationship` | Identifier of the parent element immediately above in the quotes data hierarchy                                          |                                                                  |
| `category`                   | `varchar(128)` | yes      |                | The [category](/features/policy-management/policy-elements#categories-and-types) the element type is based on            | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `type`                       | `varchar(128)` | **no**   |                | The [configured type](/features/policy-management/policy-elements#categories-and-types) the element is based on          | *defined in configuration*                                       |
| `deleted`                    | `tinyint(1)`   | yes      |                | Indicates whether the record has been deleted                                                                            |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                                                       |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                                                                  |                                                                  |

**Relationships:**

* `quote_locator` → `quotes.locator` (`many-to-one`)
* `parent_locator` → `quote_elements.locator` (`many-to-one`)

***

<span id="quote_element_tree" />

quote_element_tree [#quote_element_tree]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `quote_locator`, `parent_locator`, `child_locator`

| Column Name                  | Type          | Nullable | Attributes           | Description                                                                      | Possible Values |
| ---------------------------- | ------------- | -------- | -------------------- | -------------------------------------------------------------------------------- | --------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                           |                 |
| `quote_locator`              | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of the quote the element is associated with (ULID)                    |                 |
| `parent_locator`             | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of the element immediately above in the quote's data hierarchy (ULID) |                 |
| `child_locator`              | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of an element immediately below in the quote's data hierarchy (ULID)  |                 |
| `depth`                      | `int(11)`     | **no**   |                      | The number of levels of child elements below in the quote's data hierarchy       |                 |
| `deleted`                    | `tinyint(1)`  | yes      |                      | Indicates whether the record has been deleted                                    |                 |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                      | Time in UTC the record was created                                               |                 |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`              | Time in UTC the record was last updated                                          |                 |

**Relationships:**

* `quote_locator` → `quotes.locator` (`many-to-one`)
* `parent_locator` → `quote_elements.locator` (`many-to-one`)
* `child_locator` → `quote_elements.locator` (`many-to-one`)

***

<span id="quote_element_charges" />

quote_element_charges [#quote_element_charges]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type             | Nullable | Attributes              | Description                                                                                                                                             | Possible Values                                                                                      |
| ---------------------------- | ---------------- | -------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`       | **no**   | `PK`                    | Unique identifier of the tenant (UUID)                                                                                                                  |                                                                                                      |
| `locator`                    | `char(26)`       | **no**   | `PK`                    | Unique identifier of the quote charge (ULID)                                                                                                            |                                                                                                      |
| `account_locator`            | `char(26)`       | **no**   | `Relationship`          | Identifier of the account the charge is associated with (ULID)                                                                                          |                                                                                                      |
| `quote_locator`              | `char(26)`       | **no**   | `Index`, `Relationship` | Identifier of the quote the charge is associated with (ULID)                                                                                            |                                                                                                      |
| `product_name`               | `varchar(128)`   | **no**   |                         | The name of the configured product the quote is based on                                                                                                |                                                                                                      |
| `element_locator`            | `char(26)`       | **no**   | `Index`, `Relationship` | Identifier of the element the charge is directly associated with (ULID)                                                                                 |                                                                                                      |
| `element_category`           | `varchar(128)`   | yes      |                         | The [category](/features/policy-management/policy-elements#categories-and-types) the element type is based on                                           | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine`                                     |
| `element_type`               | `varchar(128)`   | **no**   |                         | The [configured type](/features/policy-management/policy-elements#categories-and-types) the element is based on                                         | *defined in configuration*                                                                           |
| `start_time_utc`             | `datetime(6)`    | **no**   |                         | Start of the period covered by the charge                                                                                                               |                                                                                                      |
| `end_time_utc`               | `datetime(6)`    | **no**   |                         | End of the period covered by the charge                                                                                                                 |                                                                                                      |
| `duration`                   | `decimal(19,15)` | yes      |                         | The number of units of `duration_basis` the charge spans                                                                                                |                                                                                                      |
| `duration_basis`             | `varchar(32)`    | yes      |                         | The units of time that the `duration` of the quote is expressed in                                                                                      | `years`, `months`, `weeks`, `days`, `hours`                                                          |
| `charge_category`            | `varchar(128)`   | **no**   |                         | The category the charge type is based on                                                                                                                | `none`, `premium`, `tax`, `fee`, `credit`, `invoiceFee`, `cededPremium`, `nonFinancial`, `surcharge` |
| `charge_type`                | `varchar(128)`   | **no**   |                         | The configured type the charge is based on                                                                                                              | *defined in configuration*                                                                           |
| `amount`                     | `decimal(19,3)`  | **no**   |                         | The [amount ](/features/financials/charges#charges) of the charge                                                                                       |                                                                                                      |
| `rate`                       | `decimal(19,10)` | **no**   |                         | [Rate ](/features/financials/charges#charges) describes the amount per unit time (rate \* duration = amount)                                            |                                                                                                      |
| `reference_rate`             | `decimal(19,10)` | **no**   |                         | The [reference rate ](/features/financials/charges#charges) for the charge returned in the rater (if any)                                               |                                                                                                      |
| `invoicing`                  | `varchar(128)`   | **no**   |                         | Indicates how the system invoices the charge according to its `charge_type`, with possible values listed as `invoicing` in <ApiLink name="ChargeRef" /> | `scheduled`, `next`, `immediate`                                                                     |
| `handling`                   | `varchar(128)`   | **no**   |                         | Indicates how the system handles the charge according to its `charge_type`, with possible values listed as `handling` in <ApiLink name="ChargeRef" />   | `flat`, `normal`, `retention`                                                                        |
| `tag`                        | `varchar(128)`   | yes      |                         | The [tag ](/features/financials/charges#charges) for the charge returned in the rater (if any)                                                          |                                                                                                      |
| `deleted`                    | `tinyint(1)`     | yes      |                         | Indicates whether the record has been deleted                                                                                                           |                                                                                                      |
| `datalake_created_timestamp` | `datetime(6)`    | **no**   |                         | Time in UTC the record was created                                                                                                                      |                                                                                                      |
| `datalake_updated_timestamp` | `datetime(6)`    | **no**   | `Index`                 | Time in UTC the record was last updated                                                                                                                 |                                                                                                      |
| `created_at_utc`             | `datetime(6)`    | yes      |                         | UTC timestamp when this record was created in Socotra.                                                                                                  |                                                                                                      |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `quote_locator` → `quotes.locator` (`many-to-one`)
* `element_locator` → `quote_elements.locator` (`many-to-one`)

***

<span id="quote_coverage_terms" />

quote_coverage_terms [#quote_coverage_terms]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `element_locator`, `name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                                                | Possible Values                                                  |
| ---------------------------- | --------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                                     |                                                                  |
| `quote_locator`              | `char(26)`      | **no**   | `Relationship`       | Identifier of the quote the coverage term is associated with (ULID)                                                        |                                                                  |
| `element_locator`            | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the element the coverage term is associated with (ULID)                                                      |                                                                  |
| `element_category`           | `varchar(128)`  | yes      |                      | The [category](/features/policy-management/policy-elements#categories-and-types) the associated element type is based on   | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `element_type`               | `varchar(128)`  | **no**   |                      | The [configured type](/features/policy-management/policy-elements#categories-and-types) the associated element is based on | *defined in configuration*                                       |
| `name_md5`                   | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `name`                                                                                                 |                                                                  |
| `name`                       | `varchar(1024)` | **no**   |                      | The configured name of the coverage term                                                                                   | *defined in configuration*                                       |
| `option`                     | `varchar(1024)` | **no**   |                      | The selected option or value of the coverage term                                                                          | *defined in configuration*                                       |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                                                              |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                                         |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                                    |                                                                  |

**Relationships:**

* `quote_locator` → `quotes.locator` (`many-to-one`)
* `element_locator` → `quote_elements.locator` (`many-to-one`)

***

<span id="quote_element_underwriting_flags" />

quote_element_underwriting_flags [#quote_element_underwriting_flags]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes              | Description                                                                                                                                                                       | Possible Values                                                  |
| ---------------------------- | --------------- | -------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                    | Unique identifier of the tenant (UUID)                                                                                                                                            |                                                                  |
| `locator`                    | `char(26)`      | **no**   | `PK`                    | Unique identifier of the [underwriting flag ](/features/underwriting#what-is-an-underwriting-flag) for the quote element (ULID)                                                   |                                                                  |
| `quote_locator`              | `char(26)`      | **no**   | `Index`, `Relationship` | Identifier of the quote the underwriting flag is associated with (ULID)                                                                                                           |                                                                  |
| `element_locator`            | `char(26)`      | yes      | `Index`, `Relationship` | Identifier of the quote element the underwriting flag is associated with (ULID)                                                                                                   |                                                                  |
| `element_category`           | `varchar(128)`  | yes      |                         | The [category](/features/policy-management/policy-elements#categories-and-types) the associated element type is based on                                                          | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `element_type`               | `varchar(128)`  | yes      |                         | The [configured type](/features/policy-management/policy-elements#categories-and-types) the associated element is based on                                                        | *defined in configuration*                                       |
| `level`                      | `varchar(128)`  | **no**   |                         | The [level ](/features/underwriting#what-is-an-underwriting-flag) of the underwriting flag, with possible values listed as `level` in <ApiLink name="UnderwritingFlagResponse" /> | `info`, `block`, `decline`, `reject`, `approve`                  |
| `task_locator`               | `char(26)`      | yes      | `Relationship`          | Identifier of the task associated with the underwriting flag (ULID)                                                                                                               |                                                                  |
| `note`                       | `varchar(1024)` | yes      |                         | The custom note associated with the underwriting flag                                                                                                                             |                                                                  |
| `created_by`                 | `char(36)`      | yes      |                         | Identifier of the user that created the underwriting flag (UUID)                                                                                                                  |                                                                  |
| `created_time_utc`           | `datetime(6)`   | **no**   |                         | Time in UTC the underwriting flag was created                                                                                                                                     |                                                                  |
| `cleared_by`                 | `char(36)`      | yes      |                         | Identifier of the user that cleared the underwriting flag (UUID)                                                                                                                  |                                                                  |
| `cleared_time_utc`           | `datetime(6)`   | yes      |                         | Time in UTC the underwriting flag was cleared                                                                                                                                     |                                                                  |
| `deleted`                    | `tinyint(1)`    | yes      |                         | Indicates whether the record has been deleted                                                                                                                                     |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                         | Time in UTC the record was created                                                                                                                                                |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`                 | Time in UTC the record was last updated                                                                                                                                           |                                                                  |

**Relationships:**

* `quote_locator` → `quotes.locator` (`many-to-one`)
* `element_locator` → `quote_elements.locator` (`many-to-one`)
* `task_locator` → `tasks.locator` (`many-to-one`)

***

<span id="quote_data_extensions" />

quote_data_extensions [#quote_data_extensions]

**API Reference:** [Quotes API](/api/quotes/quotes)

**Primary Key:** `tenant_locator`, `element_locator`, `is_static`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                                     | Possible Values                                                  |
| ---------------------------- | --------------- | -------- | -------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                          |                                                                  |
| `quote_locator`              | `char(26)`      | **no**   | `Relationship`       | Identifier of the quote the element data is associated with (ULID)                                              |                                                                  |
| `element_locator`            | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the element the data is associated with (ULID)                                                    |                                                                  |
| `element_category`           | `varchar(128)`  | yes      |                      | The [category](/features/policy-management/policy-elements#categories-and-types) the element type is based on   | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `element_type`               | `varchar(128)`  | **no**   |                      | The [configured type](/features/policy-management/policy-elements#categories-and-types) the element is based on | *defined in configuration*                                       |
| `is_static`                  | `tinyint(4)`    | **no**   | `PK`                 | Whether the data is static or not                                                                               |                                                                  |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                                                |                                                                  |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the [extension data ](/configuration/data-extensions/overview) field                            | *defined in configuration*                                       |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                                                          | *defined in configuration*                                       |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                                                   |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                              |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                         |                                                                  |

**Relationships:**

* `quote_locator` → `quotes.locator` (`many-to-one`)
* `element_locator` → `quote_elements.locator` (`many-to-one`)

***

<span id="quote_preferences" />

quote_preferences [#quote_preferences]

**Primary Key:** `tenant_locator`, `quote_locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                        | Possible Values                                                                                                               |
| ---------------------------- | --------------- | -------- | -------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   |                | Unique identifier of the tenant (UUID)                             |                                                                                                                               |
| `quote_locator`              | `char(26)`      | **no**   | `Relationship` | Identifier of the quote the preferences are associated with (ULID) |                                                                                                                               |
| `installment_plan_name`      | `varchar(128)`  | yes      |                | Name of the installment plan assigned to the quote, if any         | *defined in configuration*                                                                                                    |
| `installment_weights`        | `varchar(1024)` | yes      |                | Custom weights for installment amounts, if specified               |                                                                                                                               |
| `anchor_mode`                | `varchar(128)`  | yes      |                | Mode for anchoring installment generation timing                   | `generateDay`, `termStartDay`, `dueDay`                                                                                       |
| `anchor_time_utc`            | `datetime(6)`   | yes      |                | Time in UTC to anchor installment generation, if applicable        |                                                                                                                               |
| `anchor_type`                | `varchar(128)`  | yes      |                | Type of anchor for installment generation timing                   | `none`, `dayOfMonth`, `anchorTime`, `dayOfWeek`, `weekOfMonth`                                                                |
| `cadence`                    | `varchar(128)`  | yes      |                | Frequency of installment generation (e.g., `monthly`, `quarterly`) | `none`, `fullPay`, `weekly`, `everyOtherWeek`, `monthly`, `quarterly`, `semiannually`, `annually`, `thirtyDays`, `everyNDays` |
| `day_of_month`               | `varchar(128)`  | yes      |                | Day of the month for installment generation, if applicable         |                                                                                                                               |
| `day_of_week`                | `varchar(128)`  | yes      |                | Day of the week for installment generation, if applicable          | `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday`, `sunday`                                                  |
| `due_lead_days`              | `varchar(128)`  | yes      |                | Number of days before due date that invoices are generated         |                                                                                                                               |
| `generate_lead_days`         | `varchar(128)`  | yes      |                | Number of days in advance to generate installments                 |                                                                                                                               |
| `max_installments_per_term`  | `int(11)`       | yes      |                | Maximum number of installments allowed per term, if specified      |                                                                                                                               |
| `week_of_month`              | `varchar(128)`  | yes      |                | Week of the month for installment generation, if applicable        | `none`, `first`, `second`, `third`, `fourth`, `fifth`                                                                         |
| `autopay_lead_days`          | `varchar(128)`  | yes      |                | Number of days in advance of the due date to autopay invoice       |                                                                                                                               |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                 |                                                                                                                               |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was last updated                            |                                                                                                                               |

**Relationships:**

* `quote_locator` → `quotes.locator` (`one-to-one`)

***

<span id="policies" />

policies [#policies]

**API Reference:** [Policies API](/api/policy-management/policies)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                                                                    | Possible Values                             |
| ---------------------------- | --------------- | -------- | -------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                         |                                             |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the policy (ULID)                                                                         |                                             |
| `account_locator`            | `char(26)`      | **no**   | `Relationship` | Identifier of the account the policy is associated with (ULID)                                                 |                                             |
| `issued_transaction_locator` | `char(26)`      | **no**   | `Relationship` | Identifier of the transaction that issued the policy (ULID)                                                    |                                             |
| `latest_term_locator`        | `char(26)`      | **no**   | `Relationship` | Identifier of the latest term for the policy (ULID)                                                            |                                             |
| `latest_segment_locator`     | `char(26)`      | yes      | `Relationship` | Identifier of the latest segment for the policy (ULID)                                                         |                                             |
| `product_name`               | `varchar(128)`  | **no**   |                | Name of the product associated with the policy                                                                 |                                             |
| `start_time_utc`             | `datetime(6)`   | **no**   |                | Time in UTC the policy goes into effect                                                                        |                                             |
| `end_time_utc`               | `datetime(6)`   | **no**   |                | Time in UTC the policy is no longer effective                                                                  |                                             |
| `coverage_end_time_utc`      | `datetime(6)`   | yes      |                | Time in UTC the policy coverage ends                                                                           |                                             |
| `currency`                   | `varchar(128)`  | yes      |                | Currency the policy was written in                                                                             |                                             |
| `duration_basis`             | `varchar(32)`   | yes      |                | The units of time that the [duration ](/features/financials/durations) of the policy is expressed in           | `years`, `months`, `weeks`, `days`, `hours` |
| `timezone`                   | `varchar(128)`  | yes      |                | The timezone the policy was written in                                                                         |                                             |
| `billing_level`              | `varchar(50)`   | **no**   |                | Level at which billing for the policy takes place. Value may be `policy` or `account`                          | `account`, `inherit`, `policy`              |
| `created_time_utc`           | `datetime(6)`   | **no**   |                | Time in UTC the policy was created                                                                             |                                             |
| `created_by`                 | `char(36)`      | **no**   |                | Identifier of the user that created the policy (UUID)                                                          |                                             |
| `region`                     | `varchar(128)`  | yes      |                | The region assigned to the policy (if any)                                                                     |                                             |
| `jurisdiction`               | `varchar(128)`  | yes      |                | The jurisdiction assigned to the policy (if any)                                                               |                                             |
| `auto_renewal_plan_name`     | `varchar(128)`  | yes      |                | Name of the policy's [auto-renewal plan ](/features/policy-management/renewal-management#autorenewal) (if any) | *defined in configuration*                  |
| `delinquency_plan_name`      | `varchar(128)`  | yes      |                | Name of the policy's [delinquency plan ](/features/billing/delinquency#configuration) (if any)                 | *defined in configuration*                  |
| `invoice_fee_amount`         | `decimal(19,3)` | yes      |                | Amount of the policy's invoice fee (if any)                                                                    |                                             |
| `policy_number`              | `varchar(128)`  | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the policy (if any)            |                                             |
| `anonymized_time_utc`        | `datetime(6)`   | yes      |                | Time in UTC the policy was anonymized                                                                          |                                             |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                                                             |                                             |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                                                        |                                             |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `issued_transaction_locator` → `transactions.locator` (`many-to-one`)
* `latest_term_locator` → `terms.locator` (`many-to-one`)
* `latest_segment_locator` → `segments.locator` (`many-to-one`)

***

<span id="terms" />

terms [#terms]

**API Reference:** [Policy Terms API](/api/policy-management/policy-terms)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                       | Type           | Nullable | Attributes     | Description                                                                                      | Possible Values |
| --------------------------------- | -------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------ | --------------- |
| `tenant_locator`                  | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                           |                 |
| `locator`                         | `char(26)`     | **no**   | `PK`           | Unique identifier of the term (UUID)                                                             |                 |
| `static_locator`                  | `char(26)`     | **no**   |                | Static identifier of the term that persists across changes (ULID)                                |                 |
| `policy_locator`                  | `char(26)`     | **no**   | `Relationship` | Identifier of the policy the term is associated with (ULID)                                      |                 |
| `originating_transaction_locator` | `char(26)`     | **no**   | `Relationship` | Identifier of the transaction the term is associated with (ULID)                                 |                 |
| `start_time_utc`                  | `datetime(6)`  | **no**   |                | Time in UTC the term is effective                                                                |                 |
| `end_time_utc`                    | `datetime(6)`  | **no**   |                | Time in UTC the term is no longer effective                                                      |                 |
| `number`                          | `int(11)`      | **no**   |                | Sequential number of the term within the policy                                                  |                 |
| `auto_renewal_locator`            | `char(26)`     | yes      | `Relationship` | Identifier of the auto-renewal associated with the term (ULID), if any                           |                 |
| `previous_term_locator`           | `char(26)`     | yes      | `Relationship` | Identifier of the term that preceded this term (ULID), if any                                    |                 |
| `supersedes_term_locator`         | `char(26)`     | yes      | `Relationship` | Identifier of the term that this term supersedes (ULID), if any                                  |                 |
| `term_number`                     | `varchar(128)` | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the term, if any |                 |
| `deleted`                         | `tinyint(1)`   | yes      |                | Indicates whether the record has been deleted                                                    |                 |
| `datalake_created_timestamp`      | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                               |                 |
| `datalake_updated_timestamp`      | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                                          |                 |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `originating_transaction_locator` → `transactions.locator` (`many-to-one`)
* `auto_renewal_locator` → `policy_auto_renewals.locator` (`many-to-one`)
* `previous_term_locator` → `terms.locator` (`many-to-one`)
* `supersedes_term_locator` → `terms.locator` (`many-to-one`)

***

<span id="transactions" />

transactions [#transactions]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                     | Type           | Nullable | Attributes     | Description                                                                         | Possible Values                                                                                                                                                                                            |
| ------------------------------- | -------------- | -------- | -------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`                | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                              |                                                                                                                                                                                                            |
| `locator`                       | `char(26)`     | **no**   | `PK`           | Unique identifier of the transaction (ULID)                                         |                                                                                                                                                                                                            |
| `policy_locator`                | `char(26)`     | **no**   | `Relationship` | Identifier of the policy the transaction is associated with (ULID)                  |                                                                                                                                                                                                            |
| `term_locator`                  | `char(26)`     | **no**   | `Relationship` | Identifier of the term the transaction is associated with (ULID)                    |                                                                                                                                                                                                            |
| `effective_time_utc`            | `datetime(6)`  | **no**   |                | Time in UTC the transaction becomes effective                                       |                                                                                                                                                                                                            |
| `transaction_state`             | `varchar(50)`  | **no**   |                | Current state of the transaction                                                    | `draft`, `initialized`, `validated`, `earlyUnderwritten`, `priced`, `underwritten`, `accepted`, `issued`, `underwrittenBlocked`, `declined`, `rejected`, `refused`, `discarded`, `invalidated`, `reversed` |
| `category`                      | `varchar(50)`  | **no**   |                | Category of the transaction                                                         | `issuance`, `change`, `renewal`, `cancellation`, `reinstatement`, `reversal`, `aggregate`                                                                                                                  |
| `type`                          | `varchar(128)` | **no**   |                | The configured type of the transaction                                              | *defined in configuration*                                                                                                                                                                                 |
| `created_by`                    | `char(36)`     | **no**   |                | Identifier of the user that created the transaction (UUID)                          |                                                                                                                                                                                                            |
| `created_time_utc`              | `datetime(6)`  | **no**   |                | Time in UTC the transaction was created                                             |                                                                                                                                                                                                            |
| `aggregate_transaction_locator` | `char(26)`     | yes      | `Relationship` | Identifier of the aggregate transaction this transaction is part of (ULID), if any  |                                                                                                                                                                                                            |
| `base_transaction_locator`      | `char(26)`     | yes      | `Relationship` | Identifier of the transaction this transaction is derived from (ULID), if any       |                                                                                                                                                                                                            |
| `reapplication_of_locator`      | `char(26)`     | yes      | `Relationship` | Identifier of the transaction this transaction is a reapplication of (ULID), if any |                                                                                                                                                                                                            |
| `static_locator`                | `char(26)`     | yes      |                | Static identifier of the transaction that persists across changes (ULID)            |                                                                                                                                                                                                            |
| `issued_time_utc`               | `datetime(6)`  | yes      |                | Time in UTC the transaction was issued                                              |                                                                                                                                                                                                            |
| `accepted_time_utc`             | `datetime(6)`  | yes      |                | Time in UTC the transaction was accepted                                            |                                                                                                                                                                                                            |
| `underwriting_status`           | `varchar(50)`  | yes      |                | The outcome of the underwriting process (if completed)                              |                                                                                                                                                                                                            |
| `datalake_created_timestamp`    | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                  |                                                                                                                                                                                                            |
| `datalake_updated_timestamp`    | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                             |                                                                                                                                                                                                            |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `term_locator` → `terms.locator` (`many-to-one`)
* `aggregate_transaction_locator` → `transactions.locator` (`many-to-one`)
* `base_transaction_locator` → `transactions.locator` (`many-to-one`)
* `reapplication_of_locator` → `transactions.locator` (`many-to-one`)

***

<span id="affected_transactions" />

affected_transactions [#affected_transactions]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `transaction_locator`, `affected_transaction_locator`

| Column Name                    | Type          | Nullable | Attributes           | Description                                                                                                       | Possible Values           |
| ------------------------------ | ------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `tenant_locator`               | `char(36)`    | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                            |                           |
| `transaction_locator`          | `char(26)`    | **no**   | `PK`, `Relationship` | Unique identifier of the affecting transaction (ULID)                                                             |                           |
| `affected_transaction_locator` | `char(26)`    | **no**   | `PK`, `Relationship` | Unique identifier of the affected transaction (ULID)                                                              |                           |
| `action`                       | `varchar(50)` | **no**   |                      | Action taken by the affecting transaction onto the affected transaction. Value may be `reversed` or `invalidated` | `reversed`, `invalidated` |
| `datalake_created_timestamp`   | `datetime(6)` | **no**   |                      | Time in UTC the record was created                                                                                |                           |
| `datalake_updated_timestamp`   | `datetime(6)` | **no**   | `Index`              | Time in UTC the record was last updated                                                                           |                           |

**Relationships:**

* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `affected_transaction_locator` → `transactions.locator` (`many-to-one`)

***

<span id="segments" />

segments [#segments]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type             | Nullable | Attributes     | Description                                                        | Possible Values                             |
| ---------------------------- | ---------------- | -------- | -------------- | ------------------------------------------------------------------ | ------------------------------------------- |
| `tenant_locator`             | `char(36)`       | **no**   | `PK`           | Unique identifier of the tenant (UUID)                             |                                             |
| `locator`                    | `char(26)`       | **no**   | `PK`           | Unique identifier of the segment (ULID)                            |                                             |
| `policy_locator`             | `char(26)`       | **no**   | `Relationship` | Identifier of the policy the segment is associated with (ULID)     |                                             |
| `transaction_locator`        | `char(26)`       | **no**   | `Relationship` | Identifier of the transaction that created the segment (ULID)      |                                             |
| `term_locator`               | `char(26)`       | **no**   | `Relationship` | Identifier of the term the segment is associated with (ULID)       |                                             |
| `start_time_utc`             | `datetime(6)`    | **no**   |                | Time in UTC the segment begins                                     |                                             |
| `end_time_utc`               | `datetime(6)`    | **no**   |                | Time in UTC the segment ends                                       |                                             |
| `duration`                   | `decimal(19,15)` | **no**   |                | The number of units of `duration_basis` the segment spans          |                                             |
| `duration_basis`             | `varchar(32)`    | yes      |                | The units of time that the duration of the segment is expressed in | `years`, `months`, `weeks`, `days`, `hours` |
| `type`                       | `varchar(50)`    | **no**   |                | The type of segment                                                | `coverage`, `gap`                           |
| `based_on`                   | `char(26)`       | yes      | `Relationship` | Identifier of the segment this segment is based on (ULID), if any  |                                             |
| `producer_code`              | `varchar(128)`   | yes      |                | The producer code assigned to the segment (if any)                 |                                             |
| `producer_code_of_record`    | `varchar(128)`   | yes      |                | The producer code of record assigned to the segment (if any)       |                                             |
| `anonymized_time_utc`        | `datetime(6)`    | yes      |                | Time in UTC the segment was anonymized                             |                                             |
| `deleted`                    | `tinyint(1)`     | yes      |                | Indicates whether the record has been deleted                      |                                             |
| `datalake_created_timestamp` | `datetime(6)`    | **no**   |                | Time in UTC the record was created                                 |                                             |
| `datalake_updated_timestamp` | `datetime(6)`    | **no**   | `Index`        | Time in UTC the record was last updated                            |                                             |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `term_locator` → `terms.locator` (`many-to-one`)
* `based_on` → `segments.locator` (`many-to-one`)

***

<span id="policy_segment_elements" />

policy_segment_elements [#policy_segment_elements]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                   | Type           | Nullable | Attributes     | Description                                                                                                           | Possible Values                                                  |
| ----------------------------- | -------------- | -------- | -------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`              | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                                |                                                                  |
| `locator`                     | `char(26)`     | **no**   | `PK`           | Unique identifier of the segment element (UUID)                                                                       |                                                                  |
| `policy_locator`              | `char(26)`     | **no**   | `Relationship` | Identifier of the policy the segment element is associated with (ULID)                                                |                                                                  |
| `transaction_locator`         | `char(26)`     | **no**   | `Relationship` | Identifier of the transaction the segment element is associated with (ULID)                                           |                                                                  |
| `segment_locator`             | `char(26)`     | **no**   | `Relationship` | Identifier of the segment the element is associated with (ULID)                                                       |                                                                  |
| `parent_locator`              | `char(26)`     | yes      | `Relationship` | Identifier of the parent element immediately above in the policy data hierarchy (ULID)                                |                                                                  |
| `static_locator`              | `char(26)`     | **no**   |                | Static identifier of the segment element that persists across changes (ULID)                                          |                                                                  |
| `category`                    | `varchar(128)` | yes      |                | The element [category](/features/policy-management/policy-elements#categories-and-types) the element type is based on | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `type`                        | `varchar(128)` | **no**   |                | The [configured type](/features/policy-management/policy-elements#categories-and-types) the element is based on       | *defined in configuration*                                       |
| `original_effective_time_utc` | `datetime(6)`  | yes      |                | Time in UTC of the original effective date of the segment element                                                     |                                                                  |
| `deleted`                     | `tinyint(1)`   | yes      |                | Indicates whether the record has been deleted                                                                         |                                                                  |
| `datalake_created_timestamp`  | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                                                    |                                                                  |
| `datalake_updated_timestamp`  | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                                                               |                                                                  |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)
* `parent_locator` → `policy_segment_elements.locator` (`many-to-one`)

***

<span id="policy_element_tree" />

policy_element_tree [#policy_element_tree]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `segment_locator`, `parent_locator`, `child_locator`

| Column Name                  | Type          | Nullable | Attributes                    | Description                                                                       | Possible Values |
| ---------------------------- | ------------- | -------- | ----------------------------- | --------------------------------------------------------------------------------- | --------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`, `Index`                 | Unique identifier of the tenant (UUID)                                            |                 |
| `policy_locator`             | `char(26)`    | **no**   | `Index`, `Relationship`       | Identifier of the policy the element tree is associated with (ULID)               |                 |
| `transaction_locator`        | `char(26)`    | **no**   | `Index`, `Relationship`       | Identifier of the transaction the element tree is associated with (ULID)          |                 |
| `segment_locator`            | `char(26)`    | **no**   | `PK`, `Index`, `Relationship` | Identifier of the segment the element tree is associated with (ULID)              |                 |
| `parent_locator`             | `char(26)`    | **no**   | `PK`, `Relationship`          | Identifier of the element immediately above in the policy's data hierarchy (ULID) |                 |
| `child_locator`              | `char(26)`    | **no**   | `PK`, `Relationship`          | Identifier of an element immediately below in the policy's data hierarchy (ULID)  |                 |
| `depth`                      | `int(11)`     | **no**   |                               | The number of levels of child elements below in the policy's data hierarchy       |                 |
| `deleted`                    | `tinyint(1)`  | yes      |                               | Indicates whether the record has been deleted                                     |                 |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                               | Time in UTC the record was created                                                |                 |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`                       | Time in UTC the record was last updated                                           |                 |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)
* `parent_locator` → `policy_segment_elements.locator` (`many-to-one`)
* `child_locator` → `policy_segment_elements.locator` (`many-to-one`)

***

<span id="policy_element_charges" />

policy_element_charges [#policy_element_charges]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type             | Nullable | Attributes              | Description                                                                                                                                             | Possible Values                                                                                      |
| ---------------------------- | ---------------- | -------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`       | **no**   | `PK`                    | Unique identifier of the tenant (UUID)                                                                                                                  |                                                                                                      |
| `locator`                    | `char(26)`       | **no**   | `PK`                    | Unique identifier of the charge (ULID)                                                                                                                  |                                                                                                      |
| `account_locator`            | `char(26)`       | **no**   | `Relationship`          | Identifier of the account the charge is associated with (ULID)                                                                                          |                                                                                                      |
| `policy_locator`             | `char(26)`       | **no**   | `Index`, `Relationship` | Identifier of the policy the charge is associated with (ULID)                                                                                           |                                                                                                      |
| `transaction_locator`        | `char(26)`       | **no**   | `Index`, `Relationship` | Identifier of the transaction the charge is associated with (ULID)                                                                                      |                                                                                                      |
| `segment_locator`            | `char(26)`       | **no**   | `Index`, `Relationship` | Identifier of the segment the charge is associated with (ULID)                                                                                          |                                                                                                      |
| `product_name`               | `varchar(128)`   | **no**   |                         | The name of the configured product the policy is based on                                                                                               |                                                                                                      |
| `segment_element_locator`    | `char(26)`       | **no**   | `Index`, `Relationship` | Identifier of the segment element the charge is directly associated with (ULID)                                                                         |                                                                                                      |
| `element_static_locator`     | `char(26)`       | yes      | `Relationship`          | Static identifier of the element that persists across changes (ULID)                                                                                    |                                                                                                      |
| `element_category`           | `varchar(128)`   | yes      |                         | The [category](/features/policy-management/policy-elements#categories-and-types) the element type is based on                                           | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine`                                     |
| `element_type`               | `varchar(128)`   | **no**   |                         | The [configured type](/features/policy-management/policy-elements#categories-and-types) the element is based on                                         | *defined in configuration*                                                                           |
| `start_time_utc`             | `datetime(6)`    | **no**   |                         | Time in UTC the period covered by the charge begins                                                                                                     |                                                                                                      |
| `end_time_utc`               | `datetime(6)`    | **no**   |                         | Time in UTC the period covered by the charge ends                                                                                                       |                                                                                                      |
| `duration`                   | `decimal(19,15)` | yes      |                         | The number of units of `duration_basis` the charge spans                                                                                                |                                                                                                      |
| `duration_basis`             | `varchar(32)`    | yes      |                         | The units of time that the `duration` of the charge is expressed in                                                                                     | `years`, `months`, `weeks`, `days`, `hours`                                                          |
| `charge_category`            | `varchar(128)`   | **no**   |                         | The category the charge type is based on                                                                                                                | `none`, `premium`, `tax`, `fee`, `credit`, `invoiceFee`, `cededPremium`, `nonFinancial`, `surcharge` |
| `charge_type`                | `varchar(128)`   | **no**   |                         | The configured type the charge is based on                                                                                                              | *defined in configuration*                                                                           |
| `amount`                     | `decimal(19,3)`  | **no**   |                         | The amount of the charge                                                                                                                                |                                                                                                      |
| `rate`                       | `decimal(19,10)` | **no**   |                         | Rate describes the amount per unit time (rate \* duration = amount)                                                                                     |                                                                                                      |
| `reference_rate`             | `decimal(19,10)` | **no**   |                         | The reference rate for the charge returned in the rater (if any)                                                                                        |                                                                                                      |
| `rate_difference`            | `decimal(19,10)` | **no**   |                         | The difference between the rate and reference rate (if any)                                                                                             |                                                                                                      |
| `reversal_of_locator`        | `char(26)`       | yes      | `Relationship`          | Identifier of the charge reversed by this charge (if any)                                                                                               |                                                                                                      |
| `tag`                        | `varchar(128)`   | yes      |                         | The tag for the charge returned in the rater (if any)                                                                                                   |                                                                                                      |
| `invoicing`                  | `varchar(128)`   | **no**   |                         | Indicates how the system invoices the charge according to its `charge_type`, with possible values listed as `invoicing` in <ApiLink name="ChargeRef" /> | `scheduled`, `next`, `immediate`                                                                     |
| `handling`                   | `varchar(128)`   | **no**   |                         | Indicates how the system handles the charge according to its `charge_type`, with possible values listed as `handling` in <ApiLink name="ChargeRef" />   | `flat`, `normal`, `retention`                                                                        |
| `deleted`                    | `tinyint(1)`     | yes      |                         | Indicates whether the record has been deleted                                                                                                           |                                                                                                      |
| `datalake_created_timestamp` | `datetime(6)`    | **no**   |                         | Time in UTC the record was created                                                                                                                      |                                                                                                      |
| `datalake_updated_timestamp` | `datetime(6)`    | **no**   | `Index`                 | Time in UTC the record was last updated                                                                                                                 |                                                                                                      |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)
* `segment_element_locator` → `policy_segment_elements.locator` (`many-to-one`)
* `element_static_locator` → `policy_segment_elements.static_locator` (`many-to-many`)
* `reversal_of_locator` → `policy_element_charges.locator` (`many-to-one`)

***

<span id="policy_coverage_terms" />

policy_coverage_terms [#policy_coverage_terms]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `segment_element_locator`, `name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                                                | Possible Values                                                  |
| ---------------------------- | --------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                                     |                                                                  |
| `policy_locator`             | `char(26)`      | **no**   | `Relationship`       | Identifier of the policy the element data is associated with (ULID)                                                        |                                                                  |
| `transaction_locator`        | `char(26)`      | **no**   | `Relationship`       | Identifier of the transaction the element data is associated with (ULID)                                                   |                                                                  |
| `segment_locator`            | `char(26)`      | **no**   | `Relationship`       | Identifier of the segment the element data is associated with (ULID)                                                       |                                                                  |
| `segment_element_locator`    | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the element the coverage term is associated with (ULID)                                                      |                                                                  |
| `element_category`           | `varchar(128)`  | yes      |                      | The [category](/features/policy-management/policy-elements#categories-and-types) the associated element type is based on   | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `element_type`               | `varchar(128)`  | **no**   |                      | The [configured type](/features/policy-management/policy-elements#categories-and-types) the associated element is based on | *defined in configuration*                                       |
| `name_md5`                   | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `name`                                                                                                 |                                                                  |
| `name`                       | `varchar(1024)` | **no**   |                      | The configured name of the coverage term                                                                                   | *defined in configuration*                                       |
| `option`                     | `varchar(1024)` | **no**   |                      | The selected option or value of the coverage term                                                                          | *defined in configuration*                                       |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                                                              |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                                         |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                                    |                                                                  |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)
* `segment_element_locator` → `policy_segment_elements.locator` (`many-to-one`)

***

<span id="policy_element_underwriting_flags" />

policy_element_underwriting_flags [#policy_element_underwriting_flags]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes              | Description                                                                                                                | Possible Values                                                  |
| ---------------------------- | --------------- | -------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                    | Unique identifier of the tenant (UUID)                                                                                     |                                                                  |
| `locator`                    | `char(26)`      | **no**   | `PK`                    | Unique identifier of the underwriting flag (ULID)                                                                          |                                                                  |
| `policy_locator`             | `char(26)`      | **no**   | `Index`, `Relationship` | Identifier of the policy the underwriting flag is associated with (ULID)                                                   |                                                                  |
| `transaction_locator`        | `char(26)`      | **no**   | `Index`, `Relationship` | Identifier of the transaction the underwriting flag is associated with (ULID)                                              |                                                                  |
| `segment_locator`            | `char(26)`      | yes      | `Index`, `Relationship` | Identifier of the segment the underwriting flag is associated with (ULID)                                                  |                                                                  |
| `segment_element_locator`    | `char(26)`      | yes      | `Index`, `Relationship` | Identifier of the policy element the underwriting flag is associated with (ULID)                                           |                                                                  |
| `element_category`           | `varchar(128)`  | yes      |                         | The [category](/features/policy-management/policy-elements#categories-and-types) the associated element type is based on   | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `element_type`               | `varchar(128)`  | yes      |                         | The [configured type](/features/policy-management/policy-elements#categories-and-types) the associated element is based on | *defined in configuration*                                       |
| `level`                      | `varchar(128)`  | **no**   |                         | The level of the underwriting flag                                                                                         | `info`, `block`, `decline`, `reject`, `approve`                  |
| `note`                       | `varchar(1024)` | yes      |                         | The custom note associated with the underwriting flag                                                                      |                                                                  |
| `task_locator`               | `char(26)`      | yes      | `Relationship`          | Identifier of the task associated with the underwriting flag (ULID)                                                        |                                                                  |
| `created_by`                 | `char(36)`      | yes      |                         | Identifier of the user that created the underwriting flag (UUID)                                                           |                                                                  |
| `created_time_utc`           | `datetime(6)`   | **no**   |                         | Time in UTC the underwriting flag was created                                                                              |                                                                  |
| `cleared_by`                 | `char(36)`      | yes      |                         | Identifier of the user that cleared the underwriting flag (UUID)                                                           |                                                                  |
| `cleared_time_utc`           | `datetime(6)`   | yes      |                         | Time in UTC the underwriting flag was cleared                                                                              |                                                                  |
| `deleted`                    | `tinyint(1)`    | yes      |                         | Indicates whether the record has been deleted                                                                              |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                         | Time in UTC the record was created                                                                                         |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`                 | Time in UTC the record was last updated                                                                                    |                                                                  |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)
* `segment_element_locator` → `policy_segment_elements.locator` (`many-to-one`)
* `task_locator` → `tasks.locator` (`many-to-one`)

***

<span id="policy_data_extensions" />

policy_data_extensions [#policy_data_extensions]

**API Reference:** [Policies API](/api/policy-management/policies)

**Primary Key:** `tenant_locator`, `segment_element_locator`, `is_static`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                                     | Possible Values                                                  |
| ---------------------------- | --------------- | -------- | -------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                          |                                                                  |
| `policy_locator`             | `char(26)`      | **no**   | `Relationship`       | Identifier of the policy the element data is associated with (ULID)                                             |                                                                  |
| `transaction_locator`        | `char(26)`      | **no**   | `Relationship`       | Identifier of the transaction the element data is associated with (ULID)                                        |                                                                  |
| `segment_locator`            | `char(26)`      | **no**   | `Relationship`       | Identifier of the segment the element data is associated with (ULID)                                            |                                                                  |
| `segment_element_locator`    | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the element the data is associated with (ULID)                                                    |                                                                  |
| `element_category`           | `varchar(128)`  | yes      |                      | The [category](/features/policy-management/policy-elements#categories-and-types) the element type is based on   | `product`, `coverage`, `exposure`, `exposureGroup`, `policyLine` |
| `element_type`               | `varchar(128)`  | **no**   |                      | The [configured type](/features/policy-management/policy-elements#categories-and-types) the element is based on | *defined in configuration*                                       |
| `is_static`                  | `tinyint(4)`    | **no**   | `PK`                 | Whether the data is static or not                                                                               |                                                                  |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                                                |                                                                  |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the [extension data ](/configuration/data-extensions/overview) field                            | *defined in configuration*                                       |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                                                          | *defined in configuration*                                       |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                                                   |                                                                  |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                              |                                                                  |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                         |                                                                  |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)
* `segment_element_locator` → `policy_segment_elements.locator` (`many-to-one`)

***

<span id="policy_auto_renewals" />

policy_auto_renewals [#policy_auto_renewals]

**API Reference:** [Policy Auto-Renewal API](/api/policy-management/renewal-management)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                             | Type           | Nullable | Attributes              | Description                                                                      | Possible Values                                                                     |
| --------------------------------------- | -------------- | -------- | ----------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `tenant_locator`                        | `char(36)`     | **no**   | `PK`                    | Unique identifier of the tenant (UUID)                                           |                                                                                     |
| `locator`                               | `char(26)`     | **no**   | `PK`                    | Unique identifier of the policy auto-renewal (ULID)                              |                                                                                     |
| `term_locator`                          | `char(26)`     | **no**   | `Relationship`          | Identifier of the term the auto-renewal is associated with (ULID)                |                                                                                     |
| `policy_locator`                        | `char(26)`     | **no**   | `Index`, `Relationship` | Identifier of the policy the auto-renewal is associated with (ULID)              |                                                                                     |
| `state`                                 | `varchar(50)`  | **no**   |                         | Current state of the auto-renewal                                                | `active`, `discarded`, `doNotRenew`, `issued`, `error`, `terminated`, `invalidated` |
| `renewal_transaction_type`              | `varchar(128)` | **no**   |                         | The configured type of the renewal transaction                                   | *defined in configuration*                                                          |
| `renewal_transaction_locator`           | `char(26)`     | yes      | `Relationship`          | Identifier of the renewal transaction (ULID), if created                         |                                                                                     |
| `new_term_duration`                     | `int(11)`      | yes      |                         | Duration of the new term in units of the policy's `duration_basis`, if specified |                                                                                     |
| `renewal_transaction_create_time_utc`   | `datetime(6)`  | **no**   |                         | Time in UTC scheduled for the renewal transaction creation                       |                                                                                     |
| `renewal_transaction_created_time_utc`  | `datetime(6)`  | yes      |                         | Time in UTC the renewal transaction was created                                  |                                                                                     |
| `renewal_transaction_accept_time_utc`   | `datetime(6)`  | yes      |                         | Time in UTC scheduled for the renewal transaction acceptance                     |                                                                                     |
| `renewal_transaction_accepted_time_utc` | `datetime(6)`  | yes      |                         | Time in UTC the renewal transaction was accepted                                 |                                                                                     |
| `renewal_transaction_issue_time_utc`    | `datetime(6)`  | yes      |                         | Time in UTC scheduled for the renewal transaction issuance                       |                                                                                     |
| `renewal_transaction_issued_time_utc`   | `datetime(6)`  | yes      |                         | Time in UTC the renewal transaction was issued                                   |                                                                                     |
| `datalake_created_timestamp`            | `datetime(6)`  | **no**   |                         | Time in UTC the record was created                                               |                                                                                     |
| `datalake_updated_timestamp`            | `datetime(6)`  | **no**   | `Index`                 | Time in UTC the record was last updated                                          |                                                                                     |

**Relationships:**

* `term_locator` → `terms.locator` (`many-to-one`)
* `policy_locator` → `policies.locator` (`many-to-one`)
* `renewal_transaction_locator` → `transactions.locator` (`many-to-one`)

***

<span id="policy_transaction_change_instructions" />

policy_transaction_change_instructions [#policy_transaction_change_instructions]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `locator`, `transaction_locator`

| Column Name                  | Type          | Nullable | Attributes                    | Description                                                                              | Possible Values                     |
| ---------------------------- | ------------- | -------- | ----------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`                          | Unique identifier of the tenant (UUID)                                                   |                                     |
| `locator`                    | `char(26)`    | **no**   | `PK`                          | Unique identifier of the change instruction (ULID)                                       |                                     |
| `policy_locator`             | `char(26)`    | **no**   | `Index`, `Relationship`       | Identifier of the policy the change instruction is associated with (ULID)                |                                     |
| `transaction_locator`        | `char(26)`    | **no**   | `PK`, `Index`, `Relationship` | Identifier of the transaction the change instruction is associated with (ULID)           |                                     |
| `action`                     | `varchar(50)` | **no**   |                               | The action to be performed by the change instruction                                     | `add`, `params`, `modify`, `delete` |
| `data`                       | `longtext`    | yes      |                               | Structured data defining the change instruction details                                  |                                     |
| `effective_time_utc`         | `datetime(6)` | yes      |                               | Time in UTC the change instruction becomes effective                                     |                                     |
| `static_locator`             | `char(26)`    | yes      |                               | Static identifier of the element the change instruction applies to (ULID), if applicable |                                     |
| `new_policy_end_time_utc`    | `datetime(6)` | yes      |                               | Time in UTC the policy ends, if the change instruction modifies it                       |                                     |
| `trigger_billing_change`     | `tinyint(1)`  | yes      |                               | Indicates whether the change instruction should trigger billing changes                  |                                     |
| `deleted`                    | `tinyint(1)`  | yes      |                               | Indicates whether the record has been deleted                                            |                                     |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                               | Time in UTC the record was created                                                       |                                     |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`                       | Time in UTC the record was last updated                                                  |                                     |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)

***

<span id="policy_preferences" />

policy_preferences [#policy_preferences]

**API Reference:** [Policy Transactions API](/api/policy-management/policy-transactions)

**Primary Key:** `tenant_locator`, `transaction_locator`

| Column Name                  | Type            | Nullable | Attributes              | Description                                                               | Possible Values                                                                                                               |
| ---------------------------- | --------------- | -------- | ----------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`, `Index`           | Unique identifier of the tenant (UUID)                                    |                                                                                                                               |
| `policy_locator`             | `char(26)`      | **no**   | `Index`, `Relationship` | Identifier of the policy the preferences are associated with (ULID)       |                                                                                                                               |
| `transaction_locator`        | `char(26)`      | **no**   | `PK`, `Relationship`    | Identifier of the transaction the preferences are associated with (ULID)  |                                                                                                                               |
| `billing_plan_name`          | `varchar(128)`  | yes      |                         | Name of the billing plan assigned to the policy, if any                   | *defined in configuration*                                                                                                    |
| `billing_level`              | `varchar(128)`  | yes      |                         | Level at which billing for the policy takes place (`policy` or `account`) | `account`, `inherit`, `policy`                                                                                                |
| `installment_weights`        | `varchar(1024)` | yes      |                         | Custom weights for installment amounts, if specified                      |                                                                                                                               |
| `installment_plan_name`      | `varchar(128)`  | yes      |                         | Name of the installment plan assigned to the policy, if any               | *defined in configuration*                                                                                                    |
| `anchor_mode`                | `varchar(128)`  | yes      |                         | Mode for anchoring installment generation timing                          | `generateDay`, `termStartDay`, `dueDay`                                                                                       |
| `anchor_time_utc`            | `datetime(6)`   | yes      |                         | Time in UTC to anchor installment generation, if applicable               |                                                                                                                               |
| `anchor_type`                | `varchar(128)`  | yes      |                         | Type of anchor for installment generation timing                          | `none`, `dayOfMonth`, `anchorTime`, `dayOfWeek`, `weekOfMonth`                                                                |
| `cadence`                    | `varchar(128)`  | yes      |                         | Frequency of installment generation (e.g., `monthly`, `quarterly`)        | `none`, `fullPay`, `weekly`, `everyOtherWeek`, `monthly`, `quarterly`, `semiannually`, `annually`, `thirtyDays`, `everyNDays` |
| `day_of_month`               | `varchar(128)`  | yes      |                         | Day of the month for installment generation, if applicable                |                                                                                                                               |
| `day_of_week`                | `varchar(128)`  | yes      |                         | Day of the week for installment generation, if applicable                 | `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday`, `sunday`                                                  |
| `due_lead_days`              | `varchar(128)`  | yes      |                         | Number of days before due date that invoices are generated                |                                                                                                                               |
| `generate_lead_days`         | `varchar(128)`  | yes      |                         | Number of days in advance to generate installments                        |                                                                                                                               |
| `autopay_lead_days`          | `varchar(128)`  | yes      |                         | Number of days in advance of the due date to autopay invoice              |                                                                                                                               |
| `max_installments_per_term`  | `int(11)`       | yes      |                         | Maximum number of installments allowed per term, if specified             |                                                                                                                               |
| `week_of_month`              | `varchar(128)`  | yes      |                         | Week of the month for installment generation, if applicable               | `none`, `first`, `second`, `third`, `fourth`, `fifth`                                                                         |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                         | Time in UTC the record was created                                        |                                                                                                                               |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`                 | Time in UTC the record was last updated                                   |                                                                                                                               |

**Relationships:**

* `policy_locator` → `policies.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`one-to-one`)

***

<span id="policy_status" />

policy_status [#policy_status]

**Description:** This table contains one record per policy. Each record represents the current status of that policy. Multiple status fields may be true for a given policy.

**Primary Key:** `tenant_locator`, `policy_locator`

| Column Name                  | Type          | Nullable | Attributes           | Description                                                      | Possible Values |
| ---------------------------- | ------------- | -------- | -------------------- | ---------------------------------------------------------------- | --------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                           |                 |
| `policy_locator`             | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of the policy the status record corresponds to (ULID) |                 |
| `on_risk`                    | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `onRisk`               |                 |
| `pending`                    | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `pending`              |                 |
| `expired`                    | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `expired`              |                 |
| `cancelled`                  | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `cancelled`            |                 |
| `cancel_pending`             | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `cancelPending`        |                 |
| `delinquent`                 | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `delinquent`           |                 |
| `do_not_renew`               | `tinyint(1)`  | **no**   |                      | Indicates if the policy is in a status of `doNotRenew`           |                 |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                      | Time in UTC the record was created                               |                 |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`              | Time in UTC the record was last updated                          |                 |

**Relationships:**

* `policy_locator` → `policies.locator` (`one-to-one`)

***

Billing Tables [#billing-tables]

* [installments](#installments)
* [installment\_items](#installment_items)
* [installment\_settings](#installment_settings)
* [invoices](#invoices)
* [invoice\_items](#invoice_items)
* [payments](#payments)
* [payment\_data\_extensions](#payment_data_extensions)
* [disbursements](#disbursements)
* [disbursement\_data\_extensions](#disbursement_data_extensions)
* [delinquencies](#delinquencies)
* [delinquency\_references](#delinquency_references)
* [billing\_holds](#billing_holds)
* [write\_offs](#write_offs)
* [credit\_distributions](#credit_distributions)
* [credit\_items](#credit_items)
* [external\_cash\_transactions](#external_cash_transactions)
* [financial\_instruments](#financial_instruments)
* [ledger\_accounts](#ledger_accounts)
* [ledger\_account\_line\_items](#ledger_account_line_items)
* [fa\_transactions](#fa_transactions)
* [fa\_transaction\_account\_lines](#fa_transaction_account_lines)

<span id="installments" />

installments [#installments]

**API Reference:** [Installments API](/api/billing/installments)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                    | Type            | Nullable | Attributes     | Description                                                                                                  | Possible Values |
| ------------------------------ | --------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------------------ | --------------- |
| `tenant_locator`               | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                       |                 |
| `locator`                      | `char(26)`      | **no**   | `PK`           | Unique identifier of the installment (ULID)                                                                  |                 |
| `account_locator`              | `char(26)`      | **no**   | `Relationship` | Identifier of the account the installment is associated with (ULID)                                          |                 |
| `due_time_utc`                 | `datetime(6)`   | **no**   |                | Time in UTC the installment payment is due                                                                   |                 |
| `generate_time_utc`            | `datetime(6)`   | **no**   |                | Time in UTC the installment was generated                                                                    |                 |
| `autopay_time_utc`             | `datetime(6)`   | yes      |                | Time in UTC the installment payment execution will be triggered                                              |                 |
| `currency`                     | `varchar(128)`  | **no**   |                | Currency of the installment                                                                                  |                 |
| `timezone`                     | `varchar(128)`  | **no**   |                | Timezone in which the installment was generated                                                              |                 |
| `coverage_duration`            | `decimal(19,3)` | **no**   |                | Duration of coverage represented by the installment                                                          |                 |
| `coverage_start_time_utc`      | `datetime(6)`   | **no**   |                | Time in UTC when coverage for the installment begins                                                         |                 |
| `coverage_end_time_utc`        | `datetime(6)`   | **no**   |                | Time in UTC when coverage for the installment ends                                                           |                 |
| `installment_duration`         | `decimal(19,3)` | **no**   |                | Duration of the installment period                                                                           |                 |
| `installment_start_time_utc`   | `datetime(6)`   | **no**   |                | Time in UTC when the installment period begins                                                               |                 |
| `installment_end_time_utc`     | `datetime(6)`   | **no**   |                | Time in UTC when the installment period ends                                                                 |                 |
| `installment_frame_index`      | `int(11)`       | **no**   |                | Index of the installment within the billing frame sequence                                                   |                 |
| `installment_lattice_locator`  | `char(26)`      | **no**   |                | Identifier of the installment lattice that this installment corresponds from                                 |                 |
| `installment_settings_locator` | `char(26)`      | yes      | `Relationship` | Identifier of the installment settings locator that applies to this installment                              |                 |
| `reversal_of_locator`          | `char(26)`      | yes      | `Relationship` | Identifier of the installment that this installment is a reversal of, if applicable                          |                 |
| `migrated_from_locator`        | `char(26)`      | yes      | `Relationship` | Identifier of the installment that this installment was migrated from, in the case of a billing mode change  |                 |
| `enhanced_by_plugin`           | `tinyint(1)`    | yes      |                | Indicates if this installment was enhanced by the Installment Plugin or follows default installment settings |                 |
| `created_by`                   | `char(36)`      | **no**   |                | Identifier of the user that created the installment (UUID)                                                   |                 |
| `created_at_utc`               | `datetime(6)`   | **no**   |                | Time in UTC the installment was created                                                                      |                 |
| `updated_by`                   | `char(36)`      | **no**   |                | Identifier of the user that last updated the installment (UUID)                                              |                 |
| `updated_at_utc`               | `datetime(6)`   | **no**   |                | Time in UTC the installment was last updated                                                                 |                 |
| `invoice_locator`              | `char(26)`      | yes      | `Relationship` | Identifier of the invoice the installment is associated with (ULID), if any                                  |                 |
| `policy_locator`               | `char(26)`      | yes      | `Relationship` | Identifier of the policy the installment is associated with (ULID), if any                                   |                 |
| `term_locator`                 | `char(26)`      | yes      | `Relationship` | Identifier of the term the installment is associated with (ULID), if any                                     |                 |
| `quote_locator`                | `char(26)`      | yes      | `Relationship` | Identifier of the quote the installment is associated with (ULID), if any                                    |                 |
| `transaction_locator`          | `char(26)`      | yes      | `Relationship` | Identifier of the transaction that triggered the installment (ULID), if any                                  |                 |
| `datalake_created_timestamp`   | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                                                           |                 |
| `datalake_updated_timestamp`   | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                                                      |                 |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `installment_settings_locator` → `installment_settings.locator` (`many-to-one`)
* `reversal_of_locator` → `installments.locator` (`many-to-one`)
* `migrated_from_locator` → `installments.locator` (`many-to-one`)
* `invoice_locator` → `invoices.locator` (`many-to-one`)
* `policy_locator` → `policies.locator` (`many-to-one`)
* `term_locator` → `terms.locator` (`many-to-one`)
* `quote_locator` → `quotes.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)

***

<span id="installment_items" />

installment_items [#installment_items]

**API Reference:** [Installments API](/api/billing/installments)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes              | Description                                                                         | Possible Values                                                                                      |
| ---------------------------- | --------------- | -------- | ----------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                    | Unique identifier of the tenant (UUID)                                              |                                                                                                      |
| `locator`                    | `char(26)`      | **no**   | `PK`                    | Unique identifier of the installment item (ULID)                                    |                                                                                                      |
| `installment_locator`        | `char(26)`      | **no**   | `Index`, `Relationship` | Identifier of the installment the installment item is associated with (ULID)        |                                                                                                      |
| `charge_locator`             | `char(26)`      | **no**   | `Relationship`          | Identifier of the charge the installment item is associated with (ULID)             |                                                                                                      |
| `segment_element_locator`    | `char(26)`      | **no**   | `Relationship`          | Identifier of the segment element the installment item is associated with (ULID)    |                                                                                                      |
| `charge_category`            | `varchar(128)`  | **no**   |                         | Category of the associated charge                                                   | `none`, `premium`, `tax`, `fee`, `credit`, `invoiceFee`, `cededPremium`, `nonFinancial`, `surcharge` |
| `charge_type`                | `varchar(128)`  | **no**   |                         | Type of the associated charge                                                       | *defined in configuration*                                                                           |
| `amount`                     | `decimal(19,3)` | **no**   |                         | Amount of the installment item                                                      |                                                                                                      |
| `created_time_utc`           | `datetime(6)`   | **no**   |                         | Time in UTC the installment item was created                                        |                                                                                                      |
| `created_by`                 | `char(36)`      | yes      |                         | Identifier of the user that created the installment item (UUID)                     |                                                                                                      |
| `element_static_locator`     | `char(26)`      | **no**   | `Relationship`          | Static identifier of the associated segment element (ULID)                          |                                                                                                      |
| `invoice_item_locator`       | `char(26)`      | yes      | `Relationship`          | Identifier of the associated invoice item (ULID), if any                            |                                                                                                      |
| `reversal_of_locator`        | `char(26)`      | yes      | `Relationship`          | Identifier of the installment item reversed by this installment item (ULID), if any |                                                                                                      |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                         | Time in UTC the record was created                                                  |                                                                                                      |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   |                         | Time in UTC the record was last updated                                             |                                                                                                      |

**Relationships:**

* `installment_locator` → `installments.locator` (`many-to-one`)
* `charge_locator` → `policy_element_charges.locator` (`many-to-one`)
* `segment_element_locator` → `policy_segment_elements.locator` (`many-to-one`)
* `element_static_locator` → `policy_segment_elements.static_locator` (`many-to-many`)
* `invoice_item_locator` → `invoice_items.locator` (`many-to-one`)
* `reversal_of_locator` → `installment_items.locator` (`many-to-one`)

***

<span id="installment_settings" />

installment_settings [#installment_settings]

**API Reference:** [Installment Lattices API](/api/billing/installment-lattices)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes | Description                                                                 | Possible Values                                                                                                               |
| ---------------------------- | --------------- | -------- | ---------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`       | Unique identifier of the tenant (UUID)                                      |                                                                                                                               |
| `locator`                    | `char(26)`      | **no**   | `PK`       | Unique identifier of the installment settings (UUID)                        |                                                                                                                               |
| `installment_weights`        | `varchar(1024)` | yes      |            | Custom weights for installment amounts, if specified                        |                                                                                                                               |
| `anchor_mode`                | `varchar(128)`  | **no**   |            | Mode for anchoring installment generation timing                            | `generateDay`, `termStartDay`, `dueDay`                                                                                       |
| `anchor_time_utc`            | `datetime(6)`   | yes      |            | Time in UTC to anchor installment generation, if applicable                 |                                                                                                                               |
| `anchor_type`                | `varchar(128)`  | yes      |            | Type of anchor for installment generation timing                            | `none`, `dayOfMonth`, `anchorTime`, `dayOfWeek`, `weekOfMonth`                                                                |
| `cadence`                    | `varchar(128)`  | **no**   |            | Frequency of installment generation (e.g., `monthly`, `quarterly`)          | `none`, `fullPay`, `weekly`, `everyOtherWeek`, `monthly`, `quarterly`, `semiannually`, `annually`, `thirtyDays`, `everyNDays` |
| `day_of_month`               | `varchar(128)`  | yes      |            | Day of the month for installment generation, if applicable                  |                                                                                                                               |
| `day_of_week`                | `varchar(128)`  | yes      |            | Day of the week for installment generation, if applicable                   | `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday`, `sunday`                                                  |
| `week_of_month`              | `varchar(128)`  | yes      |            | Week of the month for installment generation, if applicable                 | `none`, `first`, `second`, `third`, `fourth`, `fifth`                                                                         |
| `due_lead_days`              | `varchar(128)`  | **no**   |            | Number of days before due date that invoices are generated                  |                                                                                                                               |
| `generate_lead_days`         | `varchar(128)`  | **no**   |            | Number of days in advance to generate installments                          |                                                                                                                               |
| `autopay_lead_days`          | `varchar(128)`  | yes      |            | Number of days in advance of the due date to trigger autopay for an invoice |                                                                                                                               |
| `max_installments_per_term`  | `int(11)`       | yes      |            | Maximum number of installments allowed per term, if specified               |                                                                                                                               |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |            | Time in UTC the record was created                                          |                                                                                                                               |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`    | Time in UTC the record was last updated                                     |                                                                                                                               |

***

<span id="invoices" />

invoices [#invoices]

**API Reference:** [Invoices API](/api/billing/invoices)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                                                         | Possible Values                |
| ---------------------------- | --------------- | -------- | -------------- | --------------------------------------------------------------------------------------------------- | ------------------------------ |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                              |                                |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the invoice (ULID)                                                             |                                |
| `account_locator`            | `char(26)`      | **no**   | `Relationship` | Identifier of the account the invoice is associated with (ULID)                                     |                                |
| `start_time_utc`             | `datetime(6)`   | **no**   |                | Time in UTC when the invoice period begins                                                          |                                |
| `end_time_utc`               | `datetime(6)`   | **no**   |                | Time in UTC when the invoice period ends                                                            |                                |
| `due_time_utc`               | `datetime(6)`   | **no**   |                | Time in UTC when the invoice is due                                                                 |                                |
| `generated_time_utc`         | `datetime(6)`   | **no**   |                | Time in UTC the invoice was generated                                                               |                                |
| `currency`                   | `varchar(128)`  | **no**   |                | Currency of the invoice                                                                             |                                |
| `timezone`                   | `varchar(128)`  | **no**   |                | Timezone in which the invoice was generated                                                         |                                |
| `invoice_state`              | `varchar(50)`   | **no**   |                | Current state of the invoice                                                                        | `open`, `settled`, `discarded` |
| `invoice_number`             | `varchar(128)`  | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the invoice, if any |                                |
| `total_amount`               | `decimal(19,3)` | yes      |                | Total amount of the invoice                                                                         |                                |
| `total_remaining_amount`     | `decimal(19,3)` | yes      |                | Remaining unpaid amount of the invoice                                                              |                                |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                                                  |                                |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                                             |                                |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="invoice_items" />

invoice_items [#invoice_items]

**API Reference:** [Invoices API](/api/billing/invoices)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                                      | Possible Values                                                                                      |
| ---------------------------- | --------------- | -------- | -------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                           |                                                                                                      |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the invoice item (ULID)                                     |                                                                                                      |
| `invoice_locator`            | `char(26)`      | **no**   | `Relationship` | Identifier of the invoice the item is associated with (ULID)                     |                                                                                                      |
| `timezone`                   | `varchar(128)`  | **no**   |                | Timezone for the invoice item                                                    |                                                                                                      |
| `amount`                     | `decimal(19,3)` | yes      |                | Amount of the invoice item                                                       |                                                                                                      |
| `charge_category`            | `varchar(128)`  | **no**   |                | Category of the associated charge                                                | `none`, `premium`, `tax`, `fee`, `credit`, `invoiceFee`, `cededPremium`, `nonFinancial`, `surcharge` |
| `charge_type`                | `varchar(128)`  | **no**   |                | Configured type of the associated charge                                         | *defined in configuration*                                                                           |
| `policy_locator`             | `char(26)`      | yes      | `Relationship` | Identifier of the policy the invoice item is associated with (ULID), if any      |                                                                                                      |
| `quote_locator`              | `char(26)`      | yes      | `Relationship` | Identifier of the quote the invoice item is associated with (ULID), if any       |                                                                                                      |
| `element_static_locator`     | `char(26)`      | yes      | `Relationship` | Static identifier of the element associated with the invoice item (ULID), if any |                                                                                                      |
| `remaining_amount`           | `decimal(19,3)` | yes      |                | Remaining unpaid amount of the invoice item                                      |                                                                                                      |
| `settlement_time_utc`        | `datetime(6)`   | yes      |                | Time in UTC when the invoice item was fully settled                              |                                                                                                      |
| `unsettled_time_utc`         | `datetime(6)`   | yes      |                | Time in UTC the invoice item was unsettled                                       |                                                                                                      |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                               |                                                                                                      |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                          |                                                                                                      |

**Relationships:**

* `invoice_locator` → `invoices.locator` (`many-to-one`)
* `policy_locator` → `policies.locator` (`many-to-one`)
* `quote_locator` → `quotes.locator` (`many-to-one`)
* `element_static_locator` → `policy_segment_elements.static_locator` (`many-to-many`)

***

<span id="payments" />

payments [#payments]

**API Reference:** [Payments API](/api/billing/payments)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                                                          | Possible Values                                                                                          |
| ---------------------------- | --------------- | -------- | -------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                               |                                                                                                          |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the payment (UUID)                                                              |                                                                                                          |
| `currency`                   | `varchar(128)`  | **no**   |                | Currency of the payment                                                                              |                                                                                                          |
| `payment_state`              | `varchar(30)`   | **no**   |                | Current state of the payment                                                                         | `draft`, `validated`, `requested`, `executing`, `posted`, `failed`, `cancelled`, `reversed`, `discarded` |
| `amount`                     | `decimal(19,3)` | yes      |                | Amount of the payment                                                                                |                                                                                                          |
| `type`                       | `varchar(128)`  | **no**   |                | The configured type of the payment                                                                   | *defined in configuration*                                                                               |
| `created_by`                 | `char(36)`      | **no**   |                | Identifier of the user that created the payment (UUID)                                               |                                                                                                          |
| `created_at_utc`             | `datetime(6)`   | **no**   |                | Time in UTC the payment was created                                                                  |                                                                                                          |
| `account_locator`            | `char(26)`      | yes      | `Relationship` | Identifier of the account the payment is associated with (ULID), if any                              |                                                                                                          |
| `ext_cash_trx_locator`       | `char(26)`      | yes      | `Relationship` | Identifier of the external cash transaction (ULID), if any                                           |                                                                                                          |
| `posted_at_utc`              | `datetime(6)`   | yes      |                | Time in UTC the payment was posted                                                                   |                                                                                                          |
| `remaining_amount`           | `decimal(19,3)` | yes      |                | Remaining unapplied amount of the payment                                                            |                                                                                                          |
| `reversal_reason`            | `varchar(1024)` | yes      |                | Reason for the payment reversal, if reversed                                                         |                                                                                                          |
| `reversed_at_utc`            | `datetime(6)`   | yes      |                | Time in UTC the payment was reversed                                                                 |                                                                                                          |
| `reversed_by`                | `char(36)`      | yes      |                | Identifier of the user who reversed the payment (UUID)                                               |                                                                                                          |
| `aggregate_payment_locator`  | `char(26)`      | yes      | `Relationship` | Identifier of the aggregate payment this payment belongs to (ULID), if any                           |                                                                                                          |
| `payment_mode`               | `varchar(128)`  | yes      |                | Indicates the mode of the payment (e.g., `normal`, `aggregate`)                                      | `normal`, `aggregate`                                                                                    |
| `retry_plan_name`            | `varchar(256)`  | yes      |                | Name of the payment execution retry plan associated with the payment, if any                         | *defined in configuration*                                                                               |
| `next_request_time_utc`      | `datetime(6)`   | yes      |                | Time in UTC the next payment request will be attempted                                               |                                                                                                          |
| `payment_number`             | `varchar(128)`  | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the payment (if any) |                                                                                                          |
| `anonymized_time_utc`        | `datetime(6)`   | yes      |                | Time in UTC the payment was anonymized                                                               |                                                                                                          |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                                                   |                                                                                                          |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                                              |                                                                                                          |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `ext_cash_trx_locator` → `external_cash_transactions.locator` (`many-to-one`)
* `aggregate_payment_locator` → `payments.locator` (`many-to-one`)

***

<span id="payment_data_extensions" />

payment_data_extensions [#payment_data_extensions]

**API Reference:** [Payments API](/api/billing/payments)

**Primary Key:** `tenant_locator`, `payment_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                          | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | ------------------------------------------------------------------------------------ | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                               |                            |
| `payment_locator`            | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the payment the extension data is associated with (ULID)               |                            |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                     |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the [extension data ](/configuration/data-extensions/overview) field | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                               | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                        |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                   |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                              |                            |

**Relationships:**

* `payment_locator` → `payments.locator` (`many-to-one`)

***

<span id="disbursements" />

disbursements [#disbursements]

**API Reference:** [Disbursements API](/api/billing/disbursements)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                                                               | Possible Values                                                                   |
| ---------------------------- | --------------- | -------- | -------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                    |                                                                                   |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the disbursement (UUID)                                                              |                                                                                   |
| `currency`                   | `varchar(128)`  | **no**   |                | Currency of the disbursement                                                                              |                                                                                   |
| `disbursement_state`         | `varchar(30)`   | **no**   |                | Current state of the disbursement                                                                         | `draft`, `validated`, `approved`, `executed`, `reversed`, `rejected`, `discarded` |
| `amount`                     | `decimal(19,3)` | yes      |                | Amount of the disbursement                                                                                |                                                                                   |
| `type`                       | `varchar(128)`  | **no**   |                | The configured type of the disbursement                                                                   | *defined in configuration*                                                        |
| `created_by`                 | `char(36)`      | **no**   |                | Identifier of the user that created the disbursement (UUID)                                               |                                                                                   |
| `created_at_utc`             | `datetime(6)`   | **no**   |                | Time in UTC the disbursement was created                                                                  |                                                                                   |
| `account_locator`            | `char(26)`      | yes      | `Relationship` | Identifier of the account the disbursement is associated with (ULID), if any                              |                                                                                   |
| `ext_cash_trx_locator`       | `char(26)`      | yes      | `Relationship` | Identifier of the external cash transaction (ULID), if any                                                |                                                                                   |
| `disbursement_number`        | `varchar(128)`  | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the disbursement (if any) |                                                                                   |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                                                        |                                                                                   |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                                                   |                                                                                   |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `ext_cash_trx_locator` → `external_cash_transactions.locator` (`many-to-one`)

***

<span id="disbursement_data_extensions" />

disbursement_data_extensions [#disbursement_data_extensions]

**API Reference:** [Disbursements API](/api/billing/disbursements)

**Primary Key:** `tenant_locator`, `disbursement_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                          | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | ------------------------------------------------------------------------------------ | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                               |                            |
| `disbursement_locator`       | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the disbursement the extension data is associated with (ULID)          |                            |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                     |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the [extension data ](/configuration/data-extensions/overview) field | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                               | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                        |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                   |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                              |                            |

**Relationships:**

* `disbursement_locator` → `disbursements.locator` (`many-to-one`)

***

<span id="delinquencies" />

delinquencies [#delinquencies]

**API Reference:** [Delinquency API](/api/billing/delinquency)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                            | Type           | Nullable | Attributes     | Description                                                                      | Possible Values                                                               |
| -------------------------------------- | -------------- | -------- | -------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `tenant_locator`                       | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                           |                                                                               |
| `locator`                              | `char(26)`     | **no**   | `PK`           | Unique identifier of the delinquency (ULID)                                      |                                                                               |
| `account_locator`                      | `char(26)`     | **no**   | `Relationship` | Identifier of the account the delinquency is associated with (ULID)              |                                                                               |
| `timezone`                             | `varchar(128)` | **no**   |                | Timezone for the delinquency                                                     |                                                                               |
| `delinquency_state`                    | `varchar(52)`  | **no**   |                | Current state of the delinquency                                                 | `preGrace`, `inGrace`, `lapseTriggered`, `settled`, `lapseTransactionCreated` |
| `advance_lapse_to`                     | `varchar(128)` | **no**   |                | The state to which the system should automatically advance the lapse transaction | `draft`, `validated`, `priced`, `underwritten`, `accepted`, `issued`          |
| `grace_period_days`                    | `int(11)`      | **no**   |                | Number of days in the grace period before lapse                                  |                                                                               |
| `lapse_transaction_type`               | `varchar(128)` | **no**   |                | The configured type of lapse transaction to be created                           | *defined in configuration*                                                    |
| `delinquency_level`                    | `varchar(128)` | yes      |                | Level at which the delinquency is applied. Value may be `policy` or `invoice`    | `policy`, `invoice`                                                           |
| `created_at_utc`                       | `datetime(6)`  | **no**   |                | Time in UTC the delinquency was created                                          |                                                                               |
| `updated_at_utc`                       | `datetime(6)`  | **no**   |                | Time in UTC the delinquency was last updated                                     |                                                                               |
| `grace_end_at_utc`                     | `datetime(6)`  | yes      |                | Time in UTC when the grace period ends                                           |                                                                               |
| `grace_started_at_utc`                 | `datetime(6)`  | yes      |                | Time in UTC when the grace period started                                        |                                                                               |
| `lapse_transaction_effective_date_utc` | `datetime(6)`  | yes      |                | Effective date in UTC for the lapse transaction, if applicable                   |                                                                               |
| `datalake_created_timestamp`           | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                               |                                                                               |
| `datalake_updated_timestamp`           | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                          |                                                                               |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="delinquency_references" />

delinquency_references [#delinquency_references]

**Description:** This table contains multiple records per delinquency. Each record represents a relationship between a delinquency and another entity, such as a policy or invoice.

**API Reference:** [Delinquency API](/api/billing/delinquency)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                            | Type           | Nullable | Attributes      | Description                                                                                                                            | Possible Values     |
| -------------------------------------- | -------------- | -------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `tenant_locator`                       | `char(36)`     | **no**   | `PK`            | Unique identifier of the tenant (UUID)                                                                                                 |                     |
| `locator`                              | `char(26)`     | **no**   | `PK`            | Unique identifier of the delinquency reference (ULID)                                                                                  |                     |
| `delinquency_locator`                  | `char(26)`     | **no**   | `Relationship`  | Identifier of the delinquency that the referenced entity is associated with (ULID)                                                     |                     |
| `reference_locator`                    | `char(26)`     | **no**   | `Relationship`  | Identifier of the reference, with referenced entity defined by `reference_type` (ULID)                                                 |                     |
| `reference_type`                       | `varchar(128)` | **no**   | `Discriminator` | Reference type of the delinquency reference, with possible values listed as `referenceType` in <ApiLink name="DelinquencyReference" /> | `policy`, `invoice` |
| `transaction_locator`                  | `char(26)`     | yes      | `Relationship`  | Identifier of the lapse transaction associated with this delinquency reference                                                         |                     |
| `preempting_lapse_transaction_locator` | `char(26)`     | yes      | `Relationship`  | Identifier of the lapse transaction associated with another delinquency reference that preempts this one                               |                     |
| `datalake_created_timestamp`           | `datetime(6)`  | **no**   |                 | Time in UTC the record was created                                                                                                     |                     |
| `datalake_updated_timestamp`           | `datetime(6)`  | **no**   | `Index`         | Time in UTC the record was last updated                                                                                                |                     |

**Relationships:**

* `delinquency_locator` → `delinquencies.locator` (`many-to-one`)
* `reference_locator` *(depends on `reference_type`)*:
  * `policy` → `policies.locator` (`many-to-one`)
  * `invoice` → `invoices.locator` (`many-to-one`)
* `transaction_locator` → `transactions.locator` (`many-to-one`)
* `preempting_lapse_transaction_locator` → `transactions.locator` (`many-to-one`)

***

<span id="billing_holds" />

billing_holds [#billing_holds]

**API Reference:** [Billing Holds API](/api/billing/holds)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type          | Nullable | Attributes     | Description                                                          | Possible Values                                         |
| ---------------------------- | ------------- | -------- | -------------- | -------------------------------------------------------------------- | ------------------------------------------------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`           | Unique identifier of the tenant (UUID)                               |                                                         |
| `locator`                    | `char(26)`    | **no**   | `PK`           | Unique identifier of the billing hold (ULID)                         |                                                         |
| `account_locator`            | `char(26)`    | **no**   | `Relationship` | Identifier of the account the billing hold is associated with (ULID) |                                                         |
| `hold_state`                 | `varchar(50)` | **no**   |                | Current state of the billing hold                                    | `draft`, `validated`, `active`, `discarded`, `released` |
| `target_type`                | `varchar(50)` | **no**   |                | The type of entity the billing hold applies to                       | `invoicing`, `delinquency`                              |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                | Time in UTC the record was created                                   |                                                         |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`        | Time in UTC the record was last updated                              |                                                         |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="write_offs" />

write_offs [#write_offs]

**API Reference:** [Write-Offs API](/api/billing/write-offs)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                       | Possible Values                    |
| ---------------------------- | --------------- | -------- | -------------- | ----------------------------------------------------------------- | ---------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                            |                                    |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the write-off (ULID)                         |                                    |
| `account_locator`            | `char(26)`      | **no**   | `Relationship` | Identifier of the account the write-off is associated with (ULID) |                                    |
| `currency`                   | `varchar(128)`  | **no**   |                | Currency of the write-off                                         |                                    |
| `write_off_state`            | `varchar(30)`   | **no**   |                | Current state of the write-off                                    | `draft`, `distributed`, `reversed` |
| `amount`                     | `decimal(19,3)` | **no**   |                | Amount of the write-off                                           |                                    |
| `credit_type`                | `varchar(128)`  | **no**   |                | Type of credit associated with the write-off                      | `writeOff`, `shortfallWriteOff`    |
| `created_by`                 | `char(36)`      | **no**   |                | Identifier of the user that created the write-off (UUID)          |                                    |
| `created_at_utc`             | `datetime(6)`   | **no**   |                | Time in UTC the write-off was created                             |                                    |
| `reversal_reason`            | `varchar(1024)` | yes      |                | Reason for the write-off reversal, if reversed                    |                                    |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                |                                    |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                           |                                    |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="credit_distributions" />

credit_distributions [#credit_distributions]

**API Reference:** [Credit Distribution API](/api/billing/credit-distribution)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes     | Description                                                                                                                                                         | Possible Values                                           |
| ---------------------------- | --------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                                                                              |                                                           |
| `locator`                    | `char(26)`      | **no**   | `PK`           | Unique identifier of the credit distribution (ULID)                                                                                                                 |                                                           |
| `account_locator`            | `char(26)`      | yes      | `Relationship` | Identifier of the associated account (ULID)                                                                                                                         |                                                           |
| `currency`                   | `varchar(128)`  | **no**   |                | Currency of the credit distribution                                                                                                                                 |                                                           |
| `credit_distribution_state`  | `varchar(30)`   | **no**   |                | State in which the credit distribution currently resides, with possible values listed as `creditDistributionState` in <ApiLink name="CreditDistributionResponse" /> | `draft`, `validated`, `executed`, `reversed`, `discarded` |
| `amount`                     | `decimal(19,3)` | **no**   |                | Amount of the credit distribution                                                                                                                                   |                                                           |
| `created_time_utc`           | `datetime(6)`   | **no**   |                | Time in UTC the credit distribution was created                                                                                                                     |                                                           |
| `created_by`                 | `char(36)`      | yes      |                | Identifier of the user that created the credit distribution (UUID)                                                                                                  |                                                           |
| `execution_time_utc`         | `datetime(6)`   | yes      |                | Time in UTC the credit distribution was executed                                                                                                                    |                                                           |
| `reversal_reason`            | `varchar(1024)` | yes      |                | Reason for the credit distribution reversal                                                                                                                         |                                                           |
| `reversal_time_utc`          | `datetime(6)`   | yes      |                | Time in UTC the credit distribution was reversed                                                                                                                    |                                                           |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                | Time in UTC the record was created                                                                                                                                  |                                                           |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`        | Time in UTC the record was last updated                                                                                                                             |                                                           |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="credit_items" />

credit_items [#credit_items]

**API Reference:** [Credits API](/api/billing/credits)

**Primary Key:** `tenant_locator`, `credit_locator`, `container_locator`, `container_type`

| Column Name                  | Type            | Nullable | Attributes            | Description                                                                                                        | Possible Values                                                                                |
| ---------------------------- | --------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                  | Unique identifier of the tenant (UUID)                                                                             |                                                                                                |
| `credit_locator`             | `char(26)`      | **no**   | `PK`, `Relationship`  | Identifier of the associated credit (ULID), with referenced entity defined by `credit_type`                        |                                                                                                |
| `credit_type`                | `varchar(128)`  | **no**   | `Discriminator`       | Type of the associated credit, with possible values listed as `creditType` in <ApiLink name="CreditResponse" />    | `creditDistribution`, `disbursement`, `payment`, `subpayment`, `shortfallWriteOff`, `writeOff` |
| `container_locator`          | `char(26)`      | **no**   | `PK`, `Relationship`  | Identifier of the associated source or target container (ULID), with referenced entity defined by `container_type` |                                                                                                |
| `container_type`             | `varchar(128)`  | **no**   | `PK`, `Discriminator` | Type of the associated container, with possible values listed as `containerType` in <ApiLink name="CreditItem" />  | `invoice`, `account`, `subpayment`, `invoiceItem`                                              |
| `amount`                     | `decimal(19,3)` | yes      |                       | Amount of the credit item                                                                                          |                                                                                                |
| `deleted`                    | `tinyint(1)`    | yes      |                       | Indicates whether the record has been deleted                                                                      |                                                                                                |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                       | Time in UTC the record was created                                                                                 |                                                                                                |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`               | Time in UTC the record was last updated                                                                            |                                                                                                |

**Relationships:**

* `credit_locator` *(depends on `credit_type`)*:
  * `creditDistribution` → `credit_distributions.locator` (`many-to-one`)
  * `disbursement` → `disbursements.locator` (`many-to-one`)
  * `payment` → `payments.locator` (`many-to-one`)
  * `subpayment` → `payments.locator` (`many-to-one`)
  * `shortfallWriteOff` → `write_offs.locator` (`many-to-one`)
  * `writeOff` → `write_offs.locator` (`many-to-one`)
* `container_locator` *(depends on `container_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `invoice` → `invoices.locator` (`many-to-one`)
  * `invoiceItem` → `invoice_items.locator` (`many-to-one`)
  * `subpayment` → `payments.locator` (`many-to-one`)

***

<span id="external_cash_transactions" />

external_cash_transactions [#external_cash_transactions]

**Primary Key:** `tenant_locator`, `locator`

| Column Name                    | Type           | Nullable | Attributes     | Description                                                                                              | Possible Values                          |
| ------------------------------ | -------------- | -------- | -------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| `tenant_locator`               | `char(36)`     | **no**   |                | Unique identifier of the tenant (UUID)                                                                   |                                          |
| `locator`                      | `char(26)`     | **no**   |                | Unique identifier of the external cash transaction (ULID)                                                |                                          |
| `financial_instrument_locator` | `char(26)`     | yes      | `Relationship` | Identifier of the financial instrument the transaction was executed against (ULID), if any               |                                          |
| `transaction_method`           | `varchar(128)` | yes      |                | The method used to execute the transaction                                                               | `ach`, `cash`, `eft`, `standard`, `wire` |
| `transaction_number`           | `varchar(128)` | yes      |                | The identifier or confirmation number for the transaction, as returned by the external payment processor |                                          |
| `datalake_created_timestamp`   | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                                       |                                          |
| `datalake_updated_timestamp`   | `datetime(6)`  | **no**   |                | Time in UTC the record was last updated                                                                  |                                          |

**Relationships:**

* `financial_instrument_locator` → `financial_instruments.locator` (`many-to-one`)

***

<span id="financial_instruments" />

financial_instruments [#financial_instruments]

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type           | Nullable | Attributes     | Description                                                                      | Possible Values                                  |
| ---------------------------- | -------------- | -------- | -------------- | -------------------------------------------------------------------------------- | ------------------------------------------------ |
| `tenant_locator`             | `char(36)`     | **no**   |                | Unique identifier of the tenant (UUID)                                           |                                                  |
| `locator`                    | `char(26)`     | **no**   |                | Unique identifier of the financial instrument (ULID)                             |                                                  |
| `account_locator`            | `char(26)`     | yes      | `Relationship` | Identifier of the account the financial instrument is associated with (ULID)     |                                                  |
| `institution_name`           | `varchar(128)` | yes      |                | Name of the financial institution (e.g. bank or card issuer)                     |                                                  |
| `instrument_type`            | `varchar(50)`  | yes      |                | The type of financial instrument                                                 | `checking`, `savings`, `creditCard`, `debitCard` |
| `default_transaction_method` | `varchar(50)`  | yes      |                | The default transaction method used when transacting with this instrument        | `ach`, `cash`, `eft`, `standard`, `wire`         |
| `retry_plan_name`            | `varchar(256)` | yes      |                | Name of the retry plan applied to failed transactions on this instrument, if any | *defined in configuration*                       |
| `external_identifier`        | `varchar(512)` | yes      |                | Identifier for the instrument as provided by the external payment processor      |                                                  |
| `external_account_number`    | `varchar(128)` | yes      |                | Account number for the instrument, as provided by the external payment processor |                                                  |
| `nickname`                   | `varchar(128)` | yes      |                | Custom nickname for the financial instrument                                     |                                                  |
| `expiration_time_utc`        | `datetime(6)`  | yes      |                | Time in UTC the financial instrument (e.g. card) expires, if applicable          |                                                  |
| `is_default`                 | `tinyint(1)`   | yes      |                | Whether this is the account's default financial instrument                       |                                                  |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                               |                                                  |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   |                | Time in UTC the record was last updated                                          |                                                  |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)

***

<span id="ledger_accounts" />

ledger_accounts [#ledger_accounts]

**API Reference:** [Accounting API](/api/accounting)

**Primary Key:** `tenant_locator`, `reference_type`, `reference_locator`, `currency`

| Column Name                  | Type            | Nullable | Attributes            | Description                                                                                                                              | Possible Values                                                                                                                                                          |
| ---------------------------- | --------------- | -------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                  | Unique identifier of the tenant (UUID)                                                                                                   |                                                                                                                                                                          |
| `reference_type`             | `char(68)`      | **no**   | `PK`, `Discriminator` | Reference type of the ledger account balance, with possible values listed as `referenceType` in <ApiLink name="LedgerAccountResponse" /> | `accountCreditBalance`, `invoiceCreditBalance`, `cash`, `creditCash`, `charge`, `credit`, `installmentItem`, `invoiceItem`, `account`, `policy`, `accountExpenseBalance` |
| `reference_locator`          | `char(26)`      | **no**   | `PK`, `Relationship`  | Identifier of the reference, with referenced entity defined by `reference_type` (ULID)                                                   |                                                                                                                                                                          |
| `currency`                   | `varchar(128)`  | **no**   | `PK`                  | Currency of the ledger account balance                                                                                                   |                                                                                                                                                                          |
| `balance`                    | `decimal(19,3)` | **no**   |                       | Balance of the ledger account                                                                                                            |                                                                                                                                                                          |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                       | Time in UTC the record was created                                                                                                       |                                                                                                                                                                          |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`               | Time in UTC the record was last updated                                                                                                  |                                                                                                                                                                          |

**Relationships:**

* `reference_locator` *(depends on `reference_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `policy` → `policies.locator` (`many-to-one`)
  * `invoiceItem` → `invoice_items.locator` (`many-to-one`)
  * `installmentItem` → `installment_items.locator` (`many-to-one`)
  * `credit`:
    * `payments.locator` (`many-to-one`)
    * `credit_distributions.locator` (`many-to-one`)
    * `disbursements.locator` (`many-to-one`)
    * `write_offs.locator` (`many-to-one`)
  * `accountCreditBalance` → `accounts.locator` (`many-to-one`)
  * `accountExpenseBalance` → `accounts.locator` (`many-to-one`)
  * `invoiceCreditBalance` → `invoices.locator` (`many-to-one`)
  * `cash` → `accounts.locator` (`many-to-one`)
  * `creditCash` → `payments.locator` (`many-to-one`)
  * `charge` → `policy_element_charges.locator` (`many-to-one`)

***

<span id="ledger_account_line_items" />

ledger_account_line_items [#ledger_account_line_items]

**API Reference:** [Accounting API](/api/accounting)

**Primary Key:** `tenant_locator`, `reference_type`, `reference_locator`, `ordering_number`

| Column Name                  | Type            | Nullable | Attributes            | Description                                                                                                                                | Possible Values                                                                                                                                                          |
| ---------------------------- | --------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                  | Unique identifier of the tenant (UUID)                                                                                                     |                                                                                                                                                                          |
| `reference_type`             | `char(68)`      | **no**   | `PK`, `Discriminator` | Reference type of the ledger account line item, with possible values listed as `referenceType` in <ApiLink name="LedgerAccountResponse" /> | `accountCreditBalance`, `invoiceCreditBalance`, `cash`, `creditCash`, `charge`, `credit`, `installmentItem`, `invoiceItem`, `account`, `policy`, `accountExpenseBalance` |
| `reference_locator`          | `char(26)`      | **no**   | `PK`, `Relationship`  | Identifier of the reference, with referenced entity defined by `reference_type` (ULID)                                                     |                                                                                                                                                                          |
| `ordering_number`            | `int(11)`       | **no**   | `PK`                  | Ordering number of the ledger account line item                                                                                            |                                                                                                                                                                          |
| `fa_transaction_locator`     | `char(26)`      | **no**   | `Relationship`        | Unique identifier of the financial accounting transaction (ULID)                                                                           |                                                                                                                                                                          |
| `fa_transaction_time_utc`    | `datetime(6)`   | **no**   |                       | Time in UTC the financial accounting transaction was created                                                                               |                                                                                                                                                                          |
| `fa_transaction_note`        | `varchar(128)`  | yes      |                       | Note associated with the financial accounting transaction                                                                                  |                                                                                                                                                                          |
| `accounting_type`            | `varchar(10)`   | **no**   |                       | Indicates the accounting side of the entry (`debit` or `credit`)                                                                           | `credit`, `debit`                                                                                                                                                        |
| `amount`                     | `decimal(19,3)` | **no**   |                       | Amount of the ledger account line item                                                                                                     |                                                                                                                                                                          |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                       | Time in UTC the record was created                                                                                                         |                                                                                                                                                                          |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`               | Time in UTC the record was last updated                                                                                                    |                                                                                                                                                                          |

**Relationships:**

* `reference_locator` *(depends on `reference_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `policy` → `policies.locator` (`many-to-one`)
  * `invoiceItem` → `invoice_items.locator` (`many-to-one`)
  * `installmentItem` → `installment_items.locator` (`many-to-one`)
  * `credit`:
    * `payments.locator` (`many-to-one`)
    * `credit_distributions.locator` (`many-to-one`)
    * `disbursements.locator` (`many-to-one`)
    * `write_offs.locator` (`many-to-one`)
  * `accountCreditBalance` → `accounts.locator` (`many-to-one`)
  * `accountExpenseBalance` → `accounts.locator` (`many-to-one`)
  * `invoiceCreditBalance` → `invoices.locator` (`many-to-one`)
  * `cash` → `accounts.locator` (`many-to-one`)
  * `creditCash` → `payments.locator` (`many-to-one`)
  * `charge` → `policy_element_charges.locator` (`many-to-one`)
* `fa_transaction_locator` → `fa_transactions.locator` (`many-to-one`)

***

<span id="fa_transactions" />

fa_transactions [#fa_transactions]

**API Reference:** [Accounting API](/api/accounting)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type           | Nullable | Attributes | Description                                                      | Possible Values |
| ---------------------------- | -------------- | -------- | ---------- | ---------------------------------------------------------------- | --------------- |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`       | Unique identifier of the tenant (UUID)                           |                 |
| `locator`                    | `char(26)`     | **no**   | `PK`       | Unique identifier of the financial accounting transaction (ULID) |                 |
| `transaction_time_utc`       | `datetime(6)`  | **no**   |            | Time in UTC the financial accounting transaction was created     |                 |
| `transaction_note`           | `varchar(128)` | yes      |            | Note associated with the financial accounting transaction        |                 |
| `currency`                   | `varchar(128)` | **no**   |            | Currency of the financial accounting transaction                 |                 |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |            | Time in UTC the record was created                               |                 |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`    | Time in UTC the record was last updated                          |                 |

***

<span id="fa_transaction_account_lines" />

fa_transaction_account_lines [#fa_transaction_account_lines]

**API Reference:** [Accounting API](/api/accounting)

**Primary Key:** `tenant_locator`, `fa_transaction_locator`, `ordering_number`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                                                                                     | Possible Values                                                                                                                                                          |
| ---------------------------- | --------------- | -------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                                                                          |                                                                                                                                                                          |
| `fa_transaction_locator`     | `char(26)`      | **no**   | `PK`, `Relationship` | Unique identifier of the financial accounting transaction (ULID)                                                                                                |                                                                                                                                                                          |
| `ordering_number`            | `int(11)`       | **no**   | `PK`                 | Ordering number of the financial accounting transaction account line                                                                                            |                                                                                                                                                                          |
| `reference_type`             | `char(68)`      | **no**   | `Discriminator`      | Reference type of the financial accounting transaction account line, with possible values listed as `referenceType` in <ApiLink name="LedgerAccountResponse" /> | `accountCreditBalance`, `invoiceCreditBalance`, `cash`, `creditCash`, `charge`, `credit`, `installmentItem`, `invoiceItem`, `account`, `policy`, `accountExpenseBalance` |
| `reference_locator`          | `char(26)`      | **no**   | `Relationship`       | Identifier of the reference, with referenced entity defined by `reference_type` (ULID)                                                                          |                                                                                                                                                                          |
| `accounting_type`            | `varchar(10)`   | **no**   |                      | Indicates the accounting side of the entry (`debit` or `credit`)                                                                                                | `credit`, `debit`                                                                                                                                                        |
| `amount`                     | `decimal(19,3)` | **no**   |                      | Amount of the financial accounting transaction account line                                                                                                     |                                                                                                                                                                          |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                                                                              |                                                                                                                                                                          |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                                                                         |                                                                                                                                                                          |

**Relationships:**

* `fa_transaction_locator` → `fa_transactions.locator` (`many-to-one`)
* `reference_locator` *(depends on `reference_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `policy` → `policies.locator` (`many-to-one`)
  * `invoiceItem` → `invoice_items.locator` (`many-to-one`)
  * `installmentItem` → `installment_items.locator` (`many-to-one`)
  * `credit`:
    * `payments.locator` (`many-to-one`)
    * `credit_distributions.locator` (`many-to-one`)
    * `disbursements.locator` (`many-to-one`)
    * `write_offs.locator` (`many-to-one`)
  * `accountCreditBalance` → `accounts.locator` (`many-to-one`)
  * `accountExpenseBalance` → `accounts.locator` (`many-to-one`)
  * `invoiceCreditBalance` → `invoices.locator` (`many-to-one`)
  * `cash` → `accounts.locator` (`many-to-one`)
  * `creditCash` → `payments.locator` (`many-to-one`)
  * `charge` → `policy_element_charges.locator` (`many-to-one`)

***

Claims Tables [#claims-tables]

* [fnols](#fnols)
* [fnol\_data\_extensions](#fnol_data_extensions)
* [claims](#claims)
* [claim\_data\_extensions](#claim_data_extensions)

<span id="fnols" />

fnols [#fnols]

**API Reference:** [FNOL API](/api/claims)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type           | Nullable | Attributes     | Description                                                                                      | Possible Values                                                       |
| ---------------------------- | -------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                           |                                                                       |
| `locator`                    | `char(26)`     | **no**   | `PK`           | Unique identifier of the first notice of loss or FNOL (UUID)                                     |                                                                       |
| `type`                       | `varchar(128)` | **no**   |                | The configured type of the FNOL                                                                  | *defined in configuration*                                            |
| `fnol_state`                 | `varchar(128)` | **no**   |                | Current state of the FNOL                                                                        | `draft`, `validated`, `onClaim`, `completed`, `rejected`, `discarded` |
| `account_locator`            | `char(26)`     | yes      | `Relationship` | Identifier of the account the FNOL is associated with (ULID), if any                             |                                                                       |
| `policy_locator`             | `char(26)`     | yes      | `Relationship` | Identifier of the policy the FNOL is associated with (ULID), if any                              |                                                                       |
| `segment_locator`            | `char(26)`     | yes      | `Relationship` | Identifier of the segment the FNOL is associated with (ULID), if any                             |                                                                       |
| `region`                     | `varchar(128)` | yes      |                | The region assigned to the FNOL, if any                                                          |                                                                       |
| `fnol_number`                | `varchar(128)` | yes      |                | The [custom number](/configuration/general-topics/entity-numbering) assigned to the FNOL, if any |                                                                       |
| `created_by`                 | `char(36)`     | **no**   |                | Identifier of the user that created the FNOL (UUID)                                              |                                                                       |
| `created_at_utc`             | `datetime(6)`  | **no**   |                | Time in UTC the FNOL was created                                                                 |                                                                       |
| `updated_by`                 | `char(36)`     | yes      |                | Identifier of the user that last updated the FNOL (UUID)                                         |                                                                       |
| `updated_at_utc`             | `datetime(6)`  | yes      |                | Time in UTC the FNOL was last updated                                                            |                                                                       |
| `incident_time_utc`          | `datetime(6)`  | yes      |                | Time in UTC when the incident occurred                                                           |                                                                       |
| `incident_timezone`          | `varchar(126)` | yes      |                | Timezone in which the incident occurred                                                          |                                                                       |
| `incident_summary`           | `longtext`     | yes      |                | Summary description of the incident                                                              |                                                                       |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                               |                                                                       |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                                          |                                                                       |

**Relationships:**

* `account_locator` → `accounts.locator` (`many-to-one`)
* `policy_locator` → `policies.locator` (`many-to-one`)
* `segment_locator` → `segments.locator` (`many-to-one`)

***

<span id="fnol_data_extensions" />

fnol_data_extensions [#fnol_data_extensions]

**API Reference:** [FNOL API](/api/claims)

**Primary Key:** `tenant_locator`, `fnol_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                          | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | ------------------------------------------------------------------------------------ | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                               |                            |
| `fnol_locator`               | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the FNOL the extension data is associated with (ULID)                  |                            |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                     |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the [extension data ](/configuration/data-extensions/overview) field | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                               | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                        |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                   |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                              |                            |

**Relationships:**

* `fnol_locator` → `fnols.locator` (`many-to-one`)

***

<span id="claims" />

claims [#claims]

**API Reference:** [FNOL API](/api/claims)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type           | Nullable | Attributes     | Description                                                | Possible Values            |
| ---------------------------- | -------------- | -------- | -------------- | ---------------------------------------------------------- | -------------------------- |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                     |                            |
| `locator`                    | `char(26)`     | **no**   | `PK`           | Unique identifier of the claim (ULID)                      |                            |
| `type`                       | `varchar(128)` | **no**   |                | The configured type of the claim                           | *defined in configuration* |
| `fnol_locator`               | `char(26)`     | yes      | `Relationship` | Identifier of the FNOL the claim is associated with (ULID) |                            |
| `created_by`                 | `char(36)`     | **no**   |                | Identifier of the user that created the claim (UUID)       |                            |
| `created_at_utc`             | `datetime(6)`  | **no**   |                | Time in UTC the claim was created                          |                            |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                | Time in UTC the record was created                         |                            |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                    |                            |

**Relationships:**

* `fnol_locator` → `fnols.locator` (`many-to-one`)

***

<span id="claim_data_extensions" />

claim_data_extensions [#claim_data_extensions]

**API Reference:** [FNOL API](/api/claims)

**Primary Key:** `tenant_locator`, `claim_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                          | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | ------------------------------------------------------------------------------------ | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                               |                            |
| `claim_locator`              | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the claim the extension data is associated with (ULID)                 |                            |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                     |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the [extension data ](/configuration/data-extensions/overview) field | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extensions data field                                               | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | yes      |                      | Indicates whether the record has been deleted                                        |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                   |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                              |                            |

**Relationships:**

* `claim_locator` → `claims.locator` (`many-to-one`)

***

Producer Management Tables [#producer-management-tables]

* [producers](#producers)
* [producer\_data\_extensions](#producer_data_extensions)
* [producer\_hierarchy](#producer_hierarchy)
* [producer\_codes](#producer_codes)
* [producer\_code\_data\_extensions](#producer_code_data_extensions)

<span id="producers" />

producers [#producers]

**API Reference:** [Producer Management API](/api/producer-management)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type          | Nullable | Attributes     | Description                                                 | Possible Values                                           |
| ---------------------------- | ------------- | -------- | -------------- | ----------------------------------------------------------- | --------------------------------------------------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`           | Unique identifier of the tenant (UUID)                      |                                                           |
| `locator`                    | `char(26)`    | **no**   | `PK`           | Unique identifier of the producer (ULID)                    |                                                           |
| `producer_state`             | `varchar(50)` | **no**   |                | Current state of the producer                               | `draft`, `validated`, `suspended`, `discarded`, `retired` |
| `producer_type`              | `varchar(50)` | **no**   |                | The configured type of the producer                         | *defined in configuration*                                |
| `parent_locator`             | `char(26)`    | yes      | `Relationship` | Identifier of the producer's parent producer (ULID), if any |                                                           |
| `created_by`                 | `char(36)`    | **no**   |                | Identifier of the user that created the producer (UUID)     |                                                           |
| `created_time_utc`           | `datetime(6)` | **no**   |                | Time in UTC the producer was created                        |                                                           |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                | Time in UTC the record was created                          |                                                           |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`        | Time in UTC the record was last updated                     |                                                           |

**Relationships:**

* `parent_locator` → `producers.locator` (`many-to-one`)

***

<span id="producer_data_extensions" />

producer_data_extensions [#producer_data_extensions]

**API Reference:** [Producer Management API](/api/producer-management)

**Primary Key:** `tenant_locator`, `producer_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                              | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                   |                            |
| `producer_locator`           | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the [producer](/features/producer-management/producers) the data is associated with (ULID) |                            |
| `producer_type`              | `varchar(50)`   | **no**   |                      | The configured type of the producer                                                                      | *defined in configuration* |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                                         |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the extension data field                                                                 | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extension data field                                                                    | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | **no**   |                      | Indicates whether the record has been deleted                                                            |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                       |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                  |                            |

**Relationships:**

* `producer_locator` → `producers.locator` (`many-to-one`)

***

<span id="producer_hierarchy" />

producer_hierarchy [#producer_hierarchy]

**API Reference:** [Producer Management API](/api/producer-management)

**Primary Key:** `tenant_locator`, `parent_locator`, `child_locator`

| Column Name                  | Type          | Nullable | Attributes           | Description                                                                  | Possible Values |
| ---------------------------- | ------------- | -------- | -------------------- | ---------------------------------------------------------------------------- | --------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                       |                 |
| `parent_locator`             | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of the parent producer in the hierarchy (ULID)                    |                 |
| `child_locator`              | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of the child producer in the hierarchy (ULID)                     |                 |
| `depth`                      | `int(11)`     | **no**   |                      | The number of levels between the parent and child producers in the hierarchy |                 |
| `deleted`                    | `tinyint(1)`  | **no**   |                      | Indicates whether the record has been deleted                                |                 |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                      | Time in UTC the record was created                                           |                 |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`              | Time in UTC the record was last updated                                      |                 |

**Relationships:**

* `parent_locator` → `producers.locator` (`many-to-one`)
* `child_locator` → `producers.locator` (`many-to-one`)

***

<span id="producer_codes" />

producer_codes [#producer_codes]

**API Reference:** [Producer Management API](/api/producer-management)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type           | Nullable | Attributes     | Description                                                                                                       | Possible Values                                           |
| ---------------------------- | -------------- | -------- | -------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`           | Unique identifier of the tenant (UUID)                                                                            |                                                           |
| `locator`                    | `char(26)`     | **no**   | `PK`           | Unique identifier of the producer code (ULID)                                                                     |                                                           |
| `producer_locator`           | `char(26)`     | **no**   | `Relationship` | Identifier of the [producer](/features/producer-management/producers) the producer code is associated with (ULID) |                                                           |
| `producer_code_state`        | `varchar(30)`  | **no**   |                | Current state of the producer code                                                                                | `draft`, `validated`, `suspended`, `discarded`, `retired` |
| `producer_code_type`         | `varchar(50)`  | **no**   |                | The configured type of the producer code                                                                          | *defined in configuration*                                |
| `producer_code`              | `varchar(128)` | yes      |                | The code value assigned to the producer code (if any)                                                             |                                                           |
| `created_by`                 | `char(36)`     | **no**   |                | Identifier of the user that created the producer code (UUID)                                                      |                                                           |
| `created_time_utc`           | `datetime(6)`  | **no**   |                | Time in UTC the producer code was created                                                                         |                                                           |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                | Time in UTC the record was created                                                                                |                                                           |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`        | Time in UTC the record was last updated                                                                           |                                                           |

**Relationships:**

* `producer_locator` → `producers.locator` (`many-to-one`)

***

<span id="producer_code_data_extensions" />

producer_code_data_extensions [#producer_code_data_extensions]

**API Reference:** [Producer Management API](/api/producer-management)

**Primary Key:** `tenant_locator`, `producer_code_locator`, `field_name_md5`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                                   | Possible Values            |
| ---------------------------- | --------------- | -------- | -------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                                        |                            |
| `producer_code_locator`      | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the [producer code](/features/producer-management/producers) the data is associated with (ULID) |                            |
| `producer_code_type`         | `varchar(50)`   | **no**   |                      | The configured type of the producer code                                                                      | *defined in configuration* |
| `producer_code`              | `varchar(128)`  | yes      |                      | The code value assigned to the producer code (if any)                                                         |                            |
| `field_name_md5`             | `char(32)`      | **no**   | `PK`                 | The MD5 hash of the `field_name`                                                                              |                            |
| `field_name`                 | `varchar(4096)` | **no**   |                      | The key name of the extension data field                                                                      | *defined in configuration* |
| `field_value`                | `varchar(1024)` | yes      |                      | The value of the extension data field                                                                         | *defined in configuration* |
| `deleted`                    | `tinyint(1)`    | **no**   |                      | Indicates whether the record has been deleted                                                                 |                            |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                                            |                            |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                                       |                            |

**Relationships:**

* `producer_code_locator` → `producer_codes.locator` (`many-to-one`)

***

Work Management Tables [#work-management-tables]

* [tasks](#tasks)
* [task\_history](#task_history)
* [task\_references](#task_references)
* [user\_associations](#user_associations)
* [user\_association\_history](#user_association_history)
* [user\_qualifications](#user_qualifications)

<span id="tasks" />

tasks [#tasks]

**API Reference:** [Work Management API](/api/work-management)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                  | Type            | Nullable | Attributes | Description                                                                                      | Possible Values                                    |
| ---------------------------- | --------------- | -------- | ---------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`       | Unique identifier of the tenant (UUID)                                                           |                                                    |
| `locator`                    | `char(26)`      | **no**   | `PK`       | Unique identifier of the task (ULID)                                                             |                                                    |
| `task_category`              | `varchar(128)`  | **no**   |            | The configured category of the task                                                              |                                                    |
| `task_type`                  | `varchar(128)`  | **no**   |            | The configured type of the task                                                                  | *defined in configuration*                         |
| `task_state`                 | `varchar(128)`  | **no**   |            | Current state of the task                                                                        | `active`, `pastDeadline`, `completed`, `cancelled` |
| `description`                | `varchar(2048)` | yes      |            | The description of the task, if any                                                              |                                                    |
| `task_number`                | `varchar(128)`  | yes      |            | The [custom number](/configuration/general-topics/entity-numbering) assigned to the task, if any |                                                    |
| `deadline_time_utc`          | `datetime(6)`   | yes      |            | Time in UTC of the task deadline                                                                 |                                                    |
| `assigned_to`                | `char(36)`      | yes      |            | Identifier of the user that the task is assigned to (UUID)                                       |                                                    |
| `completed_by`               | `char(36)`      | yes      |            | Identifier of the user that completed the task (UUID)                                            |                                                    |
| `completed_time_utc`         | `datetime(6)`   | yes      |            | Time in UTC the task was completed                                                               |                                                    |
| `created_by`                 | `char(36)`      | **no**   |            | Identifier of the user that created the task (UUID)                                              |                                                    |
| `created_time_utc`           | `datetime(6)`   | **no**   |            | Time in UTC the task was created                                                                 |                                                    |
| `updated_by`                 | `char(36)`      | yes      |            | Identifier of the user that last updated the task (UUID)                                         |                                                    |
| `updated_time_utc`           | `datetime(6)`   | yes      |            | Time in UTC the task was last updated                                                            |                                                    |
| `source`                     | `varchar(128)`  | yes      |            | Source of the task                                                                               |                                                    |
| `tag`                        | `varchar(128)`  | yes      |            | Tag of the task                                                                                  |                                                    |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |            | Time in UTC the record was created                                                               |                                                    |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`    | Time in UTC the record was last updated                                                          |                                                    |

***

<span id="task_history" />

task_history [#task_history]

**API Reference:** [Work Management API](/api/work-management)

**Primary Key:** `tenant_locator`, `task_locator`, `history_locator`

| Column Name                  | Type            | Nullable | Attributes           | Description                                                                                   | Possible Values                                    |
| ---------------------------- | --------------- | -------- | -------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| `tenant_locator`             | `char(36)`      | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                                        |                                                    |
| `task_locator`               | `char(26)`      | **no**   | `PK`, `Relationship` | Identifier of the task this history record belongs to (ULID)                                  |                                                    |
| `history_locator`            | `char(26)`      | **no**   | `PK`                 | Unique identifier of this history record of the task (ULID)                                   |                                                    |
| `task_state`                 | `varchar(128)`  | **no**   |                      | State of the task as of this history record                                                   | `active`, `pastDeadline`, `completed`, `cancelled` |
| `description`                | `varchar(2048)` | yes      |                      | The description of the task as of this history record, if any                                 |                                                    |
| `assigned_to`                | `char(36)`      | yes      |                      | Identifier of the user the task was assigned to as of this history record (UUID)              |                                                    |
| `deadline_time_utc`          | `datetime(6)`   | yes      |                      | Time in UTC of the task deadline as of this history record                                    |                                                    |
| `created_by`                 | `char(36)`      | **no**   |                      | Identifier of the user that created the task (UUID)                                           |                                                    |
| `created_time_utc`           | `datetime(6)`   | **no**   |                      | Time in UTC the task was created                                                              |                                                    |
| `updated_by`                 | `char(36)`      | yes      |                      | Identifier of the user that made this update (UUID)                                           |                                                    |
| `updated_time_utc`           | `datetime(6)`   | yes      |                      | Time in UTC this history record was recorded                                                  |                                                    |
| `completed_by`               | `char(36)`      | yes      |                      | Identifier of the user that completed the task, if completed as of this history record (UUID) |                                                    |
| `completed_time_utc`         | `datetime(6)`   | yes      |                      | Time in UTC the task was completed, if completed as of this history record                    |                                                    |
| `source`                     | `varchar(128)`  | yes      |                      | Source of the task                                                                            |                                                    |
| `tag`                        | `varchar(128)`  | yes      |                      | Tag of the task                                                                               |                                                    |
| `datalake_created_timestamp` | `datetime(6)`   | **no**   |                      | Time in UTC the record was created                                                            |                                                    |
| `datalake_updated_timestamp` | `datetime(6)`   | **no**   | `Index`              | Time in UTC the record was last updated                                                       |                                                    |

**Relationships:**

* `task_locator` → `tasks.locator` (`many-to-one`)

***

<span id="task_references" />

task_references [#task_references]

**API Reference:** [Work Management API](/api/work-management)

**Primary Key:** `tenant_locator`, `task_locator`, `reference_locator`, `reference_type`

| Column Name                     | Type           | Nullable | Attributes            | Description                                                                                                        | Possible Values                                                                                                              |
| ------------------------------- | -------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`                | `char(36)`     | **no**   | `PK`                  | Unique identifier of the tenant (UUID)                                                                             |                                                                                                                              |
| `task_locator`                  | `char(26)`     | **no**   | `PK`, `Relationship`  | Identifier of the task associated with the referenced entity (ULID)                                                |                                                                                                                              |
| `reference_locator`             | `char(26)`     | **no**   | `PK`, `Relationship`  | Identifier of the entity associated with the task, with referenced entity defined by `reference_type` (ULID)       |                                                                                                                              |
| `reference_type`                | `varchar(128)` | **no**   | `PK`, `Discriminator` | Type of the associated entity, with possible values listed as `referenceType` in <ApiLink name="TaskReference" />  | `account`, `quickQuote`, `quote`, `policy`, `transaction`, `invoice`, `underwritingFlag`, `payment`, `quoteGroup`, `inquiry` |
| `underwriting_flag_entity_type` | `varchar(128)` | yes      |                       | If `reference_type` = `underwritingFlag`, this indicates whether the flag is associated with a `quote` or `policy` | `quote`, `policy`                                                                                                            |
| `deleted`                       | `tinyint(1)`   | **no**   |                       | Indicates whether the record has been deleted                                                                      |                                                                                                                              |
| `datalake_created_timestamp`    | `datetime(6)`  | **no**   |                       | Time in UTC the record was created                                                                                 |                                                                                                                              |
| `datalake_updated_timestamp`    | `datetime(6)`  | **no**   | `Index`               | Time in UTC the record was last updated                                                                            |                                                                                                                              |

**Relationships:**

* `task_locator` → `tasks.locator` (`many-to-one`)
* `reference_locator` *(depends on `reference_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `quote` → `quotes.locator` (`many-to-one`)
  * `quickQuote` → `quotes.locator` (`many-to-one`)
  * `policy` → `policies.locator` (`many-to-one`)
  * `transaction` → `transactions.locator` (`many-to-one`)
  * `invoice` → `invoices.locator` (`many-to-one`)
  * `payment` → `payments.locator` (`many-to-one`)
  * `underwritingFlag` *(depends on `underwriting_flag_entity_type`)*:
    * `policy` → `policy_element_underwriting_flags.locator` (`many-to-one`)
    * `quote` → `quote_element_underwriting_flags.locator` (`many-to-one`)
  * `inquiry` → *(no table)*
  * `quoteGroup` → *(no table)*

***

<span id="user_associations" />

user_associations [#user_associations]

**API Reference:** [Work Management API](/api/work-management)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                     | Type           | Nullable | Attributes      | Description                                                                                                         | Possible Values                                                                                                              |
| ------------------------------- | -------------- | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`                | `char(36)`     | **no**   | `PK`            | Unique identifier of the tenant (UUID)                                                                              |                                                                                                                              |
| `locator`                       | `char(26)`     | **no**   | `PK`            | Identifier of the user association record (ULID)                                                                    |                                                                                                                              |
| `user_locator`                  | `char(36)`     | **no**   |                 | Identifier of the user given the association (UUID)                                                                 |                                                                                                                              |
| `user_association_role`         | `varchar(128)` | **no**   |                 | The role given to the user as part of the association                                                               |                                                                                                                              |
| `user_association_state`        | `varchar(64)`  | **no**   |                 | The current state of the user association                                                                           | `active`, `completed`, `disassociated`, `discarded`                                                                          |
| `reference_locator`             | `char(26)`     | **no**   | `Relationship`  | Identifier of the entity that is part of the association, with referenced entity defined by `reference_type` (ULID) |                                                                                                                              |
| `reference_type`                | `varchar(128)` | **no**   | `Discriminator` | Type of the associated entity, with possible values listed as `referenceType` in <ApiLink name="UserAssociation" /> | `account`, `quickQuote`, `quote`, `policy`, `transaction`, `invoice`, `underwritingFlag`, `payment`, `quoteGroup`, `inquiry` |
| `underwriting_flag_entity_type` | `varchar(128)` | yes      |                 | If `reference_type` = `underwritingFlag`, this indicates whether the flag is associated with a `quote` or `policy`  | `quote`, `policy`                                                                                                            |
| `created_by`                    | `char(36)`     | **no**   |                 | Identifier of the user that created the user association (UUID)                                                     |                                                                                                                              |
| `created_time_utc`              | `datetime(6)`  | **no**   |                 | Time in UTC the user association was created                                                                        |                                                                                                                              |
| `updated_by`                    | `char(36)`     | yes      |                 | Identifier of the user that last updated the user association (UUID)                                                |                                                                                                                              |
| `updated_time_utc`              | `datetime(6)`  | yes      |                 | Time in UTC the user association was last updated                                                                   |                                                                                                                              |
| `datalake_created_timestamp`    | `datetime(6)`  | **no**   |                 | Time in UTC the record was created                                                                                  |                                                                                                                              |
| `datalake_updated_timestamp`    | `datetime(6)`  | **no**   | `Index`         | Time in UTC the record was last updated                                                                             |                                                                                                                              |

**Relationships:**

* `reference_locator` *(depends on `reference_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `quote` → `quotes.locator` (`many-to-one`)
  * `quickQuote` → `quotes.locator` (`many-to-one`)
  * `policy` → `policies.locator` (`many-to-one`)
  * `transaction` → `transactions.locator` (`many-to-one`)
  * `invoice` → `invoices.locator` (`many-to-one`)
  * `payment` → `payments.locator` (`many-to-one`)
  * `underwritingFlag` *(depends on `underwriting_flag_entity_type`)*:
    * `policy` → `policy_element_underwriting_flags.locator` (`many-to-one`)
    * `quote` → `quote_element_underwriting_flags.locator` (`many-to-one`)
  * `inquiry` → *(no table)*
  * `quoteGroup` → *(no table)*

***

<span id="user_association_history" />

user_association_history [#user_association_history]

**API Reference:** [Work Management API](/api/work-management)

**Primary Key:** `tenant_locator`, `user_association_locator`, `history_locator`

| Column Name                  | Type          | Nullable | Attributes           | Description                                                              | Possible Values                                     |
| ---------------------------- | ------------- | -------- | -------------------- | ------------------------------------------------------------------------ | --------------------------------------------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`                 | Unique identifier of the tenant (UUID)                                   |                                                     |
| `user_association_locator`   | `char(26)`    | **no**   | `PK`, `Relationship` | Identifier of the user association this history record belongs to (ULID) |                                                     |
| `history_locator`            | `char(26)`    | **no**   | `PK`                 | Unique identifier of this history record of the user association (ULID)  |                                                     |
| `user_locator`               | `char(36)`    | **no**   |                      | Identifier of the user given the association (UUID)                      |                                                     |
| `user_association_state`     | `varchar(64)` | **no**   |                      | State of the user association as of this history record                  | `active`, `completed`, `disassociated`, `discarded` |
| `created_by`                 | `char(36)`    | **no**   |                      | Identifier of the user that created the user association (UUID)          |                                                     |
| `created_time_utc`           | `datetime(6)` | **no**   |                      | Time in UTC the user association was created                             |                                                     |
| `updated_by`                 | `char(36)`    | yes      |                      | Identifier of the user that made this update (UUID)                      |                                                     |
| `updated_time_utc`           | `datetime(6)` | yes      |                      | Time in UTC this history record was recorded                             |                                                     |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |                      | Time in UTC the record was created                                       |                                                     |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`              | Time in UTC the record was last updated                                  |                                                     |

**Relationships:**

* `user_association_locator` → `user_associations.locator` (`many-to-one`)

***

<span id="user_qualifications" />

user_qualifications [#user_qualifications]

**API Reference:** [Work Management API](/api/work-management)

**Primary Key:** `tenant_locator`, `user_locator`, `qualification_category`, `qualification_level`

| Column Name                  | Type          | Nullable | Attributes | Description                                                             | Possible Values |
| ---------------------------- | ------------- | -------- | ---------- | ----------------------------------------------------------------------- | --------------- |
| `tenant_locator`             | `char(36)`    | **no**   | `PK`       | Unique identifier of the tenant (UUID)                                  |                 |
| `user_locator`               | `char(36)`    | **no**   | `PK`       | Unique identifier of the user (UUID)                                    |                 |
| `qualification_category`     | `varchar(64)` | **no**   | `PK`       | The configured category of the qualification level assigned to the user |                 |
| `qualification_level`        | `varchar(64)` | **no**   | `PK`       | The qualification level assigned to the user                            |                 |
| `deleted`                    | `tinyint(1)`  | **no**   |            | Time in UTC the claim was created                                       |                 |
| `datalake_created_timestamp` | `datetime(6)` | **no**   |            | Time in UTC the record was created                                      |                 |
| `datalake_updated_timestamp` | `datetime(6)` | **no**   | `Index`    | Time in UTC the record was last updated                                 |                 |

***

Auxiliary Data Tables [#auxiliary-data-tables]

* [aux\_data](#aux_data)
* [diaries](#diaries)

<span id="aux_data" />

aux_data [#aux_data]

**API Reference:** [Aux Data API](/api/aux-data/aux-data)

**Primary Key:** `tenant_locator`, `locator`, `key_name`

| Column Name                  | Type           | Nullable | Attributes | Description                                                                                              | Possible Values                |
| ---------------------------- | -------------- | -------- | ---------- | -------------------------------------------------------------------------------------------------------- | ------------------------------ |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`       | Unique identifier of the tenant (UUID)                                                                   |                                |
| `locator`                    | `varchar(64)`  | **no**   | `PK`       | User-defined identifier for grouping auxiliary data keys (e.g., an entity locator or `global`)           |                                |
| `key_name`                   | `varchar(126)` | **no**   | `PK`       | Name of the auxiliary data key, unique within the given `locator`                                        |                                |
| `var_value`                  | `longtext`     | **no**   |            | Value assigned to the auxiliary data key, stored as text                                                 |                                |
| `ui_type`                    | `varchar(64)`  | **no**   |            | Indicates how the auxiliary data should appear in the UI; value may be `normal`, `readonly`, or `hidden` | `normal`, `hidden`, `readonly` |
| `created_time_utc`           | `datetime(6)`  | **no**   |            | Time in UTC the auxiliary data was created                                                               |                                |
| `updated_time_utc`           | `datetime(6)`  | **no**   |            | Time in UTC the auxiliary data was last updated                                                          |                                |
| `updated_by`                 | `char(36)`     | yes      |            | Identifier of the user who created the auxiliary data (UUID)                                             |                                |
| `expiration_time_utc`        | `datetime(6)`  | yes      |            | Time in UTC the auxiliary data expires                                                                   |                                |
| `aux_data_settings_name`     | `varchar(128)` | yes      |            | Name of the settings that apply to the auxiliary data                                                    |                                |
| `deleted`                    | `tinyint(1)`   | yes      |            | Indicates whether the record has been deleted                                                            |                                |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |            | Time in UTC the record was created                                                                       |                                |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`    | Time in UTC the record was last updated                                                                  |                                |

***

<span id="diaries" />

diaries [#diaries]

**API Reference:** [Diary API](/api/aux-data/diary)

**Primary Key:** `tenant_locator`, `locator`

| Column Name                     | Type           | Nullable | Attributes      | Description                                                                                                                 | Possible Values                                                                                                                           |
| ------------------------------- | -------------- | -------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `tenant_locator`                | `char(36)`     | **no**   | `PK`            | Unique identifier of the tenant (UUID)                                                                                      |                                                                                                                                           |
| `locator`                       | `char(26)`     | **no**   | `PK`            | Identifier of the diary entry                                                                                               |                                                                                                                                           |
| `reference_locator`             | `char(26)`     | **no**   | `Relationship`  | Identifier of the entity that is associated with the diary entry, with referenced entity defined by `reference_type` (ULID) |                                                                                                                                           |
| `reference_type`                | `varchar(32)`  | **no**   | `Discriminator` | Type of the associated entity, with possible values listed as `referenceType` in <ApiLink name="DiaryEntryResponse" />      | `quote`, `policy`, `transaction`, `task`, `fnol`, `invoice`, `account`, `underwritingFlag`, `payment`, `quoteGroup`, `inquiry`, `element` |
| `underwriting_flag_entity_type` | `varchar(128)` | yes      |                 | If `reference_type` = `underwritingFlag`, this indicates whether the flag is associated with a `quote` or `policy`          | `quote`, `policy`                                                                                                                         |
| `diary_state`                   | `varchar(50)`  | **no**   |                 | Current state of the diary, with possible values listed as `diaryState` in <ApiLink name="DiaryEntryResponse" />            | `active`, `discarded`                                                                                                                     |
| `diary_category`                | `varchar(256)` | yes      |                 | An optional category that can be given to a diary entry                                                                     |                                                                                                                                           |
| `contents`                      | `longtext`     | **no**   |                 | Contents of the diary entry, stored as text                                                                                 |                                                                                                                                           |
| `created_by`                    | `char(36)`     | **no**   |                 | Identifier of the user that created the diary entry (UUID)                                                                  |                                                                                                                                           |
| `created_time_utc`              | `datetime(6)`  | **no**   |                 | Time in UTC the diary entry was created                                                                                     |                                                                                                                                           |
| `updated_by`                    | `char(36)`     | **no**   |                 | Identifier of the user that last updated the diary entry (UUID)                                                             |                                                                                                                                           |
| `updated_time_utc`              | `datetime(6)`  | **no**   |                 | Time in UTC the diary entry was last updated                                                                                |                                                                                                                                           |
| `datalake_created_timestamp`    | `datetime(6)`  | **no**   |                 | Time in UTC the record was created                                                                                          |                                                                                                                                           |
| `datalake_updated_timestamp`    | `datetime(6)`  | **no**   | `Index`         | Time in UTC the record was last updated                                                                                     |                                                                                                                                           |

**Relationships:**

* `reference_locator` *(depends on `reference_type`)*:
  * `account` → `accounts.locator` (`many-to-one`)
  * `quote` → `quotes.locator` (`many-to-one`)
  * `policy` → `policies.locator` (`many-to-one`)
  * `transaction` → `transactions.locator` (`many-to-one`)
  * `invoice` → `invoices.locator` (`many-to-one`)
  * `payment` → `payments.locator` (`many-to-one`)
  * `fnol` → `fnols.locator` (`many-to-one`)
  * `task` → `tasks.locator` (`many-to-one`)
  * `underwritingFlag` *(depends on `underwriting_flag_entity_type`)*:
    * `policy` → `policy_element_underwriting_flags.locator` (`many-to-one`)
    * `quote` → `quote_element_underwriting_flags.locator` (`many-to-one`)
  * `quoteGroup` → *(no table)*
  * `inquiry` → *(no table)*
  * `element`:
    * `quote_elements.locator` (`many-to-one`)
    * `policy_segment_elements.static_locator` (`many-to-many`)

***

Moratoriums Tables [#moratoriums-tables]

* [moratoriums](#moratoriums)
* [moratorium\_elections](#moratorium_elections)
* [moratorium\_statuses](#moratorium_statuses)

<span id="moratoriums" />

moratoriums [#moratoriums]

**API Reference:** [Moratoriums API](/api/moratoriums)

**Primary Key:** `tenant_locator`, `moratorium_name`

| Column Name                  | Type           | Nullable | Attributes | Description                                                                                                                                                      | Possible Values                |
| ---------------------------- | -------------- | -------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`       | Unique identifier of the tenant (UUID)                                                                                                                           |                                |
| `moratorium_name`            | `varchar(128)` | **no**   | `PK`       | Unique name of the moratorium                                                                                                                                    |                                |
| `moratorium_type`            | `varchar(128)` | **no**   |            | The type of the moratorium                                                                                                                                       | *defined in configuration*     |
| `description`                | `varchar(512)` | yes      |            | The description of the moratorium                                                                                                                                |                                |
| `application_mode`           | `varchar(128)` | **no**   |            | Indicates whether the moratorium applies to all eligible policies or whether there is an option to opt in or out. Value may be `mandatory`, `optIn`, or `optOut` | `mandatory`, `optIn`, `optOut` |
| `effective_time_utc`         | `datetime(6)`  | **no**   |            | Time in UTC the moratorium takes effect                                                                                                                          |                                |
| `end_time_utc`               | `datetime(6)`  | yes      |            | Time in UTC the moratorium ends                                                                                                                                  |                                |
| `is_effective_time_waived`   | `tinyint(1)`   | yes      |            | Indicates whether eligible policies issued after the moratorium effective time are affected                                                                      |                                |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |            | Time in UTC the record was created                                                                                                                               |                                |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   |            | Time in UTC the record was last updated                                                                                                                          |                                |

***

<span id="moratorium_elections" />

moratorium_elections [#moratorium_elections]

**API Reference:** [Moratoriums API](/api/moratoriums)

**Primary Key:** `tenant_locator`, `entity_type`, `entity_locator`, `moratorium_name`

| Column Name                  | Type           | Nullable | Attributes            | Description                                                                                      | Possible Values   |
| ---------------------------- | -------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------ | ----------------- |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`                  | Unique identifier of the tenant (UUID)                                                           |                   |
| `moratorium_name`            | `varchar(128)` | **no**   | `PK`, `Relationship`  | Unique name of the moratorium                                                                    |                   |
| `entity_type`                | `varchar(128)` | **no**   | `PK`, `Discriminator` | The type of the entity associated with the moratorium election. Value may be `quote` or `policy` | `quote`, `policy` |
| `entity_locator`             | `char(26)`     | **no**   | `PK`, `Relationship`  | The locator of the entity associated with the moratorium election (ULID)                         |                   |
| `election`                   | `varchar(128)` | **no**   |                       | The election made for the moratorium. Value may be `optIn` or `optOut`                           | `optIn`, `optOut` |
| `is_deleted`                 | `tinyint(1)`   | **no**   |                       | Indicates whether the record has been deleted                                                    |                   |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                       | Time in UTC the record was created                                                               |                   |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`               | Time in UTC the record was last updated                                                          |                   |

**Relationships:**

* `moratorium_name` → `moratoriums.moratorium_name` (`many-to-one`)
* `entity_locator` *(depends on `entity_type`)*:
  * `policy` → `policies.locator` (`many-to-one`)
  * `quote` → `quotes.locator` (`many-to-one`)

***

<span id="moratorium_statuses" />

moratorium_statuses [#moratorium_statuses]

**API Reference:** [Moratoriums API](/api/moratoriums)

**Primary Key:** `tenant_locator`, `moratorium_name`, `entity_type`, `entity_locator`

| Column Name                  | Type           | Nullable | Attributes            | Description                                                                                                                                                      | Possible Values                |
| ---------------------------- | -------------- | -------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| `tenant_locator`             | `char(36)`     | **no**   | `PK`                  | Unique identifier of the tenant (UUID)                                                                                                                           |                                |
| `moratorium_name`            | `varchar(128)` | **no**   | `PK`, `Relationship`  | Unique name of the moratorium                                                                                                                                    |                                |
| `entity_type`                | `varchar(128)` | **no**   | `PK`, `Discriminator` | The type of the entity associated with the moratorium status. Value may be `quote` or `policy`                                                                   | `quote`, `policy`              |
| `entity_locator`             | `char(26)`     | **no**   | `PK`, `Relationship`  | The locator of the entity associated with the moratorium status (ULID)                                                                                           |                                |
| `is_applicable`              | `tinyint(1)`   | **no**   |                       | Indicates whether the moratorium is applicable to the associated entity                                                                                          |                                |
| `is_eligible`                | `tinyint(1)`   | **no**   |                       | Indicates whether the associated entity is eligible for the moratorium                                                                                           |                                |
| `is_in_scope`                | `tinyint(1)`   | **no**   |                       | Indicates whether the associated entity is governed by the moratorium based on both applicability and eligibility                                                |                                |
| `application_mode`           | `varchar(128)` | **no**   |                       | Indicates whether the moratorium applies to all eligible policies or whether there is an option to opt in or out. Value may be `mandatory`, `optIn`, or `optOut` | `mandatory`, `optIn`, `optOut` |
| `datalake_created_timestamp` | `datetime(6)`  | **no**   |                       | Time in UTC the record was created                                                                                                                               |                                |
| `datalake_updated_timestamp` | `datetime(6)`  | **no**   | `Index`               | Time in UTC the record was last updated                                                                                                                          |                                |

**Relationships:**

* `moratorium_name` → `moratoriums.moratorium_name` (`many-to-one`)
* `entity_locator` *(depends on `entity_type`)*:
  * `policy` → `policies.locator` (`many-to-one`)
  * `quote` → `quotes.locator` (`many-to-one`)

***

See Also [#see-also]

* [Reporting Overview](/features/reporting/reporting-overview)
* [Data Lake Data Model](/features/reporting/data-model)
* [Data Lake Database](/features/reporting/datalake)
* [Data Lake Delta Files](/features/reporting/delta-files)
