API v1 · Read-only

COIflow API

A simple, read-only REST API for pulling your agency's certificates, coverage lines, and insureds into your AMS, BI tools, or internal dashboards.

Base URL

https://coiflow.app/api/public/v1

All responses are JSON. All times are ISO-8601 UTC. All endpoints are read-only (GET).

Authentication

Create a key under Settings → API in the COIflow app. Keys are scoped to your agency and show only once at creation — store them in your AMS or password manager immediately.

Pass your key in the Authorization header on every request:

curl https://coiflow.app/api/public/v1/health \
  -H "Authorization: Bearer coif_live_XXXXXXXXXXXXXXXXXXXXXXXX"

The X-API-Key header is also accepted for AMS connectors that don't support bearer auth.

Scopes: read:insureds, read:certificates, read:coverages. All three are granted by default. Rotate or revoke any key at any time; revocation takes effect within seconds.

Errors & status codes

  • 200 — success
  • 401 — missing, malformed, or revoked key
  • 403 — key is missing the required scope
  • 429 — rate limit exceeded (see below)
  • 500 — server error; safe to retry with backoff
{ "error": "Invalid or revoked API key." }

Rate limits

Hard limit of 120 requests per minute per agency across all API keys. Requests above the limit return 429 with Retry-After: 60.

Every response includes these headers so your client can self-throttle:

  • X-RateLimit-Limit — requests allowed per 60s window
  • X-RateLimit-Remaining — requests left in the current window
  • X-RateLimit-Reset — unix timestamp when the window resets

Every call is logged and visible to your agency owner under Settings → API → API request log, including status code, endpoint, duration, and the last error message — share this with COIflow support when troubleshooting AMS sync failures.

On 429 or 5xx, retry with exponential backoff (1s, 2s, 4s, 8s, max 60s) and respect any Retry-After header.

Pagination & incremental sync

All list endpoints accept limit (default 100, max 500) and offset. Responses include a pagination.next_offsetyou can pass back to fetch the next page, or null when complete.

For incremental sync, pass updated_since=2026-06-17T00:00:00Zon /insureds and /certificatesto receive only records modified after that timestamp.

Endpoints

GET/api/public/v1/healthread:certificates
Verify your key is valid. Returns the resolved agency id and granted scopes.
GET /api/public/v1/health
Authorization: Bearer coif_live_…

{
  "ok": true,
  "agency_id": "a1b2c3d4-…",
  "scopes": ["read:insureds","read:certificates","read:coverages"],
  "server_time": "2026-06-18T16:42:00.000Z"
}
GET/api/public/v1/insuredsread:insureds
List insureds (clients) for your agency, newest activity first.
Query parameters
  • limitnumber1–500, default 100
  • offsetnumberdefault 0
  • updated_sinceISO-8601only records modified at or after this time
GET /api/public/v1/insureds?limit=100&updated_since=2026-06-17T00:00:00Z

{
  "data": [{
    "id": "…",
    "business_name": "Riverside Builders LLC",
    "contact_name": "Sam Patel",
    "email": "ops@riverside.example",
    "phone": null,
    "worst_status": "verified",
    "compliance_score": 92,
    "missing_coverages": [],
    "created_at": "2026-04-02T14:11:09Z",
    "updated_at": "2026-06-18T13:02:00Z"
  }],
  "pagination": { "limit": 100, "offset": 0, "total": 217, "next_offset": 100 }
}
GET/api/public/v1/certificatesread:certificates
List active (non-archived) certificates for your agency.
Query parameters
  • insured_iduuidfilter to one insured
  • statusstringverified, expiring, gap, lapsed, needs_review
  • updated_sinceISO-8601incremental sync filter
  • limit / offsetnumberpagination
GET /api/public/v1/certificates?status=expiring

{
  "data": [{
    "id": "…",
    "insured_id": "…",
    "carrier": "Hartford",
    "cert_type": "General Liability",
    "status": "expiring",
    "reason": "Expires within 30 days",
    "certificate_holder": "Acme Holdings LLC",
    "expiration_date": "2026-07-04",
    "parse_confidence": 0.94,
    "parsed_at": "2026-06-12T09:13:22Z",
    "created_at": "2026-06-12T09:12:55Z",
    "updated_at": "2026-06-12T09:13:22Z"
  }],
  "pagination": { "limit": 100, "offset": 0, "total": 14, "next_offset": null }
}
GET/api/public/v1/coveragesread:coverages
List coverage lines (GL, Auto, WC, Umbrella, etc.) attached to your certificates.
Query parameters
  • insured_iduuidfilter to coverages under one insured
  • certificate_iduuidfilter to one certificate
  • limit / offsetnumberpagination
GET /api/public/v1/coverages?insured_id=…

{
  "data": [{
    "id": "…",
    "certificate_id": "…",
    "coverage_type": "general_liability",
    "policy_number": "GL-9912034",
    "effective_date": "2026-01-01",
    "expiration_date": "2027-01-01",
    "each_occurrence": 1000000,
    "aggregate": 2000000,
    "combined_single_limit": null,
    "additional_insured": true,
    "waiver_of_subrogation": false
  }],
  "pagination": { "limit": 100, "offset": 0, "total": 3, "next_offset": null }
}

AMS sync guide

COIflow's API is designed for safe polling on a schedule from your AMS or middleware. Follow this pattern and you'll stay well within rate limits with zero data loss.

  1. Pick a cadence. Hourly is plenty for most agencies. For near-real-time workflows, every 5 minutes is safe.
  2. Persist a cursor. Store the timestamp of your last successful sync (e.g. last_synced_at). Initialize it to a date well before your agency started using COIflow.
  3. Pull deltas. Call /insureds and /certificates with updated_since=<last_synced_at>, paginating with next_offset until it is null.
  4. Hydrate coverages. For each new or changed certificate, call /coverages?certificate_id=… (or insured_id=… if you prefer to refresh per-client).
  5. Commit the cursor. Only advance last_synced_atafter every page has been written to your AMS. If a step fails, you'll re-pull the same window on the next run — every endpoint is idempotent.
  6. Retry transient errors. Treat 429 and 5xx as retryable with exponential backoff (1s → 60s). Treat 401/403 as permanent — alert an admin to rotate the key.
  7. Set a sane User-Agent like "AcmeAgency-AMSSync/1.2" so we can help you debug if traffic ever looks off.
Reference loop (pseudocode)
cursor = read_cursor() or "2025-01-01T00:00:00Z"
now = utc_now_iso()

offset = 0
while true:
  res = GET "/api/public/v1/certificates?updated_since=" + cursor + "&offset=" + offset
  upsert_into_ams(res.data)
  if res.pagination.next_offset is null: break
  offset = res.pagination.next_offset

for cert in changed_certificates:
  cov = GET "/api/public/v1/coverages?certificate_id=" + cert.id
  upsert_coverages(cov.data)

write_cursor(now)

Need a connector for a specific AMS (AMS360, Applied Epic, HawkSoft, EZLynx, QQCatalyst)?Tell us what you need — we'll prioritize the most-requested platforms.

Manage keys in the app: Settings → API