Skip to content
guidewire-core-workflow-a logo

Guidewire PolicyCenter Workflow

guidewire-core-workflow-a

Automate the PolicyCenter account→submission→quote→bind→issue→endorse→renew pipeline including the failure paths — underwriting issues blocking bind, quotes expiring before bind, referrals stuck pending approval, and mid-term endorsements that trigger unexpected premium audit recalculation. Use w...

SKILL.md

Full skill instructions

Guidewire PolicyCenter Workflow

Overview

Drive the PolicyCenter policy lifecycle through Cloud API and survive the state-transition failures that derail naive automation. This is the workflow used by broker portals to quote-and-bind, by CRMs to push submissions, and by renewal jobs to issue out-of-cycle. Assumes guidewire-install-auth provides the bearer token and guidewire-sdk-patterns provides the retrying client with checksum round-trip.

Five production failures this skill prevents:

  1. Bind on a quote with open UW issues — quote API returns 200, the underwritingIssues[] array is non-empty, the client ignores it, bind returns 422 rule-violation.
  2. Bind on a stale quote — quotes expire (default 30 days). A submission left open over a holiday returns 422 quote-expired on bind.
  3. Orphaned submissions on partial failure — submission → quote succeeds, bind fails, no rollback; the submission sits in Quoted status forever, blocking the next attempt.
  4. Renewal outside the renewal window — calling renewal before the window opens (typically 60–90 days before expiration) returns 422 renewal-window-closed.
  5. Endorsement premium drift — mid-term endorsement recalculates premium against current rate plans, which may differ from the rate plan in force at policy inception. The numeric difference surprises downstream finance integrations.

Prerequisites

  • A working auth + SDK layer per guidewire-install-auth and guidewire-sdk-patterns (getToken(), patchResource(), paginate(), mapError())
  • Cloud API roles pc.account.write, pc.submission.write, pc.policy.write assigned to the integration's Service Application
  • Knowledge of which product code drives the workflow (e.g., PersonalAuto, BOPLine) — submission shape is product-specific
  • For renewal jobs: read access to the renewal-window configuration on the relevant product

Instructions

Build the workflow as discrete state-transition functions, each fully responsible for surfacing the failure modes of its transition. Compose them with explicit checkpoints — never collapse the pipeline into a single fire-and-forget call.

1. Create the account

const idempotencyKey = crypto.randomUUID();
const account = await retryable(async () => {
  const res = await fetch(`${BASE}/​pc/​rest/​v1/​accounts`, {
    method: "POST",
    headers: { Authorization: `Bearer ${await getToken()}`, "Content-Type": "application/​json", "Idempotency-Key": idempotencyKey },
    body: JSON.stringify({ data: { attributes: { accountHolderContact: contact, primaryLocation: address } } }),
  });
  if (!res.ok) throw await mapError(res, "POST", "/​pc/​rest/​v1/​accounts");
  return (await res.json()).data;
});

The Idempotency-Key prevents duplicate accounts on retry. Persist account.attributes.accountNumber and the resource id immediately — both are needed downstream and the resource id is not derivable from the number.

2. Create the submission against the account

Submission is product-specific; its attributes shape varies. Read the product's submission schema from the API reference rather than hardcoding fields. The submission moves to Draft on creation.

const submission = await createSubmission(account.attributes.id, {
  productCode: "PersonalAuto",
  effectiveDate: "2026-06-01",
});

3. Quote the submission and inspect underwriting issues

The most-skipped step in naive automation. The quote response embeds underwritingIssues[]; non-empty with blocksBind: true means bind will fail.

const quoted = await fetch(`${BASE}/​pc/​rest/​v1/​jobs/​${submission.attributes.id}/​quote`, {
  method: "POST",
  headers: { Authorization: `Bearer ${await getToken()}`, "Idempotency-Key": idempotencyKey },
});
const body = (await quoted.json()).data;
const blockingIssues = body.attributes.underwritingIssues?.filter((u: any) => u.blocksBind) ?? [];
if (blockingIssues.length) {
  await routeToReferralQueue(submission, blockingIssues);
  return { status: "referred", issues: blockingIssues };
}

Some UW issues are informational and bind succeeds anyway; check the boolean per issue, not the array length. Surface blocking issues to the manual review queue with the originating actor's identity so the underwriter has context.

4. Bind within the quote validity window

Quotes carry attributes.quoteExpirationDate. Past it, bind returns 422 quote-expired. Re-quote rather than retry.

if (new Date(body.attributes.quoteExpirationDate) < new Date()) {
  return retryQuoteAndBind(submission.attributes.id);
}
const bound = await bindSubmission(submission.attributes.id);

After bind, the submission status moves to Bound and a Policy resource is created. bound.attributes.policy.id is the canonical policy reference for issuance, endorsement, and renewal.

5. Issue (commit the bound policy to in-force)

Bind alone does not put the policy in force; issuance is a separate transition. A bound-but-not-issued policy is invisible to billing; downstream invoices will not generate.

const issued = await fetch(`${BASE}/​pc/​rest/​v1/​policies/​${bound.attributes.policy.id}/​issue`, {
  method: "POST",
  headers: { Authorization: `Bearer ${await getToken()}`, "Idempotency-Key": idempotencyKey },
});

6. Endorsement with premium-drift detection

const endorsement = await openEndorsement(policyId, effectiveDate);
const requoted = await quoteEndorsement(endorsement.attributes.id);
const oldPremium = currentPolicy.attributes.totalPremium;
const newPremium = requoted.attributes.totalPremium;
if (Math.abs(newPremium - oldPremium) > MATERIAL_DRIFT_THRESHOLD) {
  await emitPremiumDriftEvent({ policyId, oldPremium, newPremium, delta: newPremium - oldPremium });
}
const boundEndorsement = await bindEndorsement(endorsement.attributes.id);

Threshold is policy-dependent; finance teams typically want any drift over a few hundred dollars surfaced before bind. Do not silently bind material drifts — they show up as billing surprises.

7. Renewal within the renewal window

The renewal window is configured per product line. Hardcoding 60 days is wrong for any product with non-default settings; read the configuration or accept rejection from the API and respond to the renewal-window-closed error type.

const policy = await fetch(`${BASE}/​pc/​rest/​v1/​policies/​${policyId}`).then(r => r.json());
const expirationDate = new Date(policy.data.attributes.expirationDate);
const renewalWindowOpens = subDays(expirationDate, 60);
if (new Date() < renewalWindowOpens) throw new Error("renewal-window-not-yet-open");
const renewalJob = await fetch(`${BASE}/​pc/​rest/​v1/​policies/​${policyId}/​renew`, { method: "POST" });

Output

A complete PolicyCenter workflow integration ships with all of the following:

  • Discrete state-transition functions: createAccount, createSubmission, quoteSubmission, bindSubmission, issuePolicy, openEndorsement, bindEndorsement, renewPolicy — each handling its own failures.
  • A blocking-UW-issue check before every bind attempt that routes referrals to a manual-review queue rather than retrying.
  • Quote-expiry detection that re-quotes rather than retrying a stale quote.
  • Premium-drift detection on endorsement with a configurable threshold and a finance-integration event emission.
  • Idempotency-Keys generated once per logical operation (one per submission, one per endorsement, one per renewal cycle), reused across retries.
  • A submission/​policy state-transition log that captures every API response — debugging "why is this stuck" requires the full transition history.

Examples

Example 1 — End-to-end happy path

const account = await createAccount(contact, address);
const submission = await createSubmission(account.attributes.id, { productCode: "PersonalAuto", effectiveDate });
const quoted = await quoteSubmission(submission.attributes.id);
if (quoted.blockingIssues.length) return { status: "referred", issues: quoted.blockingIssues };
const bound = await bindSubmission(submission.attributes.id);
const issued = await issuePolicy(bound.attributes.policy.id);
return { status: "issued", policyNumber: issued.attributes.policyNumber };

Example 2 — Referred submission resumption

// Resume after underwriter approves the referral asynchronously
const submission = await getSubmission(submissionId);
if (submission.attributes.underwritingIssues.every(u => u.status === "Approved")) {
  const requoted = await quoteSubmission(submissionId); // re-quote required after referral resolution
  return await bindAndIssue(requoted);
}

Example 3 — Renewal with window check

const policy = await getPolicy(policyId);
const window = await getRenewalWindow(policy.attributes.productCode);
if (!isWithinWindow(policy.attributes.expirationDate, window)) {
  return { status: "deferred", reason: "renewal-window-not-yet-open", retryAfter: window.opensOn };
}
const renewal = await renewPolicy(policyId);
return { status: "renewed", newPolicyId: renewal.attributes.id };

Error Handling

ErrorCauseSolution
422 with errors[].type === "rule-violation" on bindunaddressed blocking UW issueinspect quoted.attributes.underwritingIssues; never retry; route to manual review
422 quote-expired on bindquote past quoteExpirationDatere-quote the submission; do not retry the bind directly
422 renewal-window-closedrenewal initiated outside the configured windowback off until the window opens; surface retryAfter to the caller
422 submission-state-invalidtrying to bind a submission still in Draftcall quote first; the state machine is enforced server-side
409 Conflict on PATCH of submissionanother job edited the submission concurrentlyuse patchResource() from guidewire-sdk-patterns to handle checksum round-trip
Bound policy never reaches In Forcebind was called but issue was notissue is a separate API call after bind — both are required
Endorsement premium differs materially from expectedrate plan changed between policy inception and endorsement effective datesurface the drift to finance before binding; do not silently absorb the delta
Submission stuck in Quoted after a failed bindpartial-failure orphanresume by checking underwritingIssues and re-attempting bind, or withdraw via the withdraw endpoint

For deeper coverage (custom product schemas, line-of-business-specific submission shapes, multi-policy bind, broker hierarchy authorization), see implementation guide and API reference.

See Also

  • guidewire-install-auth — bearer token and scope assignment for the workflow
  • guidewire-sdk-patterns — retrying client, checksum round-trip, idempotency, error mapping
  • guidewire-core-workflow-b — the equivalent FNOL→reserve→settle pipeline in ClaimCenter
  • guidewire-webhooks-integrations — listening to App Events that fire on bind, issue, and renewal transitions
  • guidewire-observability-and-incident-response — interpreting referral-queue depth and bind-failure signals in production

Resources

More skills from jeremylongshore

openrouter-compliance-review logo
jeremylongshore/claude-code-plugins-plus-skills

openrouter-compliance-review

Review OpenRouter integration for regulatory compliance (SOC2, GDPR,

2.8K 0
View
maintainx-data-handling logo
jeremylongshore/claude-code-plugins-plus-skills

maintainx-data-handling

Data synchronization, ETL patterns, and data management for MaintainX.

2.8K 0
View
groq-core-workflow-a logo
jeremylongshore/claude-code-plugins-plus-skills

groq-core-workflow-a

Execute Groq primary workflow: chat completions with tool use and JSON

2.8K 0
View
validating-csrf-protection logo
jeremylongshore/claude-code-plugins-plus-skills

validating-csrf-protection

Validate CSRF protection implementations for security gaps. Use when

2.8K 0
View
api-contract logo
jeremylongshore/claude-code-plugins-plus-skills

api-contract

Configure this skill should be used when the user asks about "API contract",

2.8K 0
View
ideogram-incident-runbook logo
jeremylongshore/claude-code-plugins-plus-skills

ideogram-incident-runbook

Execute Ideogram incident response with triage, mitigation, and postmortem.

2.8K 0
View
gamma-sdk-patterns logo
jeremylongshore/claude-code-plugins-plus-skills

gamma-sdk-patterns

Reusable patterns for the Gamma REST API (no SDK exists).

2.8K 0
View
deepgram-sdk-patterns logo
jeremylongshore/claude-code-plugins-plus-skills

deepgram-sdk-patterns

Apply production-ready Deepgram SDK patterns for TypeScript and Python.

2.8K 0
View
openrouter-upgrade-migration logo
jeremylongshore/claude-code-plugins-plus-skills

openrouter-upgrade-migration

Migrate to OpenRouter from direct provider APIs or upgrade between SDK/model

2.8K 0
View
openrouter-common-errors logo
jeremylongshore/claude-code-plugins-plus-skills

openrouter-common-errors

Diagnose and fix common OpenRouter API errors. Use when encountering

2.8K 0
View
linear-cost-tuning logo
jeremylongshore/claude-code-plugins-plus-skills

linear-cost-tuning

Optimize Linear API usage, reduce unnecessary calls, and maximize

2.8K 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View