Insurance coverage

Define the policies you require, open a monitor for a payee, import a certificate of insurance, link a coverage, and read compliance results.

Insurance monitoring checks that a Payee carries the policies you require. You describe the required policies in a monitor configuration. A monitor tracks one Payee against that configuration. The Payee uploads a certificate of insurance (COI), Wingspan extracts and verifies the policies into coverages, and the monitor validates them.

Read Compliance and verification first for the payer and payee rules shared by order-style resources.

Resources

ResourceWhat it is
InsuranceMonitorConfigurationThe policies you require, with limit floors. Reusable.
InsuranceMonitorOne payee's compliance with one configuration.
InsuranceImportOne uploaded COI going through extraction and verification.
InsuranceCoverageA verified policy the payee carries.

Endpoints

Scopes: compliance.monitor:read and :write for configurations and monitors, compliance.insurance:read and :write for coverages and imports.

1. Create a configuration

coverages is the substance. It has one entry per required policy, and policyType must be unique across entries. Each entry (AcceptedInsuranceCoverage) has:

FieldNotes
policyTypeRequired. One of GeneralLiability, OccupationalAccident, WorkersCompensation, ProfessionalLiability, ErrorsAndOmissions, CommercialAuto, DisabilityInsurance, CyberLiability, TechnologyErrorsAndOmissions, CommercialProperty, BusinessIncome, InlandMarine, UmbrellaLiability, ExcessLiability, ProfessionalIndemnity, PollutionLiability, CrimeInsurance, MedicalMalpractice, DirectorsAndOfficersLiability, EmploymentPracticesLiability, FiduciaryLiability, MediaLiability, PerformanceBond, PaymentBond, BidBond, MaintenanceBond, AutomobileLiability, BusinessOwnersPolicy, ContractorsPackagePolicy.
limitsMinimum limits. Each has limitType, amount, and currency. A coverage is compliant when it meets or exceeds every one.
appliedProvisionsEndorsements the policy must carry.
acceptedSourceTypesInsuranceImport (an uploaded certificate) and PlanEnrollment (a Wingspan master-policy enrollment). A configuration that omits PlanEnrollment won't accept one.
coverageForm, policySpecificAttributesOptional extra requirements.

limitType values include EachOccurrence, PerOccurrence, PerClaim, PerAccident, GeneralAggregate, ProductsCompletedOperationsAggregate, PolicyAggregate, CombinedSingleLimit, EmployersLiabilityEachAccident, and others; see the reference for the full list. The EL* spellings are legacy and still appear on older configurations.

curl -X POST https://api.wingspan.app/v3/compliance/insurance-monitor-configurations \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "externalId": "ins-standard",
    "coverages": [
      {
        "policyType": "GeneralLiability",
        "limits": [
          { "limitType": "EachOccurrence", "amount": 1000000, "currency": "USD" },
          { "limitType": "GeneralAggregate", "amount": 2000000, "currency": "USD" }
        ],
        "acceptedSourceTypes": ["InsuranceImport"]
      }
    ]
  }'

The response's id is what an InsuranceCoverage requirement definition passes as dataSourceId. There is no list route for configurations, so keep the id. coverages can't be changed after create, and PATCH accepts only externalId and metadata. To change what you require, create a new configuration and point the requirement definition at it. metadata merges key by key, and a key containing . or $ returns 422.

2. Open a monitor

POST /v3/compliance/insurance-monitors:

FieldTypeNotes
payerPayeeIdstring, requiredThe relationship.
configurationIdstringPayer only. The configuration to validate against.
requirementIdstringRequired for a payee.
externalIdstringPayer only.
metadataobjectPayer only.

A create that cites a requirementId returns the monitor that is still outstanding for that relationship and configuration. A payer's direct order, an externalId, and a payer reset open a new one.

A monitor has status (Pending, Monitoring, Complete, or ForceMatched), configurationId, coverageId once linked, minimumExpiresAt, and jobs. Each job is one validation result for one required policyType, with status (Pending, Complete, Failed, Warning) and a statusReason naming the limit, provision, or date that missed.

GET /v3/compliance/insurance-monitors/{monitorId} is readable by both parties. Add expand=Configuration or expand=Coverage to inline the related resource. Either is safe to send always. A monitor with no linked coverage comes back without the coverage key. Any other value returns 422. Expansions aren't available on list rows.

3. Import a certificate

The Payee uploads the COI as a vault file, then:

curl -X POST https://api.wingspan.app/v3/compliance/insurance-imports \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "fileId": "VAULT_FILE_ID", "insuranceMonitorId": "MONITOR_ID" }'

insuranceMonitorId is only a matching hint. Monitors evaluate on their own whether verified policies satisfy them. The import is owned by the account context of the request.

status is Created, Processing, ReadyForReview, Complete, or Failed. ReadyForReview means the certificate was parsed but needs review or more policy matching before it yields a verified coverage. Each import has attemptCount, maxAttempts, coverageIds, and jobs. A job has type (Extraction or Validation) and status. Extracted policy data is on jobs[].extractedFields, one entry per policy the certificate declares, since one ACORD 25 often carries several.

To fix a wrong file before submitting, PATCH the import with a new fileId. This re-runs extraction and uses another attempt. It works on a pending or rejected import. When the import has used maxAttempts, it returns 422 with detailCode compliance.InsuranceImportAttemptLimitExceeded.

POST .../submit sends a pending import for processing into a coverage and returns the import with its new status. externalId and metadata can only be set at create, because PATCH is the re-upload path.

4. Link a coverage to a monitor

The payee calls PATCH /v3/compliance/insurance-monitors/{monitorId} with { "coverageId": "COVERAGE_ID" } to say which of its policies satisfies the requirement. A payer gets 403. A caller who is neither party gets 404.

Read coverages

GET /v3/compliance/insurance-coverages lists coverages. Filters: policyType, sourceType, sourceId, policyNumber, status, effective and expiration date bounds, and accountIds. status (Active or Expired) is derived from expirationDate. Sort by createdAt (default, newest first), updatedAt, effectiveDate, or expirationDate.

A coverage has sourceType (InsuranceImport or PlanEnrollment), policyType, carrier, policyNumber, certificateHolder, namedInsured, effectiveDate, expirationDate, limits, appliedProvisions, isVerified, and warnings. A warning is a non-blocking import check that didn't pass.

Download the certificate

GET .../insurance-monitors/{monitorId}/certificate returns a 302 to a signed URL. For a browser page that can't follow a cross-site redirect from script, use .../certificate-url:

// 200 OK
{ "url": "https://files.example.com/signed-link", "expiresAt": "2026-11-02T18:05:00Z" }

Don't store the link. Call again when you need it. Both routes are payer-only. They return 404 when the caller isn't the payer, the monitor has no linked coverage, the coverage came from a plan enrollment rather than an upload, or the import has no file. They return 503 when no link could be issued.

Errors

StatusWhen
400A payee created a monitor without requirementId. Checked first.
403A payer links a coverage.
404No seat on payerPayeeId. A configuration or monitor you can't see.
409Duplicate externalId. Submit on an import in a state that can't be submitted.
422A payee monitor body with configurationId, externalId, or metadata alongside requirementId. A repeated policyType in coverages. An unsupported expand value. An import at its attempt limit.

Events

InsuranceMonitor.Created and Updated, InsuranceImport.Created, Processed, and Submitted, InsuranceCoverage.Created and Updated.


Did this page help you?