API reference

PolicyCancel Partner API

POST a cancellation with whatever you have, track it by case id, and receive HMAC-signed webhooks as the case moves from intake to a verified outcome.

Getting started

Base URL & authentication

Base URL: https://policycancel.com/api/v1 (use your deployment URL in sandbox).

Send every request with Authorization: Bearer pc_sand_… or pc_live_…. Keys are shown only once when created and may be revoked by a partner admin.

Cancellations

Create a cancellation

POST /cancellations accepts JSON. Unknown fields are allowed and retained verbatim. consumer.phone or consumer.email is required.

POST /api/v1/cancellations
{
  "external_ref": "ref-4711",
  "consumer": {
    "name": "Jordan Rivera",
    "phone": "+15125550123",
    "email": "jordan@example.com",
    "address": { "line1": "1 Main St", "city": "Austin", "state": "TX", "zip": "78701" },
    "dob": "1990-04-02",
    "timezone": "America/Chicago"
  },
  "new_policy": { "carrier": "Clearcover", "policy_number": "CC-991", "effective_date": "2026-07-15" },
  "prior_policies": [{ "carrier": "State Farm", "policy_number": "SF-123" }],
  "requested_cancel_date": "2026-07-15",
  "consent": { "contact_attested": true },
  "metadata": {}
}

A successful create returns HTTP 201:

201 Created
{
  "id": "uuid",
  "stage": "collecting_info",
  "case_url": "https://policycancel.com/dashboard/cases/uuid",
  "tracker_url": "https://policycancel.com/c/token",
  "sandbox": true
}

Store id as the PolicyCancel case ID in your CRM. case_url opens the partner dashboard for an authorized organization member, while tracker_urlis the consumer's private progress and action link.

Validation errors return 422 with error and actionable issues. Malformed JSON returns 400. Invalid or revoked keys return 401.

Idempotency

Retry safely

Add Idempotency-Key: <unique value> to safely retry a create. A replay returns the original response with HTTP 200. Reusing the key with a different JSON body returns 409, so the same request never double-opens a case.

Lifecycle

Read & withdraw

GET/cancellations/:id

Gets one partner-owned cancellation.

200 OK
{
  "id": "uuid",
  "stage": "completed_verified",
  "case_url": "https://policycancel.com/dashboard/cases/uuid",
  "tracker_url": "https://policycancel.com/c/token",
  "sandbox": true,
  "external_ref": "ref-4711",
  "requested_cancel_date": "2026-07-15",
  "new_policy": { "carrier": "Clearcover", "policy_number": "CC-991", "effective_date": "2026-07-15" },
  "created_at": "2026-07-14T18:30:00.000Z",
  "documents": [
    { "kind": "signed_form", "url": "https://policycancel.com/api/artifacts/artifact-uuid", "bytes": 48231, "created_at": "2026-07-15T20:10:00.000Z" }
  ]
}

documents is always an array and includes available signed_form, signature_certificate, and dec_page artifacts. Each URL downloads through the partner-authorized artifact route.

GET/cancellations?stage=collecting_info&page=1

Returns { data, page, page_size, total }; page size is 50.

POST/cancellations/:id/withdraw

Moves a non-terminal case to withdrawn and cancels pending timers and messages. Invalid transitions return 409.

Bulk

CSV intake

Use data/fixtures/intake-template.csv. The fixed header flattens the JSON fields. Import returns created cases plus row-numbered errors; valid rows are committed even when another row fails. external_ref supplies CSV retry idempotency.

Webhooks

Signed event delivery

Events, delivered as the case moves. Deliveries retry five times with exponential backoff.

case.stage_changedcase.needs_partner_actioncase.submittedcase.verifiedcase.unable_to_complete

The JSON envelope is { id, type, created_at, data }. The signature header is X-PolicyCancel-Signature: t=<unix>,v1=<hex>. Verify the raw request bytes before parsing:

verify.ts
const [tPart, v1Part] = signature.split(",");
const expected = hmacSha256(secret, `${tPart.slice(2)}.${rawBody}`);
timingSafeEqual(v1Part.slice(3), expected);

Reject timestamps outside your tolerance (five minutes is recommended) and compare digests in constant time. Return any 2xx status to acknowledge delivery.