Skip to main content
POST
cURL
Creates a single policy without a file upload. Only policyNumber and riskStateCode are required. Everything else is optional and can be added later with Update Policy.
A policy record in Turris represents bound business. The available currentStatus values (bound, active, expired, cancelled, non renewed) are all lifecycle states after binding, so there is no quote or pre-bind state. policyNumber is required because it is the grouping key that ties transactions together, not because Turris re-checks that the policy is bound.

Descriptive fields and association ids

Most fields on this endpoint are descriptive: the raw values your system already holds, stored verbatim on the policy record. Two fields are different. downstreamEntityAssociationId and productId are association ids, meaning Turris record ids that create a hard link between the policy and an entity you already have in Turris. The distinction matters because compliance work runs on the links, not on the strings. Turris can only check whether an agency was licensed and appointed in the risk state on the effective date once the policy is linked to a specific downstream entity association. An agency name on its own is text. You can supply either kind, or both. They do different jobs.

Identifying the agency

Get the downstreamEntityAssociationId from List Associations. It resolves internally to the downstream entity and the upstream/downstream association pair. Send the id when you have it. It is exact, immediate, and immune to spelling drift. If your system stores a Turris association id against each agency, send it on every create. Send the descriptive fields when you do not. A policy created without an association id is stored with entityMatchStatus = unmatched, and a later matching run resolves it against your downstream entity roster in this order:
  1. A previously confirmed mapping for that normalized agency name
  2. producerCode
  3. agencyNpn, then the generic npn
  4. agencyFein
  5. agencyLicenseNumber combined with agencyLicensedStateCode
  6. Exact agency name against legal name or DBA
  7. Normalized agency name, ignoring suffixes such as Inc, LLC, Ltd, Corp
Anything the deterministic layers cannot settle goes to AI matching against your agency roster. Anything still unresolved is flagged for manual review in the Turris app. Send both when you can. They do not conflict. The association id governs the link; the descriptive fields are still stored, and they are what a reviewer reads on the policy, what name-based filters query, and what the matcher falls back to if the association is ever cleared. Sending the name alongside the id costs nothing and makes the record legible.

Identifying the product

The same split applies. Get productId from List Products. If your upstream entity has exactly one product, matching assigns it automatically after the agency match and no product matching is needed.

Carrier and agent fields

carrierName, agentName, agentNpn, agentLicenseNumber, agentLicensedState, producerName, lineOfBusiness, insuredEntityName, filingNumber, slaNumber and externalBillingId are all descriptive. There is no carrier association id on this endpoint. Agent fields feed agent matching during a matching run but are never required at create time.

Creating a policy before you have every detail

No descriptive field is required, so a partial create is a supported flow rather than a workaround. A common pattern is to create the policy as soon as the policy number and risk state are known, then PATCH in premium, coverage limits, product and agency details as they land. Get policyNumber and riskStateCode right at create time. They are the two required fields, and they are also the two Update Policy does not accept, so neither can be changed afterwards. createInitialTransaction is likewise create-only; attach later transactions with Create Transaction instead. Every other field on this endpoint can be set later through PATCH, and passing null for an association id clears it and resets that match status to unmatched.
Creating a policy through this endpoint does not by itself queue a matching run. Policies created with entityMatchStatus = unmatched stay unmatched until matching is started from the Turris app, or until you attach the association explicitly with Update Policy. If your integration cannot supply downstreamEntityAssociationId, expect an operator to run matching on the unmatched queue.
currentStatus defaults to bound and is recomputed from transactions once any are attached. See Create Transaction.

Creating the initial transaction

By default the policy is created transaction-less (transactionCount = 0). Set createInitialTransaction to true to atomically create the policy’s first transaction alongside it in one operation. The transaction is inferred, not supplied: When the flag is true, transactionCount becomes 1, latestTransactionId points at the new transaction, and currentStatus is derived from that transaction rather than the request body. Both writes commit together; either one failing rolls back the whole request. Defaults to false when omitted, leaving the create behavior unchanged.

Response Shape

All successful responses are wrapped in the standard response envelope. See Request/Response Conventions.

Error Scenarios

Bad Request (400)

Returned when the body fails validation (missing policyNumber or riskStateCode, invalid enum value, or malformed association id).

Association Not Found (404)

Returned when a supplied productId or downstreamEntityAssociationId does not exist for your upstream entity.

Duplicate Policy (409)

Returned when a policy with the same policyNumber already exists for your upstream entity.

Unauthorized (401)

Missing or invalid authentication token. See Authentication.

Idempotency

This endpoint supports idempotency. If you include an idempotency-key header, duplicate requests within 1 hour return the original response without creating a second policy. See Idempotency.

Headers

idempotency-key
string

UUID to ensure idempotent request processing

Example:

"550e8400-e29b-41d4-a716-446655440000"

x-idempotency-key
string

Alternative UUID header for idempotent request processing

Example:

"550e8400-e29b-41d4-a716-446655440000"

Body

application/json
policyNumber
string
required

Policy number that groups transactions into a single policy

Example:

"POL-2025-001"

riskStateCode
string
required

US state code where the risk is located

Example:

"CA"

currentStatus
enum<string>

Initial lifecycle status. Recomputed from transactions once any are attached; defaults to "bound".

Available options:
bound,
active,
expired,
cancelled,
non renewed
Example:

"bound"

insuredEntityName
string

Name of the insured party

Example:

"Example Corp"

agencyName
string

Agency name as your system holds it. Stored verbatim and used as the primary matching signal when downstreamEntityAssociationId is not supplied. Send both when you have the association id: the id creates the link, this field stays the human-readable label.

Example:

"Premier Insurance Agency"

carrierName
string

Insurance carrier name

Example:

"National Insurance Co"

effectiveDate
string

Policy effective date (ISO 8601)

Example:

"2025-01-15T00:00:00.000Z"

expiryDate
string

Policy expiration date (ISO 8601)

Example:

"2026-01-15T00:00:00.000Z"

premiumAmountInUSD
number

Premium amount in USD

Example:

5000

aggregateCoverageInUSD
number

Aggregate coverage limit in USD

Example:

1000000

coveragePerClaimInUSD
number

Per-claim coverage limit in USD

Example:

500000

lineOfBusiness
string

Line of business

Example:

"Commercial Lines"

licenseNumber
string

License number

Example:

"LIC-001"

npn
string

National Producer Number

Example:

"11223344"

producerName
string

Producing agent name

Example:

"Jon Doe"

producerCode
string

Producer identifier code

Example:

"PROD-001"

productName
string

Product name as your system holds it. Stored verbatim and used as a matching signal against your product catalogue when productId is not supplied.

Example:

"General Liability"

productCode
string

Product code

Example:

"GL-100"

filingNumber
string

Filing number

Example:

"FIL-2025-001"

slaNumber
string

SLA number

Example:

"SLA-2025-001"

externalBillingId
string

External billing identifier

Example:

"BILL-2025-001"

agencyNpn
string

Agency National Producer Number

Example:

"12345678"

agencyFein
string

Agency Federal Employer Identification Number

Example:

"12-3456789"

agencyLicenseNumber
string

Agency state license number

Example:

"ABC-123456"

agencyLicensedStateCode
string

State where the agency license was issued

Example:

"CA"

agentName
string

Individual agent name

Example:

"John Smith"

agentNpn
string

Agent National Producer Number

Example:

"87654321"

agentLicenseNumber
string

Agent state license number

Example:

"LIC-789012"

agentLicensedState
string

State where the agent license was issued

Example:

"TX"

productId
string

Product association. Stamps productMatchStatus = "user confirmed" when supplied.

Example:

"6650a1b2c3d4e5f6a7b8c9d0"

downstreamEntityAssociationId
string

Agency association - the downstreamEntityAssociationId from GET /downstream-entity-associations. Resolved to upstreamDownstreamAssociationId + downstreamEntityId; stamps entityMatchStatus = "user confirmed".

Example:

"6650a1b2c3d4e5f6a7b8c9d0"

createInitialTransaction
boolean

When true, atomically create the policy first transaction alongside the policy. The initial transaction is inferred as type "new", dated effectiveDate (or today when absent), and inherits the policy descriptive and confirmed-agency fields. transactionCount becomes 1 and currentStatus is derived from that transaction. Defaults to false.

Example:

true

Response

Policy created

data
object
required
requestId
string
required

Unique request identifier

Example:

"dev-2c5e7cf2-9acf-4c8c-ab2f-b81f39d775a8"

timestamp
string
required

Response timestamp

Example:

"2025-11-12T20:49:03.293Z"