curl --request GET \
--url https://api.instaview.sk/contact-fields \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.instaview.sk/contact-fields"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.instaview.sk/contact-fields', 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.instaview.sk/contact-fields",
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.instaview.sk/contact-fields"
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.instaview.sk/contact-fields")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.instaview.sk/contact-fields")
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{
"data": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"key": "order_number",
"label": "Order number",
"dataType": "string",
"category": "commercial",
"isPii": false,
"isSystem": false,
"allowPiiInContext": false,
"inEssentialPromptSet": false,
"displayOrder": 50,
"isCompanyOverride": false,
"readOnly": false,
"writable": true,
"enumOptions": [
"pricing page",
"webinar",
"referral"
],
"csvAliases": [
"Order #",
"OrderNo"
],
"description": "The order this call is about"
}
],
"total": 12
}List Contact Fields
Every field your contacts can carry: the platform’s seeded fields merged with your own, which shadow a seeded field of the same key. Read this to learn which keys fields accepts on POST /contacts and PATCH /contacts/{id}, and what each one expects.
curl --request GET \
--url https://api.instaview.sk/contact-fields \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.instaview.sk/contact-fields"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.instaview.sk/contact-fields', 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.instaview.sk/contact-fields",
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.instaview.sk/contact-fields"
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.instaview.sk/contact-fields")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.instaview.sk/contact-fields")
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{
"data": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"key": "order_number",
"label": "Order number",
"dataType": "string",
"category": "commercial",
"isPii": false,
"isSystem": false,
"allowPiiInContext": false,
"inEssentialPromptSet": false,
"displayOrder": 50,
"isCompanyOverride": false,
"readOnly": false,
"writable": true,
"enumOptions": [
"pricing page",
"webinar",
"referral"
],
"csvAliases": [
"Order #",
"OrderNo"
],
"description": "The order this call is about"
}
],
"total": 12
}Overview
A contact field is a typed, named slot on a contact —order_number, lead_source,
renewal_date. Two things make a field different from a note you keep on your own side:
- An agent can speak it.
{{contact.order_number}}in an agent’s prompt is replaced with this contact’s value at the moment the call is placed. - The platform validates it. A field declared
numberrejects"twelve"on the way in, rather than surfacing as a confused agent mid-call.
PATCH /contacts/{id} will accept
and how each value must be shaped.
category if you want them grouped the way
the dashboard groups them.What you get back
Two kinds of field, merged into one list:| Where it comes from | Can you change it? | |
|---|---|---|
isSystem: true | Seeded by InstaView for every company | No — but most can be shadowed |
isSystem: false | Defined by you | Yes |
isCompanyOverride: true.
first_name, last_name,
email, phone, company_name, company_description, agent_name and profile. A
POST /contact-fields on one of those is refused — the platform resolves them itself, so a
company definition would be advertised in the palette and then ignored on the call.isSystem: true alone does not tell you which is which, because most seeded keys
(order_number, is_vip, lead_source) can be shadowed. Check writable if what you
need to know is whether you can send a value for a key.GET /contact-fields
{
"data": [
{
"id": "3f1b...",
"key": "first_name",
"label": "First name",
"dataType": "string",
"category": "identity",
"isPii": true,
"isSystem": true,
"displayOrder": 10,
"isCompanyOverride": false,
"readOnly": false,
"writable": false
},
{
"id": "9c22...",
"key": "renewal_date",
"label": "Renewal date",
"dataType": "date",
"category": "commercial",
"csvAliases": ["renewal", "renewal date", "renews", "dátum obnovenia"],
"isPii": false,
"isSystem": true,
"displayOrder": 50,
"isCompanyOverride": false,
"readOnly": false,
"writable": true
}
],
"total": 36
}
Reading the flags
dataType — how a value is validated
dataType — how a value is validated
string, number, date, bool, enum or tags. A write is checked against it: a
number field takes 42 or "42" but not "twelve"; a bool field takes true,
"true", "yes" or "1" and their negatives, but not "maybe"; a date field is stored
as an ISO timestamp; an enum field takes only a value from its own enumOptions.A tags field stores a string[] and is the one type that accepts two shapes: an array,
or a comma-separated string, so one CSV cell holding several tags maps onto one field.
See Set Contact Fields
for what it trims, de-duplicates and treats as an erase.category — which panel the field belongs to
category — which panel the field belongs to
identity, organisation, commercial, relationship, scheduling,
recruiting, platform or custom. It is the grouping the dashboard’s variable palette
uses, and the first key this list is ordered by — so iterating the response and breaking on
a change of category gives you the same panels a user sees.Set by InstaView and not writable. A field you define is always custom; a field of yours
that shadows a seeded one reports the seeded field’s category, so job_title stays
under organisation for everybody even after you relabel it.isPii — personal data, and what it keeps out of a call
isPii — personal data, and what it keeps out of a call
email
and phone off every call without anyone deciding, and it is enforced rather than
defaulted.Two things get past it. inEssentialPromptSet below, which is ours — first_name is
personal data and is also the first word of the call. And allowPiiInContext, which is
yours: set it on the one field an agent has to be able to say, and the value joins both the
document and the prompt. For a collections agent the amount owed is the entire reason for
the call. Setting it on a field that is not isPii is a 400, not a no-op.allowPiiInContext — let one personal field through
allowPiiInContext — let one personal field through
isPii field. See
Create Contact Field.inEssentialPromptSet — in the prompt, not just queryable
inEssentialPromptSet — in the prompt, not just queryable
contextConfig.useContactContext
on the agent. There is no per-field opt-in to maintain: define fields, store values, and an
agent with the switch on can use them.readOnly — catalogued but not storable
readOnly — catalogued but not storable
company_description is your company’s own blurb, agent_name is the
agent’s. Sending a value for one is a 422 naming the key. They are listed here because an agent author
still needs to see them.writable — whether you can send a value
writable — whether you can send a value
!readOnly. Look at
first_name in the response above: readOnly is false, and a value for it is still
refused with a 422. It is one of the keys the platform RESERVES — the identity fields
(first_name, last_name, email, phone) plus company_name, company_description,
agent_name and profile. Those four identity fields are writable, just as properties of
the contact itself rather than as fields.So readOnly answers “where does this value come from” and writable answers “will this
endpoint take one from me”. writable: false always means do not send a value for this key;
it covers every readOnly field as well as every reserved one.csvAliases — extra header names for imports
csvAliases — extra header names for imports
Order # can be recognised as order_number rather than
mapped by hand.Every writable seeded field arrives with aliases in English, Slovak and Czech —
renewal_date carries renewal, renews, dátum obnovenia and more — ready for the
importer to match on. Adding your own with
PATCH /contact-fields/{id} does not
touch InstaView’s. Read the warning below first: nothing consumes any of them yet.csvAliases today changes no import behaviour. It is stored so the catalog is complete
before the contact-field import lands. Until then, map these columns explicitly.id vs key
id vs key
id exists only to address PATCH and DELETE. Everywhere else — a prompt token, a
values payload, a CSV mapping — a field is addressed by key.Ordering and paging
Ordered bycategory first — in the fixed order identity, organisation, commercial,
relationship, scheduling, recruiting, platform, custom — then by displayOrder, then
by key. displayOrder therefore only ever separates fields within one category, which is
why each category’s own numbering restarts rather than continuing one long sequence.
Unpaginated: your whole catalog is smaller than one page of any other list endpoint, so there
is nothing to page through.
Scopes
read:contacts (or its read:candidates alias). Changing the catalog needs write:contacts.
Nothing to rotate: any key that can already read your contacts can read their field catalog.
Related Resources
Create Contact Field
Update Contact
Get Contact
Update Contact Field
Authorizations
API key for authentication using Bearer scheme
Query Parameters
Required for ATS API keys to specify which company to access. Ignored for standard company API keys.