API reference
Analytics
Metrics
| Method | Path | Summary |
|---|---|---|
GET | /v1/account/analytics | Booking rates, drop-off, latency, transfers, unanswered questions, cost and per-group handoff metrics |
GET | /v1/account/analytics/booking-pages | Booking pages: views, times picked, booked, completion, cancellations, moves and no-shows per page and rep, and bookings by source |
GET | /v1/account/analytics/follow-up | Follow-up page consent, delivery, open, engagement and show-rate metrics for the filtered calls |
GET | /v1/account/analytics/pricing | Services quoted, services asked about that are not offered, specials mentioned and nearby locations named |
GET | /v1/account/analytics/visits | Visits held, and how many have notes, next steps and photos; next steps by key and how they ended; photos shared and whether families looked |
Booking rates, drop-off, latency, transfers, unanswered questions, cost and per-group handoff metrics#
GET /v1/account/analytics
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
playbookId | string (pb_… ID) | No | ID (pb_…) |
playbookVersionId | string (pbv_… ID) | No | ID (pbv_…) |
groupId | string (grp_… ID) | No | ID (grp_…) |
from | string | No | Up to 40 characters. |
to | string | No | Up to 40 characters. |
includeTests | enum | No | One of: "true", "false". |
channel | enum | No | One of: "phone", "site_chat", "page_chat", "web_voice". Default: "phone". |
effectivePlaybookId | string (epb_… ID) | No | ID (epb_…) |
fromDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
toDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
source | enum | No | One of: "number", "widget", "page". |
caller | enum | No | One of: "prospect", "other". |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
bookingRate | number | null | Yes | — |
byGroup | array<object> | Yes | — |
byGroup[].booked | integer | Yes | — |
byGroup[].bookingRate | number | null | Yes | — |
byGroup[].connected | integer | Yes | — |
byGroup[].conversations | integer | Yes | — |
byGroup[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
byGroup[].groupName | string | Yes | — |
byRule | array<object> | Yes | — |
byRule[].booked | integer | Yes | — |
byRule[].bookingRate | number | null | Yes | — |
byRule[].calls | integer | Yes | — |
byRule[].connected | integer | Yes | — |
byRule[].ruleId | string | Yes | — |
cost | object | Yes | — |
cost.centsPerMinute | number | Yes | — |
cost.connectedMinutes | number | Yes | — |
cost.perBookingCents | integer | null | Yes | — |
cost.perCallCents | integer | null | Yes | — |
cost.totalCents | integer | Yes | — |
dropOff | array<object> | Yes | — |
dropOff[].dropOffRate | number | null | Yes | — |
dropOff[].droppedHere | integer | Yes | — |
dropOff[].reached | integer | Yes | — |
dropOff[].stage | enum | Yes | One of: "open", "discover", "consult", "book", "wrap", "transfer". |
filters | object | Yes | — |
filters.channel | enum | Yes | One of: "phone", "site_chat", "page_chat", "web_voice". |
filters.from | string (date-time) | null | Yes | — |
filters.to | string (date-time) | null | Yes | — |
handoffByGroup | array<object> | Yes | — |
handoffByGroup[].callbacksCaptured | integer | Yes | — |
handoffByGroup[].connected | integer | Yes | — |
handoffByGroup[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
handoffByGroup[].groupName | string | Yes | — |
handoffByGroup[].handoffRate | number | null | Yes | — |
handoffByGroup[].handoffs | integer | Yes | — |
handoffByGroup[].medianMinutesToCallback | number | null | Yes | — |
handoffByGroup[].missedCallbacks | integer | Yes | — |
handoffByGroup[].notetaker | object | Yes | — |
handoffByGroup[].notetaker.coverage | number | null | Yes | — |
handoffByGroup[].notetaker.handedToReps | integer | Yes | — |
handoffByGroup[].notetaker.notesDone | integer | Yes | — |
handoffByGroup[].notetaker.repEdits | integer | Yes | — |
handoffByGroup[].notetaker.repEditsPerCall | number | null | Yes | — |
handoffByGroup[].notetaker.withNotes | integer | Yes | — |
handoffByGroup[].reasons | array<object> | Yes | — |
handoffByGroup[].reasons[].count | integer | Yes | — |
handoffByGroup[].reasons[].key | string | Yes | — |
handoffByGroup[].transferAnswerRate | number | null | Yes | — |
handoffByGroup[].transferAttempts | integer | Yes | — |
handoffByGroup[].transfersAnswered | integer | Yes | — |
latency | object | Yes | — |
latency.medianMs | number | null | Yes | — |
latency.p95Ms | number | null | Yes | — |
latency.turns | integer | Yes | — |
outcomes | array<object> | Yes | — |
outcomes[].count | integer | Yes | — |
outcomes[].key | string | Yes | — |
qualifiedBookingRate | number | null | Yes | — |
ringing | object | Yes | — |
ringing.byAnswered | array<object> | Yes | — |
ringing.byAnswered[].answeredBy | enum | Yes | One of: "agent", "rep", "nobody". |
ringing.byAnswered[].booked | integer | Yes | — |
ringing.byAnswered[].conversations | integer | Yes | — |
ringing.byRep | array<object> | Yes | — |
ringing.byRep[].accepted | integer | Yes | — |
ringing.byRep[].declined | integer | Yes | — |
ringing.byRep[].lostRace | integer | Yes | — |
ringing.byRep[].missed | integer | Yes | — |
ringing.byRep[].name | string | Yes | — |
ringing.byRep[].offered | integer | Yes | — |
ringing.byRep[].repMinutes | number | Yes | — |
ringing.byRep[].userId | string (usr_… ID) | Yes | ID (usr_…) |
ringing.byRingGroup | array<object> | Yes | — |
ringing.byRingGroup[].answeredByAgent | integer | Yes | — |
ringing.byRingGroup[].answeredByRep | integer | Yes | — |
ringing.byRingGroup[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
ringing.byRingGroup[].medianSecondsToAnswer | number | null | Yes | — |
ringing.byRingGroup[].missed | integer | Yes | — |
ringing.byRingGroup[].name | string | Yes | — |
ringing.byRingGroup[].nobodyAvailable | integer | Yes | — |
ringing.byRingGroup[].offered | integer | Yes | — |
ringing.byRingGroup[].repAnswerRate | number | null | Yes | — |
ringing.byRingGroup[].repMinutes | number | Yes | — |
ringing.byRingGroup[].ringGroupId | string (rgp_… ID) | Yes | ID (rgp_…) |
topUnansweredQuestions | array<object> | Yes | — |
topUnansweredQuestions[].count | integer | Yes | — |
topUnansweredQuestions[].key | string | Yes | — |
totals | object | Yes | — |
totals.booked | integer | Yes | — |
totals.calls | integer | Yes | — |
totals.connected | integer | Yes | — |
totals.handoffs | integer | Yes | — |
totals.qualified | integer | Yes | — |
totals.transferred | integer | Yes | — |
transferRate | number | null | Yes | — |
transferReasons | array<object> | Yes | — |
transferReasons[].count | integer | Yes | — |
transferReasons[].key | string | Yes | — |
unansweredHandoffs | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/analytics" \
-H "Authorization: Bearer $ACCESS_TOKEN"Booking pages: views, times picked, booked, completion, cancellations, moves and no-shows per page and rep, and bookings by source#
GET /v1/account/analytics/booking-pages
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | No | ID (grp_…) |
from | string | No | Up to 40 characters. |
to | string | No | Up to 40 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
bySource | array<object> | Yes | — |
bySource[].count | integer | Yes | — |
bySource[].key | string | Yes | — |
byUtmSource | array<object> | Yes | — |
byUtmSource[].count | integer | Yes | — |
byUtmSource[].key | string | Yes | — |
filters | object | Yes | — |
filters.from | string (date-time) | null | Yes | — |
filters.to | string (date-time) | null | Yes | — |
pages | array<object> | Yes | — |
pages[].attended | integer | Yes | — |
pages[].booked | integer | Yes | — |
pages[].cancelled | integer | Yes | — |
pages[].completion | number | null | Yes | — |
pages[].groupId | string | Yes | — |
pages[].groupName | string | Yes | — |
pages[].id | string | Yes | — |
pages[].kind | enum | Yes | One of: "personal", "group". |
pages[].moved | integer | Yes | — |
pages[].noShows | integer | Yes | — |
pages[].ownerName | string | null | Yes | — |
pages[].picked | integer | Yes | — |
pages[].title | string | Yes | — |
pages[].views | integer | Yes | — |
reps | array<object> | Yes | — |
reps[].attended | integer | Yes | — |
reps[].booked | integer | Yes | — |
reps[].cancelled | integer | Yes | — |
reps[].moved | integer | Yes | — |
reps[].name | string | Yes | — |
reps[].noShows | integer | Yes | — |
reps[].userId | string | Yes | — |
totals | object | Yes | — |
totals.attended | integer | Yes | — |
totals.booked | integer | Yes | — |
totals.cancelled | integer | Yes | — |
totals.completion | number | null | Yes | — |
totals.moved | integer | Yes | — |
totals.noShows | integer | Yes | — |
totals.picked | integer | Yes | — |
totals.views | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/analytics/booking-pages" \
-H "Authorization: Bearer $ACCESS_TOKEN"Follow-up page consent, delivery, open, engagement and show-rate metrics for the filtered calls#
GET /v1/account/analytics/follow-up
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
playbookId | string (pb_… ID) | No | ID (pb_…) |
playbookVersionId | string (pbv_… ID) | No | ID (pbv_…) |
groupId | string (grp_… ID) | No | ID (grp_…) |
from | string | No | Up to 40 characters. |
to | string | No | Up to 40 characters. |
includeTests | enum | No | One of: "true", "false". |
channel | enum | No | One of: "phone", "site_chat", "page_chat", "web_voice". Default: "phone". |
effectivePlaybookId | string (epb_… ID) | No | ID (epb_…) |
fromDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
toDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
source | enum | No | One of: "number", "widget", "page". |
caller | enum | No | One of: "prospect", "other". |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
consent | object | Yes | — |
consent.asked | integer | Yes | — |
consent.granted | integer | Yes | — |
consent.rate | number | null | Yes | — |
consent.revoked | integer | Yes | — |
delivery | object | Yes | — |
delivery.delivered | integer | Yes | — |
delivery.failed | integer | Yes | — |
delivery.queued | integer | Yes | — |
delivery.rate | number | null | Yes | — |
delivery.sent | integer | Yes | — |
delivery.skipped | integer | Yes | — |
engagement | object | Yes | — |
engagement.booked | integer | Yes | — |
engagement.cancelRate | number | null | Yes | — |
engagement.cancelled | integer | Yes | — |
engagement.formRate | number | null | Yes | — |
engagement.formSubmitted | integer | Yes | — |
engagement.rescheduleRate | number | null | Yes | — |
engagement.rescheduled | integer | Yes | — |
engagement.shareRate | number | null | Yes | — |
engagement.shared | integer | Yes | — |
engagement.videoPlayRate | number | null | Yes | — |
engagement.videoPlayed | integer | Yes | — |
filters | object | Yes | — |
filters.channel | enum | Yes | One of: "phone", "site_chat", "page_chat", "web_voice". |
filters.from | string (date-time) | null | Yes | — |
filters.to | string (date-time) | null | Yes | — |
pages | object | Yes | — |
pages.created | integer | Yes | — |
pages.medianMinutesToFirstOpen | number | null | Yes | — |
pages.openRate | number | null | Yes | — |
pages.opened | integer | Yes | — |
pages.openedByShared | integer | Yes | — |
show | object | Yes | — |
show.cohorts | array<object> | Yes | — |
show.cohorts[].attended | integer | Yes | — |
show.cohorts[].bookings | integer | Yes | — |
show.cohorts[].key | enum | Yes | One of: "opened", "not_opened", "no_page". |
show.cohorts[].noShow | integer | Yes | — |
show.cohorts[].showRate | number | null | Yes | — |
show.cohorts[].unknown | integer | Yes | — |
show.measured | integer | Yes | — |
show.unknown | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/analytics/follow-up" \
-H "Authorization: Bearer $ACCESS_TOKEN"Services quoted, services asked about that are not offered, specials mentioned and nearby locations named#
GET /v1/account/analytics/pricing
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
playbookId | string (pb_… ID) | No | ID (pb_…) |
playbookVersionId | string (pbv_… ID) | No | ID (pbv_…) |
groupId | string (grp_… ID) | No | ID (grp_…) |
from | string | No | Up to 40 characters. |
to | string | No | Up to 40 characters. |
includeTests | enum | No | One of: "true", "false". |
channel | enum | No | One of: "phone", "site_chat", "page_chat", "web_voice". Default: "phone". |
effectivePlaybookId | string (epb_… ID) | No | ID (epb_…) |
fromDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
toDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
source | enum | No | One of: "number", "widget", "page". |
caller | enum | No | One of: "prospect", "other". |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
nearbyNamed | array<object> | Yes | — |
nearbyNamed[].booked | integer | Yes | — |
nearbyNamed[].calls | integer | Yes | — |
nearbyNamed[].id | string | Yes | — |
nearbyNamed[].name | string | Yes | — |
notOfferedAsked | array<object> | Yes | — |
notOfferedAsked[].booked | integer | Yes | — |
notOfferedAsked[].calls | integer | Yes | — |
notOfferedAsked[].id | string | Yes | — |
notOfferedAsked[].name | string | Yes | — |
servicesQuoted | array<object> | Yes | — |
servicesQuoted[].booked | integer | Yes | — |
servicesQuoted[].calls | integer | Yes | — |
servicesQuoted[].id | string | Yes | — |
servicesQuoted[].name | string | Yes | — |
specialsMentioned | array<object> | Yes | — |
specialsMentioned[].booked | integer | Yes | — |
specialsMentioned[].calls | integer | Yes | — |
specialsMentioned[].id | string | Yes | — |
specialsMentioned[].name | string | Yes | — |
totals | object | Yes | — |
totals.bookedOtherwise | integer | Yes | — |
totals.bookedWhenQuoted | integer | Yes | — |
totals.calls | integer | Yes | — |
totals.connected | integer | Yes | — |
totals.quoted | integer | Yes | — |
totals.quotedConnected | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/analytics/pricing" \
-H "Authorization: Bearer $ACCESS_TOKEN"Visits held, and how many have notes, next steps and photos; next steps by key and how they ended; photos shared and whether families looked#
GET /v1/account/analytics/visits
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | No | ID (grp_…) |
from | string | No | Up to 40 characters. |
to | string | No | Up to 40 characters. |
fromDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
toDay | string | No | Pattern: ^\d\{4\}-\d\{2\}-\d\{2\}$. |
playbookId | string (pb_… ID) | No | ID (pb_…) |
playbookVersionId | string (pbv_… ID) | No | ID (pbv_…) |
effectivePlaybookId | string (epb_… ID) | No | ID (epb_…) |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
byGroup | array<object> | Yes | — |
byGroup[].groupId | string | Yes | — |
byGroup[].groupName | string | Yes | — |
byGroup[].held | integer | Yes | — |
byGroup[].notesRate | number | null | Yes | — |
byGroup[].photosRate | number | null | Yes | — |
byGroup[].stepsRate | number | null | Yes | — |
byGroup[].withNotes | integer | Yes | — |
byGroup[].withPhotos | integer | Yes | — |
byGroup[].withSteps | integer | Yes | — |
byRep | array<object> | Yes | — |
byRep[].held | integer | Yes | — |
byRep[].name | string | Yes | — |
byRep[].notesRate | number | null | Yes | — |
byRep[].photosRate | number | null | Yes | — |
byRep[].stepsRate | number | null | Yes | — |
byRep[].userId | string | Yes | — |
byRep[].withNotes | integer | Yes | — |
byRep[].withPhotos | integer | Yes | — |
byRep[].withSteps | integer | Yes | — |
filters | object | Yes | — |
filters.from | string (date-time) | null | Yes | — |
filters.to | string (date-time) | null | Yes | — |
photos | object | Yes | — |
photos.downloaded | integer | Yes | — |
photos.downloadedRate | number | null | Yes | — |
photos.medianShared | number | null | Yes | — |
photos.published | integer | Yes | — |
photos.viewed | integer | Yes | — |
photos.viewedRate | number | null | Yes | — |
steps | array<object> | Yes | — |
steps[].dismissed | integer | Yes | — |
steps[].doneLate | integer | Yes | — |
steps[].doneOnTime | integer | Yes | — |
steps[].key | string | null | Yes | — |
steps[].label | string | Yes | — |
steps[].open | integer | Yes | — |
steps[].picked | integer | Yes | — |
totals | object | Yes | — |
totals.held | integer | Yes | — |
totals.notesRate | number | null | Yes | — |
totals.photosRate | number | null | Yes | — |
totals.stepsRate | number | null | Yes | — |
totals.withNotes | integer | Yes | — |
totals.withPhotos | integer | Yes | — |
totals.withSteps | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/analytics/visits" \
-H "Authorization: Bearer $ACCESS_TOKEN"