API reference
Results
GET /api/v1/engine/results/{icon_lead_id}: poll a search until every offer has answered.
GET /api/v1/engine/results/{icon_lead_id}Returns all results of a search so far (not only the new ones). Poll until processing_done is true, waiting poll_after_ms between calls. A search stays open for up to 45 seconds.
Rate limit: 600 per minute per key (bursts of up to 600).
curl -X GET 'https://iconroute.io/api/v1/engine/results/1e8d30bb-7c5f-41b9-8cf1-5e6b57abe999' \
-H "Authorization: Bearer $ICON_API_KEY"#Response
{
"code": "OK",
"status": "accepted",
"reason": "OK",
"success": true,
"icon_lead_id": "1e8d30bb-7c5f-41b9-8cf1-5e6b57abe999",
"processing_done": true,
"accepted_count": 0,
"max_accepted_submissions": 3,
"true_exclusive_accepted": false,
"offers": [
{
"icon_result_id": "api-0b7e4a2c-981234",
"campaign_id": "6f1c2d3e-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
"offer": {
"id": "0b7e4a2c-9d8f-4e1a-b2c3-d4e5f6a7b8c9",
"name": "Example University",
"offer_type": "shared",
"is_exclusive": false,
"tcpa_text": "By clicking Submit, I agree…"
},
"school": {
"name": "Example University",
"logo_url": "https://cdn.example.com/logo.png"
},
"programs": [
{
"value": "4411",
"label": "BS Business (Online)",
"payout": 28
}
],
"payout": 28,
"form_fields": [
{
"name": "api_field_military",
"label": "Military affiliation",
"type": "select",
"required": true,
"options": [
{
"value": "none",
"label": "None"
}
]
},
{
"name": "api_field_rn_license",
"label": "RN license?",
"type": "select",
"required": false,
"required_when": {
"program_ids": [
"4411"
]
}
}
],
"expires_at": "2026-09-25T20:15:00Z"
}
]
}The envelope is the same as the search answer.
#The result entry
One result. The same core fields whether the offer is hosted by ICON or is a partner offer ICON calls.
| Field | Type | Required | Description |
|---|---|---|---|
icon_result_id | string | yes | Submit this id to POST /api/v1/engine/leads. |
campaign_id | string (uuid) or null | — | The campaign the result is sold under. |
offer | object | yes | — |
offer.id | string (uuid) | — | The ICON offer id. |
offer.name | string | — | — |
offer.offer_type | string | — | shared | exclusive | true_exclusive |
offer.is_exclusive | boolean or null | — | — |
offer.tcpa_text | string or null | — | The consent statement to show with this result. |
school | object | — | — |
school.name | string | — | — |
school.logo_url | string or null | — | — |
programs | array of object | yes | — |
programs[].value | string | yes | Send as program_id on submit. |
programs[].label | string | yes | — |
programs[].payout | number | — | Your payout for this program. Absent when none is configured. |
payout | number | — | Your best payout for this result (never the offer's own price). Absent when none is configured. |
form_fields | array of object | yes | Questions this result needs answered on submit, by name. |
form_fields[].name | string | yes | — |
form_fields[].label | string or null | — | — |
form_fields[].type | string | yes | — |
form_fields[].required | boolean | yes | — |
form_fields[].required_when | object | — | Required only when one of these programs is chosen. |
form_fields[].options | array of object | — | — |
expires_at | string (date-time) or null | — | Submit before this time. |
#Questions (form_fields)
Ask every required question, and every question whose required_when.program_ids contains the program the consumer chose. Send each answer on submit under the question's name; for a select, send one of its options[].value.
#Expiry
Submit before expires_at. An expired result answers OFFER_UNAVAILABLE: search again.
#Errors
| HTTP | Meaning |
|---|---|
| 401 | AUTH_REQUIRED (no API key) or AUTH_INVALID (a key ICON does not know); status invalid. |
| 403 | FORBIDDEN: the campaign or offer is not yours. |
| 404 | NOT_FOUND: no search with that id belongs to your key. |
| 429 | RATE_LIMITED (retryable): this API key is over its rate limit. Wait the Retry-After header's seconds (also retry_after_seconds) and retry. Limits are per API key and per leg: search 60 per minute with bursts of up to 10, results polling 600 per minute, submit 120 per minute, unless ICON set other limits for your key. |
| 500 | INTERNAL_ERROR: not retryable as is; tell your ICON contact the time and the icon_lead_id. |
| 503 | UNAVAILABLE: retry later. |