Every Core dna site answers three kinds of API request under /cdna-api: REST for everything, GraphQL for reads that span several entity types, and web events for endpoints you define yourself as jobs. Which fits which task, one worked request for each, and what is true of all three. Jobs were called hooks until the module was renamed Orchestration; the API's routes still use the old name.
L1–L3
Unit 01 · The REST API
Shaping the response with properties
The REST APIPage 3 of 25Updated
One parameter decides what a response contains: properties, a selector that names fields, renames them, reaches into relations and calls getters with arguments. How to write one, what shape the response then takes, and how a mistake shows up, which is not as an error.
Who this is for. Every API reader. Leave properties out and a record comes back with its whole default projection: this site's How-to blog answers with more than forty fields, counts and paths included. Name what you need, every time; the response is smaller, faster and does not change shape when the model gains a field.
The selector
A selector is a list of fields in braces, separated by commas. Inside it:
A relation in braces returns the related record with the fields you name: parent{id,name}. A to-many relation returns a list: children{id,name}.
A dotted path reaches into a relation and returns one value, flat, under its last segment: activeRevision.name comes back as name.
An alias renames anything: title:activeRevision.name.
A getter with arguments takes them by name, in brackets: created(format:"j M Y").
An alias, a getter with an argument and a relation
GET /cdna-api/pages/page/72?properties={id,title:activeRevision.name,created(format:"Y-m-d"),parent{id,name}} HTTP/1.1
Host: hub.coredna.com
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
{
"result": "success",
"data": {
"idname": "Error: Getter for property idname in class Pages\\Models\\Api\\Response\\Page not found"
}
}
Real response from this documentation site
That is also how any field the model does not have shows up, at any depth: a string starting with Error: in place of the value, inside a successful response. parent{id,nmae} returns the parent's id and an error string for nmae. A client that does not check for it will render the message on a page. In tests, fail on any string value that begins with Error: Getter for property.
Reading layout areas
On a versioned record (a page, a book page, a blog post, an FAQ, a custom entity record) the layout areas belong to the revision, not to the record, so the layout area getters are asked of activeRevision. areaText(name) returns a layout area's text, areaValues(name) a multiselect's values as a list. Nest them under the revision, or reach them with a dotted path and an alias to keep the response flat:
A layout area's text, read through the active revision
GET /cdna-api/pages/pages?parent.id=72&properties={id,name,lede:activeRevision.areaText(lede)} HTTP/1.1
Host: hub.coredna.com
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
Response200 OK
{
"result": "success",
"totalCount": 2,
"data": [
{
"id": 818,
"name": "API Reference",
"lede": "Every endpoint of the Core dna REST API, with requests to copy in five languages and the real responses they return."
},
{
"id": 1878,
"name": "Reference",
"lede": null
}
]
}
Real response from this documentation site
Asked of the record itself, lede:areaText(lede) is an Error: string, because the record has no such getter. A page whose layout has no layout area of that name returns null, as page 1878 does above. To see every layout area with its type and value at once, select activeRevision{areasContent}: it is verbose, and the quickest way to learn a layout you have not met.
The shape of data
How you write the selector decides where the record sits in the response:
Selector
A list
One record
Bare: {id,name}
data is the list
data is the record
Wrapped in the entity name: {pages{id,name}}, {page{id,name}}
data.pages
data.page
None
data.pages, every default field
data.page, every default field
Pick one form for a client and keep to it; the bare selector gives the simplest code. totalCount stays beside data in every case. Writes answer the same way: PUT /cdna-api/pages/page/72?properties={id,name} returns the saved page as data, without one under data.page.
Where the selector goes
On a GET, in the query string, or in the request body when it is too long for a URL. On a POST or PUT, always in the query string, because the body holds the record. Query string or request body covers both. The same selector language drives the GraphQL endpoint, so what you learn here carries over.