Hillwinds APIDocs
For AI Agents

AI Agent Guide

The page to read first if you are an LLM, coding agent, or human author of one. Anti-pitfall guidance in one place; the autocomplete reference, recipe library, and endpoint index each have their own page.

Read this first

This page exists so you don't waste tokens re-discovering quirks the rest of us have already paid for. It is short on prose and long on tables, callouts, and copy-paste snippets. The per-resource API reference pages are the authoritative source for response shapes; this page is the authoritative source for what to avoid doing.

Three resources every agent should bookmark
  • This page — pitfalls + the discovery flow. Linked sub-pages for autocomplete, recipes, and the endpoint index (see below).
  • /llms.txt and /llms-full.txt — the docs site flattened for context windows. Page-level .md URLs are not served; fetch these files or use the in-page copy button instead.
  • /v1/openapi.json — canonical query parameter names + types + enums for every operation. Pair with this page (which covers response shapes, dynamic filters, and the non-spec endpoints).
Every doc page also has a "Copy as markdown" button in the top-right — use it to feed a single page into context without rendering HTML.

Base URL and auth

EnvironmentBase URLToken prefix
Productionhttps://api.hillwinds.ai/v1ss_live_...
Test keys (sandbox data; zero credits)https://api.hillwinds.ai/v1ss_test_...
bash
curl -H "Authorization: Bearer ss_test_..." \
  "https://api.hillwinds.ai/v1/companies?states=NY&employee_bands=Mid-market+Accounts&page_size=1"

Expected sandbox company: Copperleaf Financial Co (EIN 737336823). A non-2xx response or empty data array means the copy-paste smoke test failed.

api.segmentstudio.com is dead — do not use it
Older docs / samples sometimes reference api.segmentstudio.com. That host does not resolve in DNS. The canonical host is api.hillwinds.ai. Substitute it anywhere you see the old domain.

Endpoint cheat sheet

ResourceList + filterDetailNotes
companiesGET /v1/companiesGET /v1/companies/:idAlso: /lookup, POST /batch, /export.csv, /autocomplete.
personnelGET /v1/personnelGET /v1/personnel/:idlead_type=company|broker required. Also POST /batch, /export.csv, /autocomplete.
broker-officesGET /v1/broker-officesGET /v1/broker-offices/:id/export.csv + /autocomplete (returns populated IDs).
brokersGET /v1/brokersGET /v1/brokers/:id/lookup, /export.csv, /autocomplete.
lookalikesPOST /v1/lookalikesRequest and weight referenceOne to five company, broker-office, or personnel seeds; up to 50 ranked IDs; 1 credit per result. Resolve seeds through the matching production entity endpoint first. Production keys only; test keys return PRODUCTION_KEY_REQUIRED. Custom weights affect one request and are not persisted.
filter-optionsGET /v1/filter-optionsGET /v1/filter-options/{key|resource|resource/filter}Three drill-down shapes; all free.
tagsGET /v1/tagsPOST /v1/tags, /tags/bulk; DELETE /v1/tags, /tags/:idBody: {entity_id, entity_type, tag}. Aliases resource for entity_type.
review-flagsPATCH and DELETE are Hillwinds-internalPOST and GET /v1/review-flagsA live API key with data-flags:write can submit and list owned reviews. Only Hillwinds reviewers can approve, reject, or delete them. Alias: /v1/data-flags.
api-keysGET /v1/api-keysPOST /v1/api-keys, /:id/rotate, DELETE /:idRequires API-key account context plus keys:read/keys:write.
creditsGET /v1/creditsGET /v1/credits/usageRequires API-key account context plus credits:read/usage:read.
reportsPOST /v1/reportsFile a bug report. Free. Use it for unexpected API behavior.

The five universal query parameters

Every list endpoint accepts these. Internalize them and you write efficient queries by default.

ParamDefaultWhat it doesWhen to use
modebasicbasic returns ~10 fields at the cheap rate; full returns ~40-50 fields at 10x the rate.Always start with basic; upgrade to full only when you need broker/carrier/personnel detail.
fields(all in tier)Comma-separated column allowlist. id is always returned.Use to pull only the columns you need — cheaper response, faster query.
count_onlyfalseReturns total_count, no data rows. Zero credits.Sizing a segment. ALWAYS the first call when validating a new filter.
dry_runfalseReturns estimated_rows + estimated_credits without executing. Zero credits.Final sanity check before a paginated pull.
include_counttrueWhen false, skips per-page COUNT(*). Sets has_more via page_size+1 probe instead.Inside a pagination loop — much faster than running COUNT each page.

Common pitfalls

Broad queries can be expensive

Geo-only queries such as GET /v1/companies?states=CA&page_size=10 now return data. They can still represent very large segments, so pair states= with employee_bands, industries, premium_tiers, or signals when you need a targeted pull.

search=MERCER%20SAN%20FRANCISCO returns zero rows because the underlying implementation is a substring match against the primary name field. Try several distinctive search tokens separately and compare the results. When you know a company's website, prefer an exact domain lookup such as /v1/companies/lookup?domain=example.com.

Autocomplete has a narrow column allowlist and per-resource ID gaps

Autocomplete works the same way across all four resources but with different valid column= values, and all four return populated IDs. Full reference moved to /docs/for-ai-agents/autocomplete — short version: column= must be on the per-resource allowlist (1-2 columns only), query requires ≥2 chars, and you should prefer the resource list endpoint with ?search= when you need the full enriched record.

Personnel fields change meaning by lead_type

With lead_type=broker, company_* fields on personnel records echo the broker's own corporate entity (not a client company). With lead_type=company, they describe the contact's employer. Same field names, different meaning — read field names as "the entity context for this contact."

Validate filters before spending credits

Signal filters such as admin_change and numeric filters such as cf[total_number_of_employees] are wired through, but filter behavior can still vary by column and data freshness. Always validate with &count_only=true first. If the count is wildly different from expectation, adjust the filter before spending credits on a full pull.

seniority and job_function are allowlisted buckets

seniority=C-suite includes EAs to C-suite, Senior Directors, and many other adjacent titles. job_function accepts only allowlisted labels; unknown values now return 400 VALIDATION_ERROR with the expected values. Use Human Resources, not HR, and confirm valid labels with GET /v1/filter-options/personnel/job_function?lead_type=company or lead_type=broker.

broker= matches history, not current

broker=MERCER returns every company that has Mercer in some capacity as a broker. The primary_broker field is the broker estimated to own the relationship. Filter the returned rows on primary_broker when that is the relationship you need.

Path and body naming aliases

Tags and review flags accept both human-friendly and canonical body field names. entity_typeresource; field_key field; reasonissue. Responses always return the canonical name. Review-flags is also reachable at /v1/data-flags.

Deep dives

The longest sections of this guide each live on their own page — easier to land on, link to, and feed into a context window without the surrounding prose.

  • Autocomplete reference — request/response shape, the per-resource column= allowlist, which resources return populated IDs, and when to prefer the resource list endpoint with ?search= instead.
  • Recipe library — copy-paste curl flows for the common tasks: find a company, get benefits decision-makers, build a prospect list and tag it, count for free, discover filter values, resolve a company → primary broker office ID.
  • Machine-readable endpoint index — every operation the live API exposes today, in a single table for fast pattern matching.

Discovery flow — what to read in what order

  1. /llms.txt for the link graph.
  2. /v1/openapi.json for canonical query parameter names + types + enums.
  3. This page for pitfalls and the discovery flow.
  4. The endpoint index to confirm an operation exists before crafting the request.
  5. The per-resource API reference pages for response shapes and per-resource filter lists.
  6. GET /v1/filter-options live for enum values.
  7. ?count_only=true / ?dry_run=true for free probes (both 0 credits).

When the OpenAPI spec and docs disagree: spec wins for query parameter names/types/enums (the Endpoint Index is generated from it at build time); docs win for response shapes (components.schemas ships empty), dynamic filter syntax (cf[col]=, eb[col]=, gte:/lte:), headers, and credit costs.

Errors — one paragraph

Standard envelope on failure: {ok: false, error: {code, message, details[], request_id}}. Codes you'll actually hit: 400 VALIDATION_ERROR (unknown param / missing required like lead_type), 403 FORBIDDEN (basic key requesting advanced tier or missing write scope), 429 RATE_LIMITED / 429 CRAWL_DETECTED (use Retry-After), 500 INTERNAL_ERROR (retry with backoff — sometimes a 500 masks a missing scope where 403 would be more accurate; file a report if you suspect this). Full reference at /docs/errors.

When to file a report

If you hit a silent no-op filter, an unexpected 500, an obviously stale record, or an endpoint that returns the wrong shape — file a report. It feeds the next iteration of this page and reaches the API team directly. See /docs/api/reports.