This guide covers what the API reference doesn’t: how to structure
your provider offerings for Nexio and interpret the results.
For request/response schemas, see Submit Run and
Get Run Status.
Flow
Persist run_id. Polling remains the canonical reconciliation path even when using
webhooks.
What you send
{
"input": { ... },
"offerings": [ ... ]
}
input is the subject’s profile and run context. offerings is one entry per provider per requirement category.
input.current_coverage describes existing state (e.g., incumbent products or services). It provides context for scoring but does
not replace the offerings array.
Building offerings from your data
Each provider entry becomes one offering per requirement category. If you have 3 providers each
covering 3 categories, that’s 9 offerings (3 providers x 3 categories).
Keep offerings[*].category aligned with input.coverage_types. Extra offerings for categories
not in coverage_types are ignored.
When comparing packages from multiple providers, submit offerings from each. The engine evaluates
all valid combinations — both single-provider bundles and mixed-provider packages:
Example: Insurance — Personal Lines. The input and offerings schema depends on your engine’s configuration. This example shows a personal-lines insurance placement engine.
{
"input": {
"address": { "state": "NY", "zip_code": "11231" },
"coverage_types": ["home", "auto", "umbrella"],
"appetite_bucket": "balanced",
"vehicles": 1,
"premium": 3557.23
},
"offerings": [
{
"id": "quote_line_carrier_a_home_001",
"provider_id": "prov_carrier_a",
"provider_name": "Carrier A",
"category": "home",
"quality_rating": "A+",
"pricing_tier": "premium",
"commission": 0.14,
"constraints": { "excluded_states": [], "prohibited_naics": [], "avoided_naics": [] },
"coverage": { "product_name": "Select Homeowners", "program_type": "quoted_line" },
"attributes": { "quote_id": "qt_carrier_a_home_001", "line_premium_annual": 6120, "package_premium_annual": 12840 }
},
{
"id": "quote_line_carrier_b_home_001",
"provider_id": "prov_carrier_b",
"provider_name": "Carrier B",
"category": "home",
"quality_rating": "A",
"pricing_tier": "economy",
"commission": 0.12,
"constraints": { "excluded_states": [], "prohibited_naics": [], "avoided_naics": [] },
"coverage": { "product_name": "Select Home", "program_type": "quoted_line" },
"attributes": { "quote_id": "qt_carrier_b_home_001", "line_premium_annual": 5050, "package_premium_annual": 10950 }
}
]
}
Results may include an all-Carrier A bundle, an all-Carrier B bundle, and mixed-provider combinations
(e.g. Carrier A home + Carrier C auto) — all ranked by composite scorecard.
Polling
Poll GET /api/v1/runs/{run_id} until terminal. Start at 2s delay, backoff 1.5x, cap at 30s.
| Status | Action |
|---|
queued | Keep polling |
processing | Keep polling |
completed | Consume solutions |
failed | Read error, stop |
import time, httpx
def wait_for_result(api_key: str, run_id: str) -> dict:
headers = {"Authorization": f"Bearer {api_key}"}
delay = 2
while True:
data = httpx.get(
f"https://api.usenexio.com/api/v1/runs/{run_id}",
headers=headers,
).json()
if data["status"] in ("completed", "failed"):
return data
time.sleep(delay)
delay = min(delay * 1.5, 30)
Reading results
Key fields on a completed response:
| Field | Purpose |
|---|
solutions[*].rank | Rank order (1 = best) |
solutions[*].cluster_label | Solution label: recommended, best_value, best_coverage, simplest |
solutions[*].scorecard.overall_level | Package score (lower is better) |
solutions[*].provider_count | 1 = single provider, 2+ = mixed |
solutions[*].est_cost_low / est_cost_high | Annual cost range |
solutions[*].offerings[*].provider_name | Provider per category |
solutions[*].offerings[*].category | Requirement category (domain-specific, e.g. home, auto) |
There is no solutions[*].carrier_name — use offerings[*].provider_name.
There is no solutions[*].score — use scorecard.overall_level.
Failure cases
completed with 0 solutions — output.diagnostic explains why. Common causes:
coverage_types / offerings[*].category mismatch, missing required categories, or all offerings
filtered out. This is a valid terminal state, not an error.
failed — read error and error_details. Terminal.
Stuck in processing — the EVALUATE stage can take time. Use backoff, don’t tight-loop.
Integration checklist
offerings generated per category per provider, not per package
offerings[*].category aligns with input.coverage_types
- Polling handles all four status values
- Package score read from
scorecard.overall_level
- Provider identity read from
offerings[*].provider_name
- Both request and terminal response persisted
Example artifacts
- Canonical request — complete
POST /api/v1/engines/default/runs body with input and offerings (insurance — personal lines)
- Canonical response — complete
GET /api/v1/runs/{run_id} response for a completed run (insurance — personal lines)