Objects
Objects are your workspace's record systems — Deals, Candidates, Properties, whatever you track — plus Attria's built-in ones. Agents read and write them; your code can too, with the same checks the app applies.
#Objects and fields
List the objects to learn each one's key and fields. A field's key is what record values use; its type says what a value may be; choice fields list their options.
curl "https://app.attria.io/api/v1/objects?kind=custom" \
-H "Authorization: Bearer $ATTRIA_API_KEY"const res = await fetch("https://app.attria.io/api/v1/objects?kind=custom", {
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
},
});
const page = await res.json();import os, requests
res = requests.get(
"https://app.attria.io/api/v1/objects?kind=custom",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
},
timeout=30,
)
page = res.json()| kind | Is |
|---|---|
custom | Record systems the workspace made. Their records live under /v1/objects/{key}/records. |
system | Attria's built-in objects (agents, websites, image_boards, video_boards, files). They can be linked to and carry extra fields; their records belong to their own feature. |
#Make an object
The same thing New object makes in the app. Its key is the plural name in snake_case (Deals → deals) and never changes, so code that uses it keeps working. If the key is taken the answer is 409, so a retried create never makes a twin.
curl -X POST "https://app.attria.io/api/v1/objects" \
-H "Authorization: Bearer $ATTRIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"singular_name": "Deal",
"plural_name": "Deals",
"fields": [
{
"label": "Name",
"type": "text",
"required": true
},
{
"label": "Value",
"type": "currency"
},
{
"label": "Stage",
"type": "stage",
"options": [
"New",
"Proposal",
"Won",
"Lost"
]
},
{
"label": "Contact email",
"type": "email"
}
]
}'const res = await fetch("https://app.attria.io/api/v1/objects", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
singular_name: "Deal",
plural_name: "Deals",
fields: [
{
label: "Name",
type: "text",
required: true,
},
{
label: "Value",
type: "currency",
},
{
label: "Stage",
type: "stage",
options: ["New", "Proposal", "Won", "Lost"],
},
{
label: "Contact email",
type: "email",
},
],
}),
});
const object = await res.json();import os, uuid, requests
res = requests.post(
"https://app.attria.io/api/v1/objects",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"singular_name": "Deal",
"plural_name": "Deals",
"fields": [
{
"label": "Name",
"type": "text",
"required": True,
},
{
"label": "Value",
"type": "currency",
},
{
"label": "Stage",
"type": "stage",
"options": ["New", "Proposal", "Won", "Lost"],
},
{
"label": "Contact email",
"type": "email",
},
],
},
timeout=30,
)
object = res.json()#Write records
values is keyed by field key and checked exactly as the app checks it: unknown keys, missing required fields and wrong types are refused with 422 and a message naming the field. Choice fields take an option's id or its label.
curl -X POST "https://app.attria.io/api/v1/objects/deals/records" \
-H "Authorization: Bearer $ATTRIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"values": {
"name": "Acme renewal",
"value": 12000,
"stage": "Proposal",
"contact_email": "ana@acme.com"
}
}'const res = await fetch("https://app.attria.io/api/v1/objects/deals/records", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
values: {
name: "Acme renewal",
value: 12000,
stage: "Proposal",
contact_email: "ana@acme.com",
},
}),
});
const record = await res.json();import os, uuid, requests
res = requests.post(
"https://app.attria.io/api/v1/objects/deals/records",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"values": {
"name": "Acme renewal",
"value": 12000,
"stage": "Proposal",
"contact_email": "ana@acme.com",
},
},
timeout=30,
)
record = res.json()Updates change only the keys you send, merged under a row lock so they never overwrite an edit an agent or a person made a moment earlier. Send null to clear a field.
curl -X PATCH "https://app.attria.io/api/v1/objects/deals/records/3e8d1c2b-7a6f-4e5d-9c8b-1a2f3e4d5c6b" \
-H "Authorization: Bearer $ATTRIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"values": {
"stage": "Won",
"value": 14500
}
}'const res = await fetch("https://app.attria.io/api/v1/objects/deals/records/3e8d1c2b-7a6f-4e5d-9c8b-1a2f3e4d5c6b", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
values: {
stage: "Won",
value: 14500,
},
}),
});
const record = await res.json();import os, uuid, requests
res = requests.patch(
"https://app.attria.io/api/v1/objects/deals/records/3e8d1c2b-7a6f-4e5d-9c8b-1a2f3e4d5c6b",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"values": {
"stage": "Won",
"value": 14500,
},
},
timeout=30,
)
record = res.json()#Query records
curl "https://app.attria.io/api/v1/objects/deals/records?filter=%7B%22stage%22%3A%22Won%22%7D&sort=-value&limit=20" \
-H "Authorization: Bearer $ATTRIA_API_KEY"const res = await fetch("https://app.attria.io/api/v1/objects/deals/records?filter=%7B%22stage%22%3A%22Won%22%7D&sort=-value&limit=20", {
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
},
});
const page = await res.json();import os, requests
res = requests.get(
"https://app.attria.io/api/v1/objects/deals/records?filter=%7B%22stage%22%3A%22Won%22%7D&sort=-value&limit=20",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
},
timeout=30,
)
page = res.json()| Parameter | Does |
|---|---|
filter | A JSON object of field key → value; every pair must match. A choice matches by id or label; for a multi_select a list matches records that contain all of it; null matches an empty field. |
search | Text found anywhere in the record's values, case-insensitive. |
sort | updated_at, created_at or any field key; prefix - for descending. Default -updated_at. |
limit | Page size; pass the previous page's next_cursor as cursor. |
#Relationships
Link any record to any other under a relation_key such as company or owner — including built-in objects, like an agent. Sending the same link again returns the existing one.
curl -X POST "https://app.attria.io/api/v1/objects/deals/records/3e8d1c2b-7a6f-4e5d-9c8b-1a2f3e4d5c6b/relationships" \
-H "Authorization: Bearer $ATTRIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"relation_key": "company",
"target": {
"object": "companies",
"id": "0b6f4e3d-2c1b-4a9f-8e7d-6c5b4a3f2e1d"
},
"label": "Buyer"
}'const res = await fetch("https://app.attria.io/api/v1/objects/deals/records/3e8d1c2b-7a6f-4e5d-9c8b-1a2f3e4d5c6b/relationships", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTRIA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
relation_key: "company",
target: {
object: "companies",
id: "0b6f4e3d-2c1b-4a9f-8e7d-6c5b4a3f2e1d",
},
label: "Buyer",
}),
});
const relationship = await res.json();import os, uuid, requests
res = requests.post(
"https://app.attria.io/api/v1/objects/deals/records/3e8d1c2b-7a6f-4e5d-9c8b-1a2f3e4d5c6b/relationships",
headers={
"Authorization": f"Bearer {os.environ['ATTRIA_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"relation_key": "company",
"target": {
"object": "companies",
"id": "0b6f4e3d-2c1b-4a9f-8e7d-6c5b4a3f2e1d",
},
"label": "Buyer",
},
timeout=30,
)
relationship = res.json()Deleting a record also deletes every relationship to or from it, and can't be undone.
#Endpoints
- GET
/v1/objectsList Objects - POST
/v1/objectsCreate an Object - GET
/v1/objects/{object}Get an Object - PATCH
/v1/objects/{object}Change an Object - GET
/v1/objects/{object}/recordsList and query records - POST
/v1/objects/{object}/recordsCreate a record - GET
/v1/objects/{object}/records/{id}Get a record - PATCH
/v1/objects/{object}/records/{id}Update a record - del
/v1/objects/{object}/records/{id}Delete a record - GET
/v1/objects/{object}/records/{id}/relationshipsList a record's relationships - POST
/v1/objects/{object}/records/{id}/relationshipsLink a record to another