Conversation Sync
Conversation sync configs automatically export finished agent conversations into your AutessaDB tables — the full transcript lands in a column of a table you choose, matched to an existing row or inserted as a new one, so downstream tools, triggers, and reports can work with conversation data like any other row.
All paths on this page are relative to https://api.autessa.com/autessa_poweruser/conversation-sync. Every request is a POST with a JSON body, and every ID is an opaque string. See the Poweruser API overview for authentication and conventions.
How syncing works
Each config is a standing rule that runs asynchronously whenever a conversation is logged for your company:
- Filter — only
enabledconfigs run. A config can restrict itself to specific agents (agentIds), to conversations that do or don't have an evaluation (requiresEvaluation), and to production traffic only (allowSandboxConversations: falseskips Builder sandbox conversations and syncs only conversations started with an API key). - Write — for every entry in
tableUpdates, the conversation's transcript JSON is written intoconversationJsonColumnon rows of the target AutessaDB table wherematchColumnequals the conversation ID.additionalColumnsare updated at the same time, with template variables substituted. - No match — if no row matches, the entry's
onNoMatchbehavior decides:SKIPdrops the write,INSERTcreates a new row (upsert) that includes the match column set to the conversation ID.
Multiple configs can match the same conversation; each runs independently, and a failure in one config or one table update does not stop the others. Because the data lands in regular AutessaDB rows, you can chain triggers on the target table to post-process transcripts.
The conversation sync config object
- Name
id- Type
- string
- Description
Unique config identifier.
- Name
name- Type
- string
- Description
Display name. Must be unique within the company.
- Name
description- Type
- string
- Description
What the config is for.
- Name
enabled- Type
- boolean
- Description
Whether the config runs. Disabled configs are kept but never match.
- Name
agentIds- Type
- array<string>
- Description
Agents whose conversations this config syncs.
nullmeans all agents.
- Name
requiresEvaluation- Type
- boolean
- Description
truesyncs only conversations that have an evaluation,falseonly those without one,nulldoesn't filter on evaluation at all.
- Name
allowSandboxConversations- Type
- boolean
- Description
When
false(the default), only conversations started with an API key are synced; Builder sandbox test conversations are skipped.
- Name
tableUpdates- Type
- array<TableUpdate>
- Description
The AutessaDB writes to perform for each matching conversation. See table update entries below.
- Name
createdAt- Type
- string
- Description
ISO-8601 creation timestamp.
- Name
updatedAt- Type
- string
- Description
ISO-8601 timestamp of the last update.
Table update entries
- Name
tableId- Type
- string
- Description
The AutessaDB table to update.
- Name
matchColumn- Type
- string
- Description
Column name matched against the conversation ID to find the target row (for example
"conversation_id").
- Name
conversationJsonColumn- Type
- string
- Description
Column that receives the conversation transcript as a JSON array of log entries.
- Name
additionalColumns- Type
- map<string, string>
- Description
Extra columns to set on the matched row. Values are literal strings with template variables substituted. Target columns must be
SHORT_TEXTorLONG_TEXT.
- Name
onNoMatch- Type
- string
- Description
SKIP(default) — do nothing when no row matches.INSERT— insert a new row containing the conversation JSON, the additional columns, and the match column set to the conversation ID.
- Name
includeToolCalls- Type
- boolean
- Description
Whether the JSON written to
conversationJsonColumnincludesTOOL_REQUEST/TOOL_RESPONSElog entries. Defaults totrue.
Template variables
Values in additionalColumns may embed these placeholders:
| Variable | Substituted with |
|---|---|
@@{conversationId} | The conversation's ID. |
@@{closeDate} | When the conversation closed. |
@@{agentId} | The agent's ID. |
@@{agentVersion} | The agent version that ran the conversation. |
@@{apiKeyId} | The API key that started the conversation, if any. |
@@{companyId} | Your company's ID. |
@@{conversation} | Full transcript JSON — always includes tool calls. |
@@{shortened_conversation} | Transcript JSON without tool calls. |
{
"id": "V1StGXR8Z5",
"name": "Closed support tickets",
"description": "Writes finished support conversations back onto the ticket row.",
"enabled": true,
"agentIds": ["aG9dK2mP4q"],
"requiresEvaluation": null,
"allowSandboxConversations": false,
"tableUpdates": [
{
"tableId": "tB6xN4rW8z",
"matchColumn": "conversation_id",
"conversationJsonColumn": "transcript",
"additionalColumns": {
"status": "closed",
"closed_at": "@@{closeDate}",
"agent_version": "@@{agentVersion}"
},
"onNoMatch": "INSERT",
"includeToolCalls": true
}
],
"createdAt": "2026-06-12T09:30:00",
"updatedAt": "2026-06-28T17:42:10"
}
Create a config
/conversation-sync/createCreates a new sync config for the company. The name must be unique within
the company — creation fails with an error message otherwise. The config
starts matching conversations immediately unless you pass enabled: false.
Request parameters
- Name
name- Type
- string
- Description
Display name, unique within the company.
- Name
description- Type
- string
- Description
What the config is for.
- Name
enabled- Type
- boolean
- Description
Whether the config runs. Defaults to
true.
- Name
agentIds- Type
- array<string>
- Description
Restrict to these agents. Omit or send an empty array to sync all agents.
- Name
requiresEvaluation- Type
- boolean
- Description
true= only evaluated conversations,false= only unevaluated ones. Omit to sync regardless of evaluation.
- Name
allowSandboxConversations- Type
- boolean
- Description
Also sync Builder sandbox conversations. Defaults to
false(API-key conversations only).
- Name
tableUpdates- Type
- array<TableUpdate>
- Description
The writes to perform, in the table update entry shape.
Response
- Name
configId- Type
- string
- Description
The new config's ID.
- Name
message- Type
- string
- Description
Confirmation message.
- Name
errors- Type
- array<string>
- Description
Error messages, if any occurred (for example
"A conversation sync config with this name already exists").
- cURL
- JavaScript
- Python
curl https://api.autessa.com/autessa_poweruser/conversation-sync/create \
-X POST \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Closed support tickets",
"description": "Writes finished support conversations back onto the ticket row.",
"agentIds": ["aG9dK2mP4q"],
"tableUpdates": [
{
"tableId": "tB6xN4rW8z",
"matchColumn": "conversation_id",
"conversationJsonColumn": "transcript",
"additionalColumns": {
"status": "closed",
"closed_at": "@@{closeDate}"
},
"onNoMatch": "INSERT"
}
]
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/conversation-sync/create',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Closed support tickets',
description: 'Writes finished support conversations back onto the ticket row.',
agentIds: ['aG9dK2mP4q'],
tableUpdates: [
{
tableId: 'tB6xN4rW8z',
matchColumn: 'conversation_id',
conversationJsonColumn: 'transcript',
additionalColumns: { status: 'closed', closed_at: '@@{closeDate}' },
onNoMatch: 'INSERT'
}
]
})
}
);
const { configId } = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/conversation-sync/create',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'name': 'Closed support tickets',
'description': 'Writes finished support conversations back onto the ticket row.',
'agentIds': ['aG9dK2mP4q'],
'tableUpdates': [
{
'tableId': 'tB6xN4rW8z',
'matchColumn': 'conversation_id',
'conversationJsonColumn': 'transcript',
'additionalColumns': {'status': 'closed', 'closed_at': '@@{closeDate}'},
'onNoMatch': 'INSERT'
}
]
}
)
config_id = response.json()['configId']
{
"configId": "V1StGXR8Z5",
"message": "Conversation sync config created successfully",
"errors": []
}
Get a config
/conversation-sync/getRetrieves a single sync config. Configs are company-scoped — requesting a config that belongs to another company returns an error.
Request parameters
- Name
id- Type
- string
- Description
The config to fetch.
Response
- Name
config- Type
- ConversationSyncConfig
- Description
- Name
errors- Type
- array<string>
- Description
Error messages, if any occurred.
curl https://api.autessa.com/autessa_poweruser/conversation-sync/get \
-X POST \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{ "id": "V1StGXR8Z5" }'
{
"config": {
"id": "V1StGXR8Z5",
"name": "Closed support tickets",
"enabled": true,
"agentIds": ["aG9dK2mP4q"],
"allowSandboxConversations": false,
"tableUpdates": [
{
"tableId": "tB6xN4rW8z",
"matchColumn": "conversation_id",
"conversationJsonColumn": "transcript",
"onNoMatch": "INSERT",
"includeToolCalls": true
}
],
"createdAt": "2026-06-12T09:30:00",
"updatedAt": "2026-06-28T17:42:10"
},
"errors": []
}
List all configs
/conversation-sync/allLists every sync config in the company, enabled or not.
Request parameters
None — send an empty object {}.
Response
- Name
configs- Type
- array<ConversationSyncConfig>
- Description
All configs, each in the conversation sync config object shape.
- Name
totalCount- Type
- integer
- Description
Number of configs returned.
- Name
errors- Type
- array<string>
- Description
Error messages, if any occurred.
curl https://api.autessa.com/autessa_poweruser/conversation-sync/all \
-X POST \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{}'
{
"configs": [
{
"id": "V1StGXR8Z5",
"name": "Closed support tickets",
"enabled": true,
"agentIds": ["aG9dK2mP4q"],
"allowSandboxConversations": false,
"tableUpdates": [{ "tableId": "tB6xN4rW8z", "matchColumn": "conversation_id" }]
}
],
"totalCount": 1,
"errors": []
}
Update a config
/conversation-sync/updatePartially updates a config: only the fields you send are changed, everything
else keeps its current value. Renames are checked for uniqueness. Note that
tableUpdates is replaced wholesale when present — send the complete list
you want, not a delta.
Request parameters
- Name
id- Type
- string
- Description
The config to update.
- Name
name- Type
- string
- Description
New display name, unique within the company.
- Name
description- Type
- string
- Description
New description.
- Name
enabled- Type
- boolean
- Description
Enable or disable the config.
- Name
agentIds- Type
- array<string>
- Description
New agent filter. Send an empty array
[]to clear the filter and sync all agents.
- Name
requiresEvaluation- Type
- boolean
- Description
New evaluation filter.
- Name
allowSandboxConversations- Type
- boolean
- Description
New sandbox allowance.
- Name
tableUpdates- Type
- array<TableUpdate>
- Description
Full replacement list of table update entries.
Response
- Name
message- Type
- string
- Description
Confirmation message.
- Name
errors- Type
- array<string>
- Description
Error messages, if any occurred.
- cURL
- JavaScript
- Python
curl https://api.autessa.com/autessa_poweruser/conversation-sync/update \
-X POST \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "V1StGXR8Z5",
"enabled": false,
"agentIds": []
}'
await fetch(
'https://api.autessa.com/autessa_poweruser/conversation-sync/update',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 'V1StGXR8Z5',
enabled: false,
agentIds: []
})
}
);
import os
import requests
requests.post(
'https://api.autessa.com/autessa_poweruser/conversation-sync/update',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={'id': 'V1StGXR8Z5', 'enabled': False, 'agentIds': []}
)
{
"message": "Conversation sync config updated successfully",
"errors": []
}
Delete a config
/conversation-sync/deletePermanently deletes a sync config. Conversations that were already synced stay in their AutessaDB tables; only future syncing stops.
Request parameters
- Name
id- Type
- string
- Description
The config to delete.
Response
- Name
message- Type
- string
- Description
Confirmation message.
- Name
errors- Type
- array<string>
- Description
Error messages, if any occurred.
curl https://api.autessa.com/autessa_poweruser/conversation-sync/delete \
-X POST \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{ "id": "V1StGXR8Z5" }'
{
"message": "Conversation sync config deleted successfully",
"errors": []
}
Errors
| Status | When |
|---|---|
200 | Success — check errors for validation messages (duplicate config name, "You do not have access to this config" for another company's config). |
401 | Invalid or missing poweruser key. |
403 | Scoped key without the endpoint in its allow-list. |
408 | Server-side error; errors contains the message. |
Sync execution itself is asynchronous — write failures against the target
table (unknown column names, unsupported column types) are logged
server-side and never surface through these endpoints, so double-check
column names in tableUpdates against the target table's schema.