Am I affected?
Check a webhook payload orGET /executions/{execution_id} response from before the change:
Already migrated? Nested keys mean you are on Extractions and no action is needed. The legacy toggles are gone from the agent Extractions tab, which now configures webhooks and Extractions only.
Migration by feature
Four features, four different paths. Open the one whose field your integration reads.Extraction
extracted_data · flat keys → Rebuild as extractions. One extraction per field in your prose box. Keys stay stable if you reuse your current names.Custom analytics
custom_extractions → Rebuild, one per item. Types map onto answer types. Numbers become strings, and min/max clamping has no equivalent — use validation.is_valid instead.Agent extraction
agent_extraction → Discontinued. No replacement template and no migration on your behalf. Identify the fields from a payload and author your own.Call summary
summary → No change required. Stays a flat top-level key, now sourced from the Call Summary extraction. Keep reading it as you do today.What the payload looks like
Category is a grouping label you choose. Name is the key you choose.Result object fields
Which field to read:
Breaking changes
- Values are two levels deeper.
extracted_data.call_reasonbecomesextracted_data["Call Details"]["Call Reason"]. - Values are objects, not scalars. Select
objectiveorsubjectivefrom the result. subjectiveandobjectiveare always JSON strings. A numeric extraction returns"250000", not250000. Custom Analytics returned a real number, so parse it yourself. Min/max clamping has no equivalent; usevalidation.is_validto confirm the value parses.custom_extractionsandagent_extractionreturnnull. The keys stay in the payload, so a consumer reading them finds them present and empty rather than missing.summarystays a flat top-level key. Webhook payloads keepsummaryas a string at the top level, populated by the Call Summary extraction instead of the legacy summarization task. If you read top-levelsummary, no change is required.objectivecannot drift. Pre-defined answers are constrained by the request, so the value matches your configured option character for character. Switch fuzzy matching to exact comparison.- New capabilities: per-answer confidence, LLM reasoning, and format validation. Route
confidence_label: "Low"to human review.
Expected formats
A failed check never loses the value.
is_valid: false is set and subjective holds the LLM’s response unchanged.
Calls with no user speech
Enabled per account rather than by default. Email support@bolna.ai to turn it on; it then applies to every agent on the account. When a call contains no user turns (voicemail, an immediate hangup, dead air), the LLM has nothing to work from and can still invent a plausible answer. With this enabled, every extraction on the agent returns a fixed sentinel instead.No user turns detected
No User Turn Detected appears in subjective, objective, reasoning_subjective and reasoning_objective, in every extraction across every category.
Check for the sentinel before reading any extraction value, and route these calls to your no-contact path rather than treating them as answered.
CSV exports
Seven columns per extraction instead of one, followingextracted_data_<Category>_<Name>_<field>.
Update any loader or formula referencing columns by name.
Configuring through the API
Extractions are managed under
/dispositions. “Disposition” is the API’s name for a single extraction. The /extractions path is an internal template registry, not this endpoint.Creating one
POST
nameis the result key.categoryis the key above it.questionis the LLM prompt. State what to look at, what to ignore, and what each option means.- Always include a fallback option such as
NAso the model is never forced to pick a real answer for a question the call never reached. - Set
is_subjective: truefor free text,is_objective: truefor pre-defined, or both. subjective_typeacceptstext,numeric,boolean,email,timestamp,regex.regexalso requiressubjective_type_config: {"pattern": "…"}.- Extractions in one category are answered in a single LLM call, so grouping related fields keeps their answers consistent with each other.
Verifying a migration
POST /v2/agent/{agent_id}/dispositions/test
{"extracted_data": {…}} in exactly the shape a live call produces. Paste a real past transcript and diff against what your old configuration returned for that call. No call is spent.
Reading historical calls
extracted_data was a shared field, so calls placed while both a legacy extraction task and Extractions were enabled hold both shapes at once — flat legacy keys alongside nested categories:
A call from the transition period
subjective and objective. Code that branches on the nested shape reads both new calls and historical ones correctly.
FAQ
Is historical data converted?
Is historical data converted?
No. Completed calls keep the results and shape they were stored with, readable indefinitely. Only calls placed after you migrate use the new shape. Code that reads historical calls must keep handling the old shape permanently, not just until the cutoff.
Can I still run the legacy features?
Can I still run the legacy features?
No. They are removed, and an agent still carrying a legacy configuration simply produces no results from it. Rebuild the fields you need as extractions.
Will results be worded differently?
Will results be worded differently?
Free-text answers may be phrased differently for an identical call, because the prompt structure differs. Pre-defined answers are stable, since they can only be one of your configured values. Diff side by side before disabling anything.
Can I keep my field names?
Can I keep my field names?
Yes. Set each extraction’s name to your current key. The name is unchanged; the path is one level deeper.
Will you migrate my configuration for me?
Will you migrate my configuration for me?
No. Recreating extractions is self-serve, through the dashboard or the
/dispositions API. This includes Agent Extraction, which is discontinued rather than replaced.What happens if I never migrated?
What happens if I never migrated?
Agents keep taking calls. Only structured results stop: legacy fields return
null, and no extractions run unless configured. Transcripts, recordings and call summaries are unaffected.My payload does not match these pages.
My payload does not match these pages.
Email support@bolna.ai with the
execution_id of the call, the field you were reading, and the value you expected. The execution_id is the id in the webhook payload and in GET /executions responses. One id is much quicker for us to work with than a description of the problem — we can pull that exact execution and see which extraction path produced the value.execution_id for a payload that does not match this guide.
Next steps
Using extractions
Configure extractions in the dashboard
Dispositions API
Manage extractions programmatically
Webhooks
Receive extraction data in real-time

