Agent skill

Coterie Webhooks Skill

Receive and authenticate Coterie small business insurance webhooks. Use when setting up a Coterie webhook endpoint, checking the opt-in Authentication header (token <guid>), debugging 401s, or handling Coterie application, quote and policy updates such as Status ReadyToQuote or Pending.

Install this skill

npx skills add hookdeck/webhook-skills --skill coterie-webhooks


Coterie (small business commercial insurance API) sends real-time webhooks to a partner's server for three kinds of object: applications, quotes and policies. Payloads are not signed. The only authentication is an opt-in static header named Authentication.

When to Use This Skill

  • How do I receive Coterie webhooks?
  • How do I verify the Coterie Authentication: token <guid> header?
  • Does Coterie sign webhook payloads? (No: shared token header only)
  • Why does my Coterie webhook endpoint return 401?
  • How do I tell Coterie application, quote and policy webhooks apart?

Verification (core)

Ask your Coterie contact to enable the Authentication header (all optional headers are turned on by request only). Coterie then sends Authentication: token {guid}. The header is Authentication, not Authorization, and the key is the whole value including the token prefix:

const crypto = require('crypto');

// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
  const ha = crypto.createHash('sha256').update(String(a)).digest();
  const hb = crypto.createHash('sha256').update(String(b)).digest();
  return crypto.timingSafeEqual(ha, hb);
}

function verifyCoterieRequest(headers, expected = process.env.COTERIE_AUTHENTICATION) {
  if (!expected) return false;                 // never accept when unconfigured
  const received = headers['authentication'];  // full value, e.g. "token 1234-..."
  return Boolean(received) && safeEqual(received, expected);
}

Return 401 when this fails, 400 for a body that isn't a JSON object, and 200 once handled. Read the body raw (express.raw({ type: '*/*' })) so any content type works. Python and Next.js equivalents are in references/verification.md.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Webhook Types

Coterie's docs name three webhook actions but no event-type field. Tell them apart by the identifier key in the payload (the examples do this):

KindIdentifier keyDocumented status example
applicationapplicationId (no quoteId)Status: "ReadyToQuote"
quotequoteIdPolicyType, Premium, LineItems
policyPolicyIdStatus: "Pending", PolicyNumber

Quote payloads also carry applicationId, so check quoteId first.

Optional Headers

Also enabled on request: x-timeStamp (epoch milliseconds of the event), x-applicationId and x-leadId (your own id, passed in the application Metadata).

Environment Variables

COTERIE_AUTHENTICATION=token 00000000-0000-0000-0000-000000000000   # full header value

Local Development

npx hookdeck-cli listen 3000 coterie --path /webhooks/coterie

No account required. Give the printed URL to your Coterie contact as the webhook URL.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 3, 2026

View on GitHub →