Skip to navigation

Get quote results

Hear about each new quote by webhook, by polling, or with a read that waits for the next change.
View as Markdown

POST /v1/quote-requests answers right away with 202 and a quote request whose status is in_progress. Truvo then asks the carriers in the background, and their quotes arrive one at a time over up to 60 seconds.

Each change to the request raises its version: the start of its run, each new quote, and the final status. A read never starts a new rating run. You can hear about the changes in four ways:

WayUse this whenCalls in the exampleFirst price
WebhooksYou run a server that can take a POST from Truvo, and you want no reads while you wait.A read for each event you act on: 6About 4 s, plus the time the delivery takes
Quick pollingYour client can’t hold a request open, or you read on a schedule.31 reads, one every 2 seconds4 to 6 s
Waiting readsYou call from code and can hold a request open for 20 seconds. We recommend this.8 readsAbout 4 s
MCPAn AI agent reads the request through the Truvo MCP server.8 tool callsAbout 4 s

The example

The figures in the table come from one quote request:

  • The request starts at 0 s. Its 202 answer is version 1, and its run starts right after that, at version 2.
  • Quotes arrive at 4, 9, 15, and 38 seconds. Each one raises the version.
  • One carrier never answers, so the request completes at the 60-second deadline with four quotes.

Webhooks

Subscribe a URL to quote_request.updated, quote_request.completed, quote_request.incomplete, and quote_request.failed. Truvo sends a signed POST each time the request changes, and you read the request when an event arrives. Webhooks covers subscriptions, signatures, and retries.

In the example, Truvo sends six events: one when the request starts, one for each quote, and quote_request.completed at 60 s. Each event names only the request and its new version, so read the request to get the quotes.

You need an https URL on a public host that answers 2xx within 15 seconds. The webhook routes answer 404 while Truvo has webhooks turned off.

Quick polling

Without Prefer: wait, a read answers at once. Read the request every few seconds until its status is no longer in_progress.

curl https://api.truvo.com/v1/quote-requests/qreq_... \
-H "Authorization: Bearer $TRUVO_API_KEY" \
-H "Truvo-Version: 2026-09-26"

In the example, a read every 2 seconds takes 31 reads from 0 s to 60 s. Each quote shows up 0 to 2 seconds after it arrives, so the first price shows by 6 s. Each read counts toward your rate limit, so a faster loop uses more of it.

Waiting reads

Add Prefer: wait=20 and since_version to the read:

curl "https://api.truvo.com/v1/quote-requests/qreq_...?since_version=1" \
-H "Authorization: Bearer $TRUVO_API_KEY" \
-H "Truvo-Version: 2026-09-26" \
-H "Prefer: wait=20"
  • Prefer: wait=N holds the read open for up to N seconds, where N is a whole number from 0 to 20. The read answers as soon as the request changes: a new quote, a new status, or the end of the request.
  • since_version is the version from the last answer you got, starting with the 202 answer. If the request is already newer, or its status isn’t in_progress, the read answers at once, so a quote that arrives between two of your reads doesn’t wait for the next change. A version higher than the current one counts as the current one. Without since_version, the wait counts from the version that the read finds first.

In the example, each read sends the version of the answer before it:

ReadSent atsince_versionAnswers atWhy
10 s10 sThe request is already at version 2: its run started, with no quotes yet.
20 s24 sThe first quote.
34 s39 sThe second quote.
49 s415 sThe third quote.
515 s535 sNothing changed for 20 seconds.
635 s538 sThe fourth quote.
738 s658 sNothing changed for 20 seconds.
858 s660 sThe request completes.

A held read answers within about a second of the change. A read that the server held carries Preference-Applied: wait=N, and a read that answered at once doesn’t. When the server can’t hold a read, it answers at once with Retry-After and without Preference-Applied. Wait that many seconds before you read again.

A Prefer value or a since_version that isn’t valid gets 422 with the code invalid_input.

The loop

This loop starts from the version in the 202 answer, waits out Retry-After when an answer has it, and stops when the status is no longer in_progress:

version=1 # the version in the 202 answer
while true; do
body=$(curl -s -D headers.txt "https://api.truvo.com/v1/quote-requests/$QUOTE_REQUEST_ID?since_version=$version" \
-H "Authorization: Bearer $TRUVO_API_KEY" \
-H "Truvo-Version: 2026-09-26" \
-H "Prefer: wait=20")
state=$(printf '%s' "$body" | jq -r .status)
printf '%s\n' "$body" | jq -c '{status, quotes}'
if [ "$state" != "in_progress" ]; then
break
fi
version=$(printf '%s' "$body" | jq -r .version)
retry_after=$(awk -F': ' 'tolower($1) == "retry-after" { print $2 + 0 }' headers.txt)
if [ -n "$retry_after" ]; then
sleep "$retry_after"
fi
done

Agents over MCP

An agent that uses the Truvo MCP server calls get_quote_request, which works like a waiting read:

  • wait_seconds takes the place of Prefer: wait, from 0 to 20, and the wait is 20 seconds when the agent leaves it out.
  • since_version works as it does over HTTP.
  • Read status in the start_quote_request result and each get_quote_request result. While it is in_progress, call get_quote_request again with the same id, wait_seconds: 20, and since_version set to the version you just read. If you read by handle, send the same read_handle too.

In the example, the agent makes the same 8 calls as the waiting reads above, and it can tell the person about each quote as it arrives.

The 60-second deadline

Truvo currently stops collecting answers 60 seconds after it accepts a quote request, then finishes the request with the answers it has.

  • A carrier that hasn’t answered by then reads no_answer in market_outcomes.
  • With no quote or offline quote, all listed carriers giving no answer leaves the request incomplete, with the reason no_carrier_answered; a decline beside silence uses carriers_unavailable. You can try a new request later; it may still return no quotes.
  • If the run could not start or the call broke, the request ends failed. A run that lists no carriers also stays failed.
  • A finished request doesn’t change.

Statuses

Switch on status.

StatusFinal?Normal?What to do
in_progressNoYesRead again. Quotes can show before the request finishes.
action_requiredNoYesNot used yet. When used, show status_details.message, then follow next_actions.
completedYesYesShow the quotes. A completed request can hold no quotes.
incompleteYesYesShow status_details.message. You can try a new request later; it may still return no quotes.
failedYesNoShow status_details.message, then follow status_details.retry_action.

status_details says why the request has its status: a reason and a message that you can show the person. New reasons can arrive in any revision, so show message, and give any switch on reason a default branch. The reasons today:

ReasonStatusMeans
queuedin_progressTruvo hasn’t asked the carriers yet.
collectingin_progressThe carriers are answering.
quotedcompletedEvery carrier answered.
partly_quotedcompletedSome carriers didn’t answer. The quotes that came in are listed.
no_quotescompletedEvery carrier result is a final answer without a quote.
offline_quotes_onlycompletedCarriers offered prices, but the person can’t buy any of them online through Truvo.
carriers_unavailableincompleteA final answer sits beside carrier silence, and there are no quotes.
no_carrier_answeredincompleteNo carrier answered this time.
quote_run_failedfailedTruvo could not finish this quote request.
quote_run_not_startedfailedTruvo could not start this quote request.

Read the result

  • quotes gives the ID and the version of each quote. A carrier can give a quote for each product it prices. To read one quote version, call GET /v1/quotes/{id}?version=.
  • market_outcomes has one entry for each carrier result on this request: quote, offline_quote, decline, missing_information, pending, or no_answer. Each entry names the carrier by carrier.id and carrier.name. A carrier with several quotes has one quote entry, which names its first quote. offline_quote means the carrier offered a price that the person can’t buy online through Truvo.
  • next_actions lists what you can do next.
  • status_details.retry_action is null unless the request is incomplete or failed. When a request failed, follow its retry action. When it is incomplete, follow it only if you try a new request. Use a new Idempotency-Key for that request.

failed is an error on Truvo’s side and always says what to do next. incomplete is a finished result where carriers gave no final answer. Neither completed nor incomplete is an error.

A request with zero quotes completes with offline_quotes_only when a carrier offered a price that the person can’t buy online through Truvo, and with no_quotes when every carrier result is a final answer without a quote. It ends incomplete when listed carriers gave no final answer and there is no quote or offline quote. Why did a request finish with no quotes? says what to do in each case.

Quote statuses

Each quote has its own status and status_details.

StatusFinal?Normal?What to do
activeNoYesOffer the quote’s next_actions. The quote turns inactive by availability.expires_at.
inactiveYesYesShow status_details.message. For a current price, send a new quote request.

The reasons today are available for an active quote, and expired for an inactive one. New reasons can arrive in any revision.

Show quotes to a person covers each quote field, the price, and the actions that send the person to buy.