atteq API
  • Guides
  • Recipes
  • Cookbook
  • API Reference
Information
agents
    List AgentsgetCreate AgentpostDocument AttachmentsgetGet VersiongetEdit DraftpatchReplace Draft GraphputPublish VersionpostGet AgentgetDelete AgentdeleteCopy AgentpostGet DraftgetGet Agent MapgetPending ChangesgetList PlacementsgetRestore VersionpostList VersionsgetGet Mapget
voice_agent
    Open Browser CallpostEnd Browser CalldeleteGet Agent Test LinkgetGet Bridge CeilinggetSet Bridge Ceilingpatch
ai_profiles
    Get Ai Profile CapabilitiesgetList Live SettingsgetCreate Live SettingspostDelete Live SettingsdeleteUpdate Live SettingspatchList Llm SettingsgetCreate Llm SettingspostDelete Llm SettingsdeleteUpdate Llm SettingspatchList ProfilesgetCreate ProfilepostGet ProfilegetDelete ProfiledeleteUpdate ProfilepatchCopy ProfilepostSet Text SectionputSet Voice SectionputList Stt SettingsgetCreate Stt SettingspostDelete Stt SettingsdeleteUpdate Stt SettingspatchList Tts SettingsgetCreate Tts SettingspostDelete Tts SettingsdeleteUpdate Tts SettingspatchList Vad SettingsgetCreate Vad SettingspostDelete Vad SettingsdeleteUpdate Vad Settingspatch
analyst
    List Agent FindingsgetCall Back FindingpostDismiss FindingpostUndo Finding DismissaldeleteTeach FindingpostWatch FindingpostList Question ChartsgetList Tracked QuestionsgetCreate Tracked QuestionpostGet Question Search CostgetSearch For Tracked QuestionpostPropose Tracked QuestionpostDelete Tracked QuestiondeleteUpdate Tracked QuestionpatchGet Reading SwitchgetSet Reading SwitchputGet Agent Summaryget
analytics
    List ChartsgetCreate ChartpostPreview ChartpostGet ChartgetDelete ChartdeleteUpdate ChartpatchRun ChartpostList DatasetsgetList BoardsgetCreate BoardpostGet TraversalgetGet BoardgetDelete BoarddeleteUpdate Boardpatch
authentication
    List InvitationsgetInvite MemberpostRevoke InvitationdeleteResend InvitationpostList MembersgetRemove MemberdeleteGet Member Conversation AccessgetSet Member Conversation AccesspatchSet Member FlagspatchSet Member RolepatchGet OrganizationgetUpdate OrganizationpatchGet Role FlagsgetSet Role Flagspatch
automations
    List AutomationsgetCreate AutomationpostGet AutomationgetDelete AutomationdeleteUpdate AutomationpatchSet Automation EnabledputGet Automation MapgetRun AutomationpostList Automation RunsgetGet Automation Runget
billable-metrics
    List MetricsgetUsage SummarygetGet Metricget
outbound_calls
    Place CallpostList CampaignsgetCreate CampaignpostGet CampaigngetDelete CampaigndeleteUpdate CampaignpatchActivate CampaignpostLink CollectionpostAdd ContactspostAdd Contacts From CollectionpostRemove Contacts From CollectionpostSet Campaign HoursputPreview Campaign HourspostPause CampaignpostGet Campaign SummarygetExclude ContactpostInclude Contactpost
channels
    List ChannelsgetCreate ChannelpostList Thread SubjectsgetClose Channel ThreadpostList Thread DecisionsgetGet Thread Contact FilegetHand Thread To AgentpostList Thread MailgetGet Prepared ReplygetAsk Again For Prepared ReplypostDiscard Prepared ReplypostSend Prepared ReplypostReply On Channel ThreadpostGet ChannelgetDelete ChanneldeleteUpdate ChannelpatchSend On ChannelpostList Channel ThreadsgetList RostergetCreate Roster EntrypostGet Own Roster EntrygetGet Roster EntrygetDelete Roster EntrydeleteUpdate Roster EntrypatchAdd Roster AddresspostChange Roster AddressputRemove Roster Addressdelete
custom-data
    List CollectionsgetCreate CollectionpostList Collection NamesgetGet CollectiongetDelete CollectiondeleteUpdate CollectionpatchAdd FieldpostDelete FielddeleteUpdate FieldpatchImport RecordspostPlan ImportpostPropose ImportpostGet ImportgetList RecordsgetCreate RecordpostBulk Delete RecordspostBulk Set FieldpostCount RecordsgetList Records Of ContactgetDelete Records Of ContactdeleteGet RecordgetDelete RecorddeleteUpdate Recordpatch
connections
    List ConnectionsgetCreate ConnectionpostCreate Forwarded AddresspostCreate Mail ServerpostDiscover Mail ServerpostAuthorize Microsoft MailboxpostList ProvidersgetGet ConnectiongetDelete ConnectiondeleteUpdate ConnectionpatchGet Forwarded AddressgetCheck Forwarded AddresspostList Person GrantsgetSet Person GrantputRemove Person GrantdeleteGet Mail ServergetUpdate Mail ServerpatchList Mail Server FoldersgetEnter Mail Server PasswordputChange Mail Server ServersputTest Mail Server AgainpostGet Microsoft MailboxgetUpdate Microsoft MailboxpatchList Microsoft Mailbox FoldersgetConsent To Microsoft Mailbox WritespostWithdraw Microsoft Mailbox Writesdelete
custom-tools
    List Custom ToolsgetCreate Custom ToolpostGet Custom ToolgetDelete Custom TooldeleteGet Custom Tool DraftgetEdit Custom Tool DraftpatchPublish Custom ToolpostRestore Custom Tool VersionpostTry Custom ToolpostList Custom Tool Versionsget
rag
    List DocumentsgetUpload DocumentpostSearch DocumentspostGet DocumentgetDelete DocumentdeleteDownload DocumentgetReingest Documentpost
flows
    List FlowsgetCreate FlowpostGet FlowgetDelete FlowdeleteRename FlowpatchAdd Flow EdgepostDelete Flow EdgedeleteSet Entry SteppatchAdd SteppostDelete StepdeleteUpdate SteppatchTest FlowpostList Flow Testsget
dynamic_context
    Create GraphpostGet GraphgetDelete GraphdeleteAdd EdgepostDelete EdgedeleteAdd NodepostDelete NodedeleteUpdate NodepatchSet Rootput
inbox
    Get Inbox Open CountgetSet Inbox PreferencespatchGet Inbox RailgetCreate Inbox ViewpostDelete Inbox ViewdeleteUpdate Inbox Viewpatch
handoff
    Assign Threadpost
interactions
    List InteractionsgetCount InteractionsgetGet InteractiongetSet Conversation LabelspostGet TracegetGet TranscriptgetList LabelsgetCreate LabelpostDelete LabeldeleteUpdate Labelpatch
legal
    Agree To Processing AgreementpostAgree To TermspostLegal BoxesgetList Legal DocumentsgetRead Legal DocumentgetList Legal VersionsgetRead Legal VersiongetDownload Legal VersiongetOrganization Legal HistorygetOwn Legal HistorygetObject To SubprocessorspostWithdraw ObjectionpostLegal Pendingget
not-a-tool
    Agree To Processing AgreementpostAgree To TermspostObject To SubprocessorspostWithdraw Objectionpost
memory
    List MemoriesgetList Memory LinesgetCreate Memory LinepostDelete Memory LinedeleteUpdate Memory LinepatchList Memory PeoplegetGet Memory PersongetForget PersondeleteGet Memory SwitchgetSet Memory SwitchputWipe ContactdeleteGet Conversation MemorygetRecall MemoriespostGet MemorygetDelete MemorydeletePatch Memorypatch
notifications
    List InboxgetGet Unread CountgetMark ReadpostMark Unreaddelete
recipes
    List RecipesgetList Installed RecipesgetGet Installed RecipegetUninstall RecipedeleteSet Recipe EnabledputUpdate Recipe ParameterspatchUpdate RecipepostInstall Recipepost
data-retention
    Get RetentiongetSet Retentionpatch
text
    Open ConversationpostClose ConversationpostAnswer ConfirmationpostGet Sent FilegetSend MessagepostSet Modepatch
tools
    List ToolsgetCreate ToolpostList BuiltinsgetImport Mcp ServerpostImport OpenapipostPreview Openapi ImportpostSuggest Tool ExamplespostGet ToolgetDelete TooldeleteUpdate ToolpatchTest ToolpostList Tool Testsget
trunks
    List Transfer DirectorygetCreate Transfer Directory EntrypostGet Transfer Directory EntrygetDelete Transfer Directory EntrydeleteUpdate Transfer Directory EntrypatchList TrunksgetCreate TrunkpostGet TrunkgetDelete TrunkdeleteUpdate TrunkpatchList Forward Recordsget
Schemas
powered by Zudoku
attek API
attek API

custom-data


List Collections

GET
/api/v1/collections

List this organization's collections, oldest first, each with its declared fields (type, required, personal), its identity field and the ids of the query, get and write tools an agent reaches it through.

List Collections › Responses

200

Successful Response

​CollectionOut[]
CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
GET/api/v1/collections
curl /api/v1/collections \ --header 'Authorization: Bearer <token>'
Example Responses
[ { "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" } ]
json
application/json

Create Collection

POST
/api/v1/collections

Create a collection: the place for every fact of the client's business the agent must read or write, such as opening hours, prices, services, customers. Use when the agent needs to read or write structured data instead of having a fact hard-coded into a prompt, because a record is edited while a prompt is republished.

A collection is a named set of records with a declared schema. Each field has a type, is optional or required, and is marked personal or not. Three tools appear with it — query, get and write — so an agent can reach it with no further setup.

Create Collection › Request Body

CollectionCreate
name
​string · minLength: 1 · maxLength: 200 · required
description
​string
Default:
​FieldIn[]
​

Create Collection › Responses

Successful Response

CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
POST/api/v1/collections
curl /api/v1/collections \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "description": "", "fields": [ { "default": { "kind": "value", "offset_days": 0, "value": {} }, "key": "key", "label": "label", "options": [ "string" ], "personal": false, "required": false, "type": "text", "width": 64 } ], "name": "name", "slug": "string" }'
Example Request Body
{ "description": "", "fields": [ { "default": { "kind": "value", "offset_days": 0, "value": {} }, "key": "key", "label": "label", "options": [ "string" ], "personal": false, "required": false, "type": "text", "width": 64 } ], "name": "name", "slug": "string" }
json
Example Responses
{ "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" }
json
application/json

List Collection Names

GET
/api/v1/collections/names

The lean list a picker reads from — id and name only, no fields, no flag. Use when offering a collection picker that only needs names, not schemas.

List Collection Names › Responses

200

Successful Response

​CollectionNameOut[]
The lean row `GET /collections/names` answers — id and name only, for a picker that stays open without the `databases` flag (rule 21).
CollectionNameOut
id
​string · uuid · required
name
​string · required
GET/api/v1/collections/names
curl /api/v1/collections/names \ --header 'Authorization: Bearer <token>'
Example Responses
[ { "id": "00000000-0000-0000-0000-000000000000", "name": "name" } ]
json
application/json

Get Collection

GET
/api/v1/collections/{collection_id}

Read one collection: its declared fields (type, required, personal), its identity field and the ids of the query, get and write tools an agent reaches it through.

Get Collection › path Parameters

collection_id
​string · uuid · required

Get Collection › Responses

Successful Response

CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
GET/api/v1/collections/{collection_id}
curl /api/v1/collections/:collection_id \ --header 'Authorization: Bearer <token>'
Example Responses
{ "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" }
json
application/json

Delete Collection

DELETE
/api/v1/collections/{collection_id}

Delete a collection, its records and its three tools permanently. Use when the collection and everything in it should stop existing.

Agents that referenced those tools stop being able to call them.

Delete Collection › path Parameters

collection_id
​string · uuid · required

Delete Collection › Responses

Successful Response

No data returned
DELETE/api/v1/collections/{collection_id}
curl /api/v1/collections/:collection_id \ --request DELETE \ --header 'Authorization: Bearer <token>'
Example Responses
No example specified for this content type

Update Collection

PATCH
/api/v1/collections/{collection_id}

Rename a collection, or say which of its fields identifies a record. Use when the collection's name or identity field needs to change.

The identity field is any field you declared — it is what decides whether two records are the same thing, and what an import merges on.

Update Collection › path Parameters

collection_id
​string · uuid · required

Update Collection › Request Body

CollectionUpdate
​
​
​

Update Collection › Responses

Successful Response

CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
PATCH/api/v1/collections/{collection_id}
curl /api/v1/collections/:collection_id \ --request PATCH \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "description": "string", "identity_field_key": "string", "name": "string" }'
Example Request Body
{ "description": "string", "identity_field_key": "string", "name": "string" }
json
Example Responses
{ "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" }
json
application/json

Add Field

POST
/api/v1/collections/{collection_id}/fields

Declare one more field on a collection, and regenerate its tools' schemas. Use when the collection's existing schema is missing a fact it needs to hold.

Add Field › path Parameters

collection_id
​string · uuid · required

Add Field › Request Body

One declared field. `key` is what a record's values are keyed by and what the model sees as a parameter name; `label` is what a person reads.
FieldIn
key
​string · minLength: 1 · maxLength: 64 · pattern: ^[a-z][a-z0-9_]*$ · required
label
​string · minLength: 1 · maxLength: 200 · required
type
​FieldType · enum · required

What one declared field holds.

Five, and each is a parse rule rather than a column type. The values live in JSONB and the database enforces nothing about them, so what a type means is service's to keep — which is where it had to live anyway: "a 0 is not a no" is a product rule, not a column.

Still deliberately no email and no phone, even now that DATOS-02's default country is ruled (the organization's own — docs/features/ authentication.md). A PHONE type would impose a parse obligation on the whole column — one bad number and the record stops being writable — where what #378 needed was a normaliser on the identity, which changes only how two rows compare. So an identity value is canonicalised by shape, not by a declared type: service._canonical_identity reads the value itself, and if it parses as a phone number under the organization's default country it is stored E.164 (shared.phone.to_e164, ADR 0023); otherwise strip() + casefold(), as before. A TEXT field holding a phone number is still the ordinary case this platform's collections use. A field holding an email address is a TEXT field the client marked personal, which is what the retention rule actually keys on.

Enum values:
text
number
boolean
date
option
​
options
​string[]
personal
​boolean
Default: false
required
​boolean
Default: false
​

Add Field › Responses

Successful Response

CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
POST/api/v1/collections/{collection_id}/fields
curl /api/v1/collections/:collection_id/fields \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "default": { "kind": "value", "offset_days": 0, "value": {} }, "key": "key", "label": "label", "options": [ "string" ], "personal": false, "required": false, "type": "text", "width": 64 }'
Example Request Body
{ "default": { "kind": "value", "offset_days": 0, "value": {} }, "key": "key", "label": "label", "options": [ "string" ], "personal": false, "required": false, "type": "text", "width": 64 }
json
Example Responses
{ "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" }
json
application/json

Delete Field

DELETE
/api/v1/collections/{collection_id}/fields/{key}

Undeclare a field. Use when the field should no longer exist on the collection; its values are dropped from every record.

Delete Field › path Parameters

collection_id
​string · uuid · required
key
​string · required

Delete Field › Responses

Successful Response

CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
DELETE/api/v1/collections/{collection_id}/fields/{key}
curl /api/v1/collections/:collection_id/fields/:key \ --request DELETE \ --header 'Authorization: Bearer <token>'
Example Responses
{ "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" }
json
application/json

Update Field

PATCH
/api/v1/collections/{collection_id}/fields/{key}

Change a declared field. Use when a field's type, requiredness or personal-data marking needs to change, not when correcting one record's value.

Changing its type re-reads every stored value and refuses, naming examples, if any of them would not survive. Changing whether it is personal changes what the retention purge deletes.

Update Field › path Parameters

collection_id
​string · uuid · required
key
​string · required

Update Field › Request Body

Partial edit — only the provided fields change. `default: null` removes the default; leaving `default` out leaves it as it is.
FieldUpdate
​
​
​
​
​
​
​

Update Field › Responses

Successful Response

CollectionOut
created_at
​string · date-time · required
description
​string · required
​FieldOut[] · required
​required
id
​string · uuid · required
​required
name
​string · required
org_id
​string · uuid · required
​required
slug
​string · required
updated_at
​string · date-time · required
​required
​
​
records_deleted_whole
​boolean
Default: false
PATCH/api/v1/collections/{collection_id}/fields/{key}
curl /api/v1/collections/:collection_id/fields/:key \ --request PATCH \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "default": { "kind": "value", "offset_days": 0, "value": {} }, "label": "string", "options": [ "string" ], "personal": true, "required": true, "type": "text", "width": 64 }'
Example Request Body
{ "default": { "kind": "value", "offset_days": 0, "value": {} }, "label": "string", "options": [ "string" ], "personal": true, "required": true, "type": "text", "width": 64 }
json
Example Responses
{ "contact_field_key": "string", "created_at": "2024-08-25T15:00:00Z", "description": "description", "fields": [ { "collection_id": "00000000-0000-0000-0000-000000000000", "default": { "kind": "value", "offset_days": 0, "value": {} }, "filter_kind": "text", "filter_ops": [ "eq" ], "id": "00000000-0000-0000-0000-000000000000", "key": "key", "label": "label", "options": [ "string" ], "personal": true, "position": 0, "required": true, "source_header": "string", "type": "text", "width": 0 } ], "get_tool_id": "00000000-0000-0000-0000-000000000000", "id": "00000000-0000-0000-0000-000000000000", "identity_field_key": "string", "name": "name", "org_id": "00000000-0000-0000-0000-000000000000", "owner": { "id": "00000000-0000-0000-0000-000000000000", "kind": "kind" }, "query_tool_id": "00000000-0000-0000-0000-000000000000", "records_deleted_whole": false, "slug": "slug", "updated_at": "2024-08-25T15:00:00Z", "write_tool_id": "00000000-0000-0000-0000-000000000000" }
json
application/json

Import Records

POST
/api/v1/collections/{collection_id}/imports

Import a CSV into a collection. Use when the file and mapping have been checked with propose_import/plan_import and are ready to actually write.

With a mapping — the proposal as the client corrected it — every column it names that this collection does not declare becomes a field, and the columns left out of it are not written. Without one, columns are matched to declared fields by name and the rest are ignored. A cell that does not fit its field's type is discarded and the row is kept; a row that then lacks a required field its default does not fill is rejected whole. A row that adds a record gets the defaults of the fields it leaves empty. What was refused is recorded on the run, and a run that refused anything puts a notice in your inbox.

Import Records › path Parameters

collection_id
​string · uuid · required

Import Records › Request Body

Body_import_records
file
​string · required
​

Import Records › Responses

Successful Response

ImportRunOut
accepted
​integer · required
collection_id
​string · uuid · required
created_at
​string · date-time · required
​required
id
​string · uuid · required
rejected
​integer · required
​Rejection[] · required
status
​ImportStatus · enum · required
Enum values:
succeeded
failed
total
​integer · required
POST/api/v1/collections/{collection_id}/imports
curl /api/v1/collections/:collection_id/imports \ --request POST \ --header 'Content-Type: multipart/form-data' \ --header 'Authorization: Bearer <token>' \ --form 'file=file' \ --form 'mapping=string'
Example Request Body
{ "file": "file", "mapping": "string" }
text
Example Responses
{ "accepted": 0, "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "finished_at": "2024-08-25T15:00:00Z", "id": "00000000-0000-0000-0000-000000000000", "rejected": 0, "rejections": [ { "column": "string", "reason": "reason", "row": 0, "value": "value" } ], "status": "succeeded", "total": 0 }
json
application/json

Plan Import

POST
/api/v1/collections/{collection_id}/imports/plan

Say what importing this CSV would do, without doing any of it. Use after propose_import's mapping is confirmed and before import_records, to preview the effect.

How many records it creates and how many it merges onto ones already here, the rows it cannot take and why, the fields it would declare, and the fields of this collection the file says nothing about and will leave alone.

Plan Import › path Parameters

collection_id
​string · uuid · required

Plan Import › Request Body

Body_plan_import
file
​string · required
​

Plan Import › Responses

Successful Response

What the import would do, computed without doing any of it. An import is the one moment a client changes thousands of records at once and there is no undoing it afterwards, so this is the step where they find out.
ImportPlanOut
creates
​integer · required
rejected
​integer · required
total
​integer · required
updates
​integer · required
ambiguous_dates
​string[]
declares
​string[]
​Rejection[]
untouched
​string[]
POST/api/v1/collections/{collection_id}/imports/plan
curl /api/v1/collections/:collection_id/imports/plan \ --request POST \ --header 'Content-Type: multipart/form-data' \ --header 'Authorization: Bearer <token>' \ --form 'file=file' \ --form 'mapping=string'
Example Request Body
{ "file": "file", "mapping": "string" }
text
Example Responses
{ "ambiguous_dates": [ "string" ], "creates": 0, "declares": [ "string" ], "rejected": 0, "rejections": [ { "column": "string", "reason": "reason", "row": 0, "value": "value" } ], "total": 0, "untouched": [ "string" ], "updates": 0 }
json
application/json

Propose Import

POST
/api/v1/collections/{collection_id}/imports/proposal

Read a CSV and propose what it would declare, without writing anything. Use first, before plan_import or import_records, to see how a file's columns would be understood.

Answers a field per column — name, type, whether it holds personal data, and the options of a column that repeats a short vocabulary — plus which columns already match this collection, which headers mean the same name, and which dates read equally well both ways round. Every value is a proposal to correct before importing.

Propose Import › path Parameters

collection_id
​string · uuid · required

Propose Import › Request Body

Body_propose_import
file
​string · required

Propose Import › Responses

Successful Response

What a file would declare, before the client has said anything. Writes nothing, decides nothing, and is not required before an import: it is what makes the mapping screen possible.
ImportProposalOut
​ProposedColumn[] · required
total
​integer · required
ambiguous_dates
​string[]
​HeaderCollision[]
​
unnamed
​string[]
POST/api/v1/collections/{collection_id}/imports/proposal
curl /api/v1/collections/:collection_id/imports/proposal \ --request POST \ --header 'Content-Type: multipart/form-data' \ --header 'Authorization: Bearer <token>' \ --form 'file=file'
Example Request Body
{ "file": "file" }
text
Example Responses
{ "ambiguous_dates": [ "string" ], "collisions": [ { "headers": [ "string" ], "key": "key" } ], "columns": [ { "header": "header", "key": "key", "label": "label", "matches_existing": false, "options": [ "string" ], "personal": false, "sample": [ "string" ], "type": "text" } ], "identity_key": "string", "total": 0, "unnamed": [ "string" ] }
json
application/json

Get Import

GET
/api/v1/collections/{collection_id}/imports/{run_id}

Read one CSV import run: whether the file could be read at all, how many rows it had, how many were written or rejected, and why each rejected row was refused.

Get Import › path Parameters

collection_id
​string · uuid · required
run_id
​string · uuid · required

Get Import › Responses

Successful Response

ImportRunOut
accepted
​integer · required
collection_id
​string · uuid · required
created_at
​string · date-time · required
​required
id
​string · uuid · required
rejected
​integer · required
​Rejection[] · required
status
​ImportStatus · enum · required
Enum values:
succeeded
failed
total
​integer · required
GET/api/v1/collections/{collection_id}/imports/{run_id}
curl /api/v1/collections/:collection_id/imports/:run_id \ --header 'Authorization: Bearer <token>'
Example Responses
{ "accepted": 0, "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "finished_at": "2024-08-25T15:00:00Z", "id": "00000000-0000-0000-0000-000000000000", "rejected": 0, "rejections": [ { "column": "string", "reason": "reason", "row": 0, "value": "value" } ], "status": "succeeded", "total": 0 }
json
application/json

List Records

GET
/api/v1/collections/{collection_id}/records

List a collection's records, oldest first or, at newest_first, newest first, narrowed by any filter. Use when showing or searching the records in a collection.

List Records › path Parameters

collection_id
​string · uuid · required

List Records › query Parameters

limit
​integer · min: 1 · max: 200
Default: 200
offset
​integer · min: 0
Default: 0
filter
​string[]
Default: []
newest_first
​boolean
Default: false

List Records › Responses

Successful Response

​RecordOut[]
RecordOut
collection_id
​string · uuid · required
created_at
​string · date-time · required
​object · required
id
​string · uuid · required
​object · required
updated_at
​string · date-time · required
​required
GET/api/v1/collections/{collection_id}/records
curl /api/v1/collections/:collection_id/records \ --header 'Authorization: Bearer <token>'
Example Responses
[ { "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "data": {}, "id": "00000000-0000-0000-0000-000000000000", "provenance": {}, "updated_at": "2024-08-25T15:00:00Z", "withdrawn_at": "2024-08-25T15:00:00Z" } ]
json
application/json

Create Record

POST
/api/v1/collections/{collection_id}/records

Add a record. Use when writing a new fact into a collection. Every value must fit its field's declared type.

If the collection declares an identity field and one already has that value, this updates it instead of adding a second. A field you leave empty that has a default gets it; a date defaulting to the day of creation is that day in your organization's timezone. At retention 0 the fields you marked personal are refused before they are written, and the answer says which.

Create Record › path Parameters

collection_id
​string · uuid · required

Create Record › Request Body

The values to write, keyed by field `key`. A key the collection does not declare is rejected rather than stored: shapeless data pushes the guessing onto every consumer, permanently.
RecordIn
​object
without_defaults
​string[] · maxItems: 256

Create Record › Responses

Successful Response

What one write did, including what it declined to do. `dropped_fields` is the retention-`0` answer and is the reason this is a shape rather than a bare `RecordOut`: a personal field is **refused before it is written**, the rest of the record is written, and the caller is told which ones went nowhere. Nothing is written and then deleted.
WriteResult
created
​boolean · required
​RecordOut · required
dropped_fields
​string[]
POST/api/v1/collections/{collection_id}/records
curl /api/v1/collections/:collection_id/records \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "values": {}, "without_defaults": [ "string" ] }'
Example Request Body
{ "values": {}, "without_defaults": [ "string" ] }
json
Example Responses
{ "created": true, "dropped_fields": [ "string" ], "record": { "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "data": {}, "id": "00000000-0000-0000-0000-000000000000", "provenance": {}, "updated_at": "2024-08-25T15:00:00Z", "withdrawn_at": "2024-08-25T15:00:00Z" } }
json
application/json

Bulk Delete Records

POST
/api/v1/collections/{collection_id}/records/bulk-delete

Delete every record a selection names. Use when removing many records at once instead of one at a time; this cannot be undone.

Bulk Delete Records › path Parameters

collection_id
​string · uuid · required

Bulk Delete Records › Request Body

What to delete. Nothing but the selection: which records, and that is the whole of the decision.
BulkDeleteIn
​required

Bulk Delete Records › Responses

Successful Response

What one bulk action did. `matched` is the number of records it actually touched, resolved the same way the count was — so a client that saw "3,412" and then reads "3,412" here is looking at one number asked twice, not two numbers that happen to agree.
BulkResult
matched
​integer · required
POST/api/v1/collections/{collection_id}/records/bulk-delete
curl /api/v1/collections/:collection_id/records/bulk-delete \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "selection": { "ids": [ "00000000-0000-0000-0000-000000000000" ], "mode": "ids" } }'
Example Request Body
{ "selection": { "ids": [ "00000000-0000-0000-0000-000000000000" ], "mode": "ids" } }
json
Example Responses
{ "matched": 0 }
json
application/json

Bulk Set Field

POST
/api/v1/collections/{collection_id}/records/bulk-set-field

Set one field to one value on every record a selection names. Use when the same correction applies to many records at once instead of one at a time.

Bulk Set Field › path Parameters

collection_id
​string · uuid · required

Bulk Set Field › Request Body

One field, one value, over a selection. `value` is text and is parsed against the field's declared type, exactly as a filter's value is.
BulkSetFieldIn
key
​string · minLength: 1 · maxLength: 64 · required
​required
value
​string · required

Bulk Set Field › Responses

Successful Response

What one bulk action did. `matched` is the number of records it actually touched, resolved the same way the count was — so a client that saw "3,412" and then reads "3,412" here is looking at one number asked twice, not two numbers that happen to agree.
BulkResult
matched
​integer · required
POST/api/v1/collections/{collection_id}/records/bulk-set-field
curl /api/v1/collections/:collection_id/records/bulk-set-field \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "key": "key", "selection": { "ids": [ "00000000-0000-0000-0000-000000000000" ], "mode": "ids" }, "value": "value" }'
Example Request Body
{ "key": "key", "selection": { "ids": [ "00000000-0000-0000-0000-000000000000" ], "mode": "ids" }, "value": "value" }
json
Example Responses
{ "matched": 0 }
json
application/json

Count Records

GET
/api/v1/collections/{collection_id}/records/count

Count the records a filter finds, however many pages they span. Use when you need how many records match, not the records themselves — before a bulk action, or to show a total.

Count Records › path Parameters

collection_id
​string · uuid · required

Count Records › query Parameters

filter
​string[]
Default: []

Count Records › Responses

Successful Response

How many records a question finds. Its own shape rather than a bare integer because it is what a client shows *before* acting, and a number with no name beside it is the sort of thing that ends up meaning "loaded".
RecordCount
count
​integer · required
GET/api/v1/collections/{collection_id}/records/count
curl /api/v1/collections/:collection_id/records/count \ --header 'Authorization: Bearer <token>'
Example Responses
{ "count": 0 }
json
application/json

List Records Of Contact

GET
/api/v1/collections/{collection_id}/records/of-contact/{identity}

List what a collection holds about one person: the records whose contact field names them, the number or address matched however it was written. Use on a person's record, once for each collection that marks a contact field (contact_field_key); empty for one that does not.

List Records Of Contact › path Parameters

collection_id
​string · uuid · required
identity
​string · required

List Records Of Contact › query Parameters

limit
​integer · min: 1 · max: 200
Default: 200
offset
​integer · min: 0
Default: 0

List Records Of Contact › Responses

Successful Response

​RecordOut[]
RecordOut
collection_id
​string · uuid · required
created_at
​string · date-time · required
​object · required
id
​string · uuid · required
​object · required
updated_at
​string · date-time · required
​required
GET/api/v1/collections/{collection_id}/records/of-contact/{identity}
curl /api/v1/collections/:collection_id/records/of-contact/:identity \ --header 'Authorization: Bearer <token>'
Example Responses
[ { "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "data": {}, "id": "00000000-0000-0000-0000-000000000000", "provenance": {}, "updated_at": "2024-08-25T15:00:00Z", "withdrawn_at": "2024-08-25T15:00:00Z" } ]
json
application/json

Delete Records Of Contact

DELETE
/api/v1/collections/{collection_id}/records/of-contact/{identity}

Delete everything a collection holds about one person: every record whose contact field names them. Use for the one action on a person's record that deletes all of what a recipe's collection remembers about them; this cannot be undone, so ask the person first. Their conversations stay.

Delete Records Of Contact › path Parameters

collection_id
​string · uuid · required
identity
​string · required

Delete Records Of Contact › Responses

Successful Response

What one bulk action did. `matched` is the number of records it actually touched, resolved the same way the count was — so a client that saw "3,412" and then reads "3,412" here is looking at one number asked twice, not two numbers that happen to agree.
BulkResult
matched
​integer · required
DELETE/api/v1/collections/{collection_id}/records/of-contact/{identity}
curl /api/v1/collections/:collection_id/records/of-contact/:identity \ --request DELETE \ --header 'Authorization: Bearer <token>'
Example Responses
{ "matched": 0 }
json
application/json

Get Record

GET
/api/v1/collections/{collection_id}/records/{record_id}

Read one record by id, withdrawn or not: its values, who wrote each cell and when, and withdrawn_at if it was withdrawn. Queries and lists leave withdrawn records out; this read does not.

Get Record › path Parameters

collection_id
​string · uuid · required
record_id
​string · uuid · required

Get Record › Responses

Successful Response

RecordOut
collection_id
​string · uuid · required
created_at
​string · date-time · required
​object · required
id
​string · uuid · required
​object · required
updated_at
​string · date-time · required
​required
GET/api/v1/collections/{collection_id}/records/{record_id}
curl /api/v1/collections/:collection_id/records/:record_id \ --header 'Authorization: Bearer <token>'
Example Responses
{ "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "data": {}, "id": "00000000-0000-0000-0000-000000000000", "provenance": {}, "updated_at": "2024-08-25T15:00:00Z", "withdrawn_at": "2024-08-25T15:00:00Z" }
json
application/json

Delete Record

DELETE
/api/v1/collections/{collection_id}/records/{record_id}

Withdraw one record by id. Use when a single record should stop being seen by the agent or returned; its history is kept.

Delete Record › path Parameters

collection_id
​string · uuid · required
record_id
​string · uuid · required

Delete Record › Responses

Successful Response

RecordOut
collection_id
​string · uuid · required
created_at
​string · date-time · required
​object · required
id
​string · uuid · required
​object · required
updated_at
​string · date-time · required
​required
DELETE/api/v1/collections/{collection_id}/records/{record_id}
curl /api/v1/collections/:collection_id/records/:record_id \ --request DELETE \ --header 'Authorization: Bearer <token>'
Example Responses
{ "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "data": {}, "id": "00000000-0000-0000-0000-000000000000", "provenance": {}, "updated_at": "2024-08-25T15:00:00Z", "withdrawn_at": "2024-08-25T15:00:00Z" }
json
application/json

Update Record

PATCH
/api/v1/collections/{collection_id}/records/{record_id}

Change some of a record's values. Use when correcting or updating one existing record by id; the fields you do not send are untouched.

Update Record › path Parameters

collection_id
​string · uuid · required
record_id
​string · uuid · required

Update Record › Request Body

The values to write, keyed by field `key`. A key the collection does not declare is rejected rather than stored: shapeless data pushes the guessing onto every consumer, permanently.
RecordIn
​object
without_defaults
​string[] · maxItems: 256

Update Record › Responses

Successful Response

What one write did, including what it declined to do. `dropped_fields` is the retention-`0` answer and is the reason this is a shape rather than a bare `RecordOut`: a personal field is **refused before it is written**, the rest of the record is written, and the caller is told which ones went nowhere. Nothing is written and then deleted.
WriteResult
created
​boolean · required
​RecordOut · required
dropped_fields
​string[]
PATCH/api/v1/collections/{collection_id}/records/{record_id}
curl /api/v1/collections/:collection_id/records/:record_id \ --request PATCH \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "values": {}, "without_defaults": [ "string" ] }'
Example Request Body
{ "values": {}, "without_defaults": [ "string" ] }
json
Example Responses
{ "created": true, "dropped_fields": [ "string" ], "record": { "collection_id": "00000000-0000-0000-0000-000000000000", "created_at": "2024-08-25T15:00:00Z", "data": {}, "id": "00000000-0000-0000-0000-000000000000", "provenance": {}, "updated_at": "2024-08-25T15:00:00Z", "withdrawn_at": "2024-08-25T15:00:00Z" } }
json
application/json

channelsconnections