Skip to main content
A handful of FormBharo behaviours are counterintuitive if you come from a typical REST API background. This page documents the four most common integration mistakes.
Both unanswered questions and questions that were never reached appear as null in form_data. This makes it impossible to distinguish “caller skipped this question” from “call ended before we got here” by looking at form_data alone.The trap is testing truthiness: if (form_data.field_name) fails silently for three legitimate answer values:
  • 0 — a valid numeric answer
  • "" — a valid (if unusual) string answer
  • false — a valid boolean answer
All three are falsy in JavaScript (and similar in Python and other languages), so they would be incorrectly treated as missing answers.What to do instead: Always check form_status.field_name === "answered" before using a value from form_data. A status of "answered" guarantees the caller provided a valid response. A status of "skipped" means the question was reached but not answered. If the key is absent from form_status, the question was never asked.
The completed counter in agent analytics includes both complete and screened_out calls. The completion_rate metric is built from this combined count.This is intentional — a screened-out caller did complete the relevant portion of the form (they gave an answer that matched an end_call_values trigger). But if you want to count only calls where the caller answered all questions all the way through, you need to subtract screened_out from completed yourself.
Keep this in mind when reporting conversion rates or SLA metrics — the dashboard number will be higher than your “fully answered” count.
created_at on a conversation record is updated every time the record is written — including when someone manually edits an answer via the API. It is not a fixed timestamp set at the moment the call was connected.This has two consequences:
  1. Sorting by created_at sorts by most recent activity, not by when calls happened. A call from last month that was edited today appears at the top of a created_at DESC sort.
  2. A past time window is never final. If you poll for all calls between yesterday 09:00 and 10:00, you will get a set of results. If you poll the same window an hour later, a call from that slot that was edited in the meantime will reappear — and a call that slipped in at exactly 10:00:00 originally might now be gone if its created_at moved.
What to do instead: Treat conversation_id as your stable identifier. When a call comes back in a poll response, update your local record rather than inserting a new one. For polling new activity, use a since value slightly before your last successful poll timestamp to catch records whose created_at was bumped into the gap.
When a caller answers a multi-select question, FormBharo stores the result as a single comma-and-space-joined string — not as a JSON array.
Not:
If you pass the raw value to code that expects a list — an array .map(), a Python for loop, a database array column — it will fail or behave unexpectedly.What to do instead: Split on ", " (comma followed by a space) to reconstruct the list before using the value.
Be precise with the delimiter — splitting on "," alone (no space) will leave leading spaces on every item after the first.