Get Schema
curl --request GET \
--url https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"mode": "single",
"workflows": [
{
"workflow_id": 123,
"workflow_name": "<string>",
"fields": [
{
"id": "<string>",
"name": "<string>",
"type": "boolean",
"description": "",
"options": [
"<string>"
],
"optional": false
}
]
}
],
"text_word_frequency": true,
"shared_fields": [
{
"name": "<string>",
"type": "boolean",
"workflow_ids": [
123
],
"options": [
"<string>"
]
}
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Post-Call Variables
Get Extraction Schema
List extraction fields per workflow plus the cross-workflow intersection.
GET
/
api
/
v1
/
analytics
/
post-call-variables
/
schema
Get Schema
curl --request GET \
--url https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"mode": "single",
"workflows": [
{
"workflow_id": 123,
"workflow_name": "<string>",
"fields": [
{
"id": "<string>",
"name": "<string>",
"type": "boolean",
"description": "",
"options": [
"<string>"
],
"optional": false
}
]
}
],
"text_word_frequency": true,
"shared_fields": [
{
"name": "<string>",
"type": "boolean",
"workflow_ids": [
123
],
"options": [
"<string>"
]
}
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Return the extraction field schemas for one or more workflows. When more than one
workflow_id is supplied, the response also includes shared_fields — the intersection of field names present on every workflow in the request.
GET /api/v1/analytics/post-call-variables/schema
Use this endpoint to populate the field picker in an extraction chart builder — it’s the source of truth for which fields are chartable per workflow, and which are safe to chart across workflows.
Query parameters
string
required
Comma-separated list of workflow ids the caller owns. Non-integer entries return
400; an id from another organization returns 404.Response
string
"single" when exactly one workflow_id was supplied, otherwise "cross".array
One entry per requested workflow.
Show workflows[]
Show workflows[]
integer
string
array
Extraction field specs configured on the workflow.
Show fields[]
Show fields[]
string
Field id (stable across renames).
string
Field name — the key used to look up values in
post_call_data.data.string
One of
boolean, selector, number, text.string
Human description shown in the UI.
array | null
Allowed values for
selector fields; null for other types.boolean
Whether the LLM is allowed to skip this field.
array | null
The cross-workflow intersection.
null (or omitted) in single mode; always an array (possibly empty) in cross mode.Show shared_fields[]
Show shared_fields[]
string
Shared field name — must exist on every workflow in the request.
string
The unified type. A field with the same name but different types across workflows is dropped.
array | null
For
selector fields, the intersection of options across all workflows. A field whose selector-option intersection is empty is dropped.array
The subset of the request the field belongs to — in v1 this always equals the full request.
Cross-workflow mode
When you pass more than oneworkflow_id, the response describes both the per-workflow fields and the compatible set for cross-workflow charts. See Overview → Single vs. cross-workflow mode for the five common use cases (agent versions, regional variants, A/B, portfolio, drift monitoring).
The matching algorithm is spec’d in openspec/changes/post-call-variable-charts/design.md §D3:
- Intersect field
namesets across all requested workflows. - Drop names whose
typeis not the same on every workflow. - For
selectorfields, take the intersection ofoptionsacross all workflows; drop the field if the intersection is empty.
Example — single workflow
cURL
curl "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema?workflow_ids=42" \
-H "X-API-Key: $PEACHDESK_API_KEY"
Response
{
"mode": "single",
"workflows": [
{
"workflow_id": 42,
"workflow_name": "Intake v3",
"fields": [
{
"id": "fld_qualified",
"name": "qualified",
"type": "boolean",
"description": "Caller qualified for a callback",
"options": null,
"optional": false
},
{
"id": "fld_amount",
"name": "quoted_amount",
"type": "number",
"description": "Amount quoted during the call",
"options": null,
"optional": true
},
{
"id": "fld_reason",
"name": "cancel_reason",
"type": "selector",
"description": "Reason the caller wanted to cancel",
"options": ["price", "product", "support", "other"],
"optional": true
}
]
}
],
"shared_fields": null
}
Example — cross-workflow
cURL
curl "https://api.peachdeskai.com/api/v1/analytics/post-call-variables/schema?workflow_ids=42,43,44" \
-H "X-API-Key: $PEACHDESK_API_KEY"
Response
{
"mode": "cross",
"workflows": [
{ "workflow_id": 42, "workflow_name": "Intake US", "fields": [ /* ... */ ] },
{ "workflow_id": 43, "workflow_name": "Intake UK", "fields": [ /* ... */ ] },
{ "workflow_id": 44, "workflow_name": "Intake AU", "fields": [ /* ... */ ] }
],
"shared_fields": [
{
"name": "qualified",
"type": "boolean",
"options": null,
"workflow_ids": [42, 43, 44]
},
{
"name": "cancel_reason",
"type": "selector",
"options": ["price", "product"],
"workflow_ids": [42, 43, 44]
}
]
}
Errors
| Status | When |
|---|---|
400 | workflow_ids is missing, empty, or contains a non-integer id. |
400 | No organization is selected on the caller. |
404 | Any workflow_id does not belong to the caller’s organization. |
Authorizations
SessionAuthApiKeyAuth
Interactive user session: the login JWT, sent as Authorization: Bearer <token>.
Query Parameters
Comma-separated workflow ids

