Skip to content

Frames

A frame defines the axis of evaluation used by positions on a table. It carries four values, each one with a label — they could be Dialectic, Diatribic, Didactic, Diabolical — and, for each of those four, the question a person answers and a word at each end of the scale they answer it on. Where a frame carries that text it arrives with the frame, so there is no wording for a client to hold its own copy of. Not every frame carries it, and the frame object says what a client sees when one doesn't.

Frames are immutable. There is no update endpoint: correcting one means deleting it and creating its replacement, which is only possible while no table is built on it. A frame's labels, questions, and end labels are the whole of what gives a plotted position its meaning, and one frame is shared by every table built on it, so an edit would change how positions on other people's tables read without moving a single coordinate.

That is what makes a frame worth holding on to. Fetch the collection once and match tables against it locally by their frame_id, rather than fetching a frame per table — a frame you already hold cannot have become wrong, only missing, and the next fetch resolves that.

The frame object

AttributeTypeDescription
iduuidThe unique identifier of the frame.
namestringName of the frame. Required, and must be unique across all frames.
val1stringThe first value's label. Required. Up to 50 characters.
val2stringThe second value's label. Required. Up to 50 characters.
val3stringThe third value's label. Required. Up to 50 characters.
val4stringThe fourth value's label. Required. Up to 50 characters.
val1_questionstringThe question answered for the first value. Up to 255 characters.
val1_min_labelstringThe label at the low end of the first value's scale. Up to 50 characters.
val1_max_labelstringThe label at the high end of the first value's scale. Up to 50 characters.
val2_questionstringThe question answered for the second value. Up to 255 characters.
val2_min_labelstringThe label at the low end of the second value's scale. Up to 50 characters.
val2_max_labelstringThe label at the high end of the second value's scale. Up to 50 characters.
val3_questionstringThe question answered for the third value. Up to 255 characters.
val3_min_labelstringThe label at the low end of the third value's scale. Up to 50 characters.
val3_max_labelstringThe label at the high end of the third value's scale. Up to 50 characters.
val4_questionstringThe question answered for the fourth value. Up to 255 characters.
val4_min_labelstringThe label at the low end of the fourth value's scale. Up to 50 characters.
val4_max_labelstringThe label at the high end of the fourth value's scale. Up to 50 characters.
json
{
  "id": "9651ded6-b2d8-451e-b4ac-3bce40c9201c",
  "name": "Rhetorical",
  "val1": "Dialectic",
  "val2": "Diatribic",
  "val3": "Didactic",
  "val4": "Diabolical",
  "val1_question": "How well does this hold up under argument?",
  "val1_min_label": "Falls apart",
  "val1_max_label": "Holds firm",
  "val2_question": "How strongly does this provoke you?",
  "val2_min_label": "Barely",
  "val2_max_label": "Fiercely",
  "val3_question": "How much does this teach you?",
  "val3_min_label": "Nothing new",
  "val3_max_label": "Genuinely instructive",
  "val4_question": "How mischievous is this?",
  "val4_min_label": "Wholesome",
  "val4_max_label": "Fiendish"
}

A value's question and its two end labels arrive together or not at all: a frame carries the question and both end labels for all four of its values, or carries none of the twelve. There is no partial set, so a client meets one of exactly two shapes.

These twelve are where a frame's presentation text lives — the question to put in front of a person, and the words to label each end of the scale they answer on. A frame created before the fields existed has all twelve null, and no request will fill them in: a frame is never edited, so there is no endpoint that adds this text to a frame that came without it. So read them with a fallback rather than an assumption. Every frame created through the API carries all twelve, which is a statement about new frames rather than a guarantee about the one in front of you.

The question's voice belongs to the frame. One frame may ask a person about themselves — how important is this to you? — where another asks them to place a subject. Within a single frame all four questions address the same subject in the same voice, so the four read as one coherent set.

Creating a frame

POST https://api.cxipgroup.com/frames
Admin token required

To create a frame, send an authenticated request to the above endpoint with the frame's attributes in the body. Every parameter below is required: a frame cannot be created without the question and end labels for each of its four values, and an empty string is refused the same way a missing field is.

Parameters:

ParameterValueDescription
namestring (required)The frame's name. Must be unique across all frames.
val1string (required)The first value's label. Up to 50 characters.
val2string (required)The second value's label. Up to 50 characters.
val3string (required)The third value's label. Up to 50 characters.
val4string (required)The fourth value's label. Up to 50 characters.
val1_questionstring (required)The question answered for the first value. Up to 255 characters.
val1_min_labelstring (required)The label at the low end of the first value's scale. Up to 50 characters.
val1_max_labelstring (required)The label at the high end of the first value's scale. Up to 50 characters.
val2_questionstring (required)The question answered for the second value. Up to 255 characters.
val2_min_labelstring (required)The label at the low end of the second value's scale. Up to 50 characters.
val2_max_labelstring (required)The label at the high end of the second value's scale. Up to 50 characters.
val3_questionstring (required)The question answered for the third value. Up to 255 characters.
val3_min_labelstring (required)The label at the low end of the third value's scale. Up to 50 characters.
val3_max_labelstring (required)The label at the high end of the third value's scale. Up to 50 characters.
val4_questionstring (required)The question answered for the fourth value. Up to 255 characters.
val4_min_labelstring (required)The label at the low end of the fourth value's scale. Up to 50 characters.
val4_max_labelstring (required)The label at the high end of the fourth value's scale. Up to 50 characters.

Request:

bash
curl -i "https://api.cxipgroup.com/frames" \
  -X POST \
  -H "Authorization: Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Deliberation",
    "val1": "Dialectic",
    "val2": "Wellness",
    "val3": "Reasoning",
    "val4": "Desirability",
    "val1_question": "How well does this hold up under argument?",
    "val1_min_label": "Falls apart",
    "val1_max_label": "Holds firm",
    "val2_question": "How much does this affect your wellbeing?",
    "val2_min_label": "No impact",
    "val2_max_label": "Strong impact",
    "val3_question": "How much have you thought about this?",
    "val3_min_label": "Quick reaction",
    "val3_max_label": "Well reasoned",
    "val4_question": "How much do you want this?",
    "val4_min_label": "Not at all",
    "val4_max_label": "Very much"
  }'
javascript
const response = await fetch("https://api.cxipgroup.com/frames", {
  method: "POST",
  body: JSON.stringify({
    name: "Deliberation",
    val1: "Dialectic",
    val2: "Wellness",
    val3: "Reasoning",
    val4: "Desirability",
    val1_question: "How well does this hold up under argument?",
    val1_min_label: "Falls apart",
    val1_max_label: "Holds firm",
    val2_question: "How much does this affect your wellbeing?",
    val2_min_label: "No impact",
    val2_max_label: "Strong impact",
    val3_question: "How much have you thought about this?",
    val3_min_label: "Quick reaction",
    val3_max_label: "Well reasoned",
    val4_question: "How much do you want this?",
    val4_min_label: "Not at all",
    val4_max_label: "Very much"
  }),
  headers: {
    "Content-type": "application/json; charset=UTF-8",
    "Authorization": "Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876"
  },
});

Response:

json
{
  "id": "b9cdcd91-8fe8-41dc-9b46-ae6eb5e3c751",
  "name": "Deliberation",
  "val1": "Dialectic",
  "val2": "Wellness",
  "val3": "Reasoning",
  "val4": "Desirability",
  "val1_question": "How well does this hold up under argument?",
  "val1_min_label": "Falls apart",
  "val1_max_label": "Holds firm",
  "val2_question": "How much does this affect your wellbeing?",
  "val2_min_label": "No impact",
  "val2_max_label": "Strong impact",
  "val3_question": "How much have you thought about this?",
  "val3_min_label": "Quick reaction",
  "val3_max_label": "Well reasoned",
  "val4_question": "How much do you want this?",
  "val4_min_label": "Not at all",
  "val4_max_label": "Very much"
}

Status codes:

StatusWhen
201 CreatedThe frame was created. Its URL is in the Location header.
401 UnauthorizedMissing or invalid token.
403 ForbiddenThe token is not an admin (adtk_) token.
422 Unprocessable ContentValidation failed. A name already in use lands here, as does a missing, blank, or over-long question or end label. The response body names the fields at fault.

Listing frames

GET https://api.cxipgroup.com/frames
User token required

To list frames, send an authenticated request to the above endpoint. This endpoint is paginated — the response is a bare array, with pagination metadata in the response headers.

Frames come back oldest first by created_at, with id settling any tie. The order is total, so paging the whole collection reaches every frame exactly once, and a frame created later goes to the end rather than displacing what is already there.

Parameters:

ParameterValueDescription
limitinteger (optional)The number of records to return per page. Defaults to 20, with a maximum of 100.
pageinteger (optional)The page of records you want returned. 0 or 1 returns the first page.

Request:

bash
curl -i -G "https://api.cxipgroup.com/frames" \
  -H "Authorization: Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876" \
  --data-urlencode "limit=100" \
  --data-urlencode "page=1"
javascript
const response = await fetch("https://api.cxipgroup.com/frames?limit=100&page=1", {
  method: "GET",
  headers: {
    "Content-type": "application/json; charset=UTF-8",
    "Authorization": "Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876"
  },
});

Response:

json
[
  {
    "id": "3fa26bc2-6a32-4655-be8d-1fc2cac1291a",
    "name": "Rhetorical",
    "val1": "Dialectic",
    "val2": "Diatribic",
    "val3": "Didactic",
    "val4": "Diabolical",
    "val1_question": "How well does this hold up under argument?",
    "val1_min_label": "Falls apart",
    "val1_max_label": "Holds firm",
    "val2_question": "How strongly does this provoke you?",
    "val2_min_label": "Barely",
    "val2_max_label": "Fiercely",
    "val3_question": "How much does this teach you?",
    "val3_min_label": "Nothing new",
    "val3_max_label": "Genuinely instructive",
    "val4_question": "How mischievous is this?",
    "val4_min_label": "Wholesome",
    "val4_max_label": "Fiendish"
  },
  {
    "id": "4fc443fc-5c06-42a7-8e09-e649b4b388d8",
    "name": "Kawaii",
    "val1": "Delectable",
    "val2": "Cute",
    "val3": "Clever",
    "val4": "Gross",
    "val1_question": "How much do you want to eat this?",
    "val1_min_label": "Not a bite",
    "val1_max_label": "All of it",
    "val2_question": "How cute is this?",
    "val2_min_label": "Plain",
    "val2_max_label": "Unbearably cute",
    "val3_question": "How clever is this?",
    "val3_min_label": "Obvious",
    "val3_max_label": "Ingenious",
    "val4_question": "How much does this put you off?",
    "val4_min_label": "Not at all",
    "val4_max_label": "Completely"
  }
]

Status codes:

StatusWhen
200 OKThe body is a bare array of frames.
401 UnauthorizedMissing or invalid token.
422 Unprocessable ContentA negative limit. Other unusable pagination values resolve rather than failing.

Getting a frame

GET https://api.cxipgroup.com/frames/:id
User token required

To retrieve a single frame by its id, send an authenticated request to the above endpoint.

Parameters:

ParameterValueDescription
iduuid (required)The unique identifier of the frame to retrieve.

Request:

bash
curl -i "https://api.cxipgroup.com/frames/9651ded6-b2d8-451e-b4ac-3bce40c9201c" \
  -H "Authorization: Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876"
javascript
const response = await fetch("https://api.cxipgroup.com/frames/9651ded6-b2d8-451e-b4ac-3bce40c9201c", {
  method: "GET",
  headers: {
    "Content-type": "application/json; charset=UTF-8",
    "Authorization": "Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876"
  },
});

Response:

json
{
  "id": "9651ded6-b2d8-451e-b4ac-3bce40c9201c",
  "name": "Rhetorical",
  "val1": "Dialectic",
  "val2": "Diatribic",
  "val3": "Didactic",
  "val4": "Diabolical",
  "val1_question": "How well does this hold up under argument?",
  "val1_min_label": "Falls apart",
  "val1_max_label": "Holds firm",
  "val2_question": "How strongly does this provoke you?",
  "val2_min_label": "Barely",
  "val2_max_label": "Fiercely",
  "val3_question": "How much does this teach you?",
  "val3_min_label": "Nothing new",
  "val3_max_label": "Genuinely instructive",
  "val4_question": "How mischievous is this?",
  "val4_min_label": "Wholesome",
  "val4_max_label": "Fiendish"
}

Status codes:

StatusWhen
200 OKThe body is the frame.
401 UnauthorizedMissing or invalid token.
404 Not FoundNo frame with that id.

Deleting a frame

DELETE https://api.cxipgroup.com/frames/:id
Admin token required

To delete a frame, send an authenticated request to the above endpoint. A successful delete returns an empty body.

Because frames are immutable, this is also how you correct one: delete it and create its replacement, which carries a new id. It only works while nothing is built on the frame — a frame any table points at is a 409 for as long as that table exists, so a frame already in use has no correction path.

Parameters:

ParameterValueDescription
iduuid (required)The unique identifier of the frame to delete.

Request:

bash
curl -i "https://api.cxipgroup.com/frames/9651ded6-b2d8-451e-b4ac-3bce40c9201c" \
  -X DELETE \
  -H "Authorization: Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876"
javascript
const response = await fetch("https://api.cxipgroup.com/frames/9651ded6-b2d8-451e-b4ac-3bce40c9201c", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer adtk_80573e65-c815-49d8-b7b9-75cf2f143876"
  },
});

Status codes:

StatusWhen
204 No ContentThe frame was deleted. The body is empty.
401 UnauthorizedMissing or invalid token.
403 ForbiddenThe token is not an admin (adtk_) token.
404 Not FoundNo frame with that id.
409 ConflictThe frame is still referenced by one or more tables.

Shapecaster API Documentation