REST API

Everything the dashboard does, from your own systems: upload policies, run a prior-vs-renewal check, and read the findings and diff summary. Included in the Agency plan.

Authentication

Create a key in Settings → API keys (owner only; shown once, stored hashed) and send it as a bearer token. Limits: 5,000 requests/day per organization, 10 active keys.

curl https://YOUR-DOMAIN/api/v1/checks \
  -H "Authorization: Bearer bindcheck_YOUR_KEY"

Errors are JSON: {"error": {"code": "...", "message": "..."}} with conventional status codes (401 bad/expired key, 403 plan limit or scope, 404, 429 rate limit).

Scopes & expiration

Keys are created as full access or read-only. Read-only keys can call every GET endpoint (list checks, poll a policy, read findings) but any POST/PATCH/DELETE returns 403 insufficient_scope — use them for dashboards, BI pulls and monitoring. Keys can optionally expire (90 days / 1 year) for rotation policies; an expired key returns 401 key_expired. Every API write is attributed to its key by label in the organization's activity log.

Policies

POST/api/v1/policies

Upload a policy PDF as multipart/form-data with a file field (8 MB max) and a role of prior, renewal, quote or policy. Returns 202 with the policy in processing — extraction (form schedule, dec-page limits/deductibles, endorsements) runs asynchronously.
curl -X POST https://YOUR-DOMAIN/api/v1/policies \
  -H "Authorization: Bearer bindcheck_YOUR_KEY" \
  -F "role=renewal" \
  -F "file=@renewal.pdf"

GET/api/v1/policies/:id

Poll after upload until status is done (parsed extraction populated: line of business, carrier, named insured, dates, the form schedule, and the declarations limits/deductibles) or error. Typically 15–60 seconds. Form entries carry number, edition and description only — never copyrighted form wording.

DELETE/api/v1/policies/:id

Delete the policy and its stored file. Irreversible.

Checks

POST/api/v1/checks

Create a check pairing a prior policy with a renewal or quote. Body: {"prior_policy_id": 12, "renewal_policy_id": 34, "kind": "renewal"}. Returns 201; once both policies are extracted the diff runs and the check moves to done. Returns 403 plan_limit at your plan's monthly check cap.

GET/api/v1/checks

List checks, newest first. Query params: status (processing, done, error), kind (renewal, quote), review_required, page, per_page (max 100).
{
  "data": [{
    "id": 87,
    "kind": "renewal",
    "status": "done",
    "review_required": true,
    "prior_policy_id": 12,
    "renewal_policy_id": 34,
    "summary": {
      "total": 6, "critical": 1, "warning": 3, "info": 2,
      "reviewRequired": true, "hasManuscript": true,
      "byCategory": { "removed": 1, "changed": 3, "missing": 1, "manuscript": 1 }
    },
    "created_at": "2026-07-11 18:22:05"
  }],
  "page": 1, "per_page": 25, "total": 41
}

GET/api/v1/checks/:id

One check with its diff summary.

GET/api/v1/checks/:id/findings

The findings for a check. Each finding carries severity (critical, warning, info), category (added, removed, changed, missing, manuscript, review), form_number, field_key, prior_value, renewal_value, description, remediation and verdict (open, dismissed, resolved).
{
  "data": [{
    "id": 5012,
    "severity": "critical",
    "category": "removed",
    "form_number": "CG 20 37",
    "field_key": "additional_insured_completed_ops",
    "prior_value": "CG 20 37 04 13",
    "renewal_value": null,
    "description": "Completed-operations additional insured endorsement present on the prior policy is not on the renewal.",
    "remediation": "Confirm with the carrier whether CG 20 37 was intended to drop; if the account requires completed-ops AI, request reinstatement.",
    "verdict": "open"
  }]
}

PATCH/api/v1/findings/:id

Update a finding's verdict (open, dismissed, resolved) as you work it.

Typical integration

  1. Push the prior and renewal PDFs with POST /policies, poll each until done.
  2. Create the check with POST /checks; poll the check until done.
  3. Read GET /checks/:id/findings and surface them (or gate delivery on summary.critical == 0 && !review_required).
  4. Write verdicts back with PATCH /findings/:id as your team works the renewal.

Outbound webhooks (check completed, critical finding opened) are planned — tell us if you need them and we'll prioritize.