Saving data
Endpoint: POST /api/tickets/multi
Create, update, and delete records in a single batch request. The endpoint accepts an array of operations.
Permissions
All write operations respect the authenticated user's permissions. The API returns an error if the user is not authorized to perform the requested action on the target record or app.
Creating records
Send an array with one or more record objects. Each object must include:
transition: "add"- the create actionapp_alias- app type (e.g.,"TASK","TICKET")workspace_alias- target workspace (e.g.,"IT")- Field values keyed by field name
curl --request POST \
--url "https://acme.comind.work/api/tickets/multi" \
--header "Authorization: CMW_AUTH_CODE YOUR-TOKEN" \
--header "Content-Type: application/json" \
--data '[{
"transition": "add",
"app_alias": "TASK",
"workspace_alias": "HELPDESK",
"title": "New task via API",
"priority": "high",
"description": "<!-- html --><p>Task description here</p>"
}]'
Response
[
{
"successful": true,
"created": true,
"data": {
"id": "new-record-guid",
"number": 456,
"project_alias": "HELPDESK",
"publishing_alias": "TASK"
},
"warnings": []
}
]
Rich text fields
Prefix HTML content with <!-- html --> to indicate it should be stored as rich text:
{
"description": "<!-- html --><p>This is <strong>formatted</strong> text</p>"
}
Plain text and markdown are also accepted - the server converts them to HTML automatically. The <!-- html --> prefix tells the API the content is already HTML and should not be converted.
Markdown conversion supports **bold**, *italic*, [link](url), and paragraph breaks (double newlines).
Lookup values
Lookup fields (state, priority, custom dropdowns) require internal db values, not display captions. Use GET /api/schema/{WS}!{APP} to discover available lookup values:
{ "priority": "high" }
{ "state": "open" }
Updating records
Provide the record id and a transition (action alias):
curl --request POST \
--url "https://acme.comind.work/api/tickets/multi" \
--header "Authorization: CMW_AUTH_CODE YOUR-TOKEN" \
--header "Content-Type: application/json" \
--data '[{
"id": "record-guid",
"transition": "edit",
"title": "Updated title",
"priority": "high",
"comment": "<!-- html --><p>Changed priority</p>"
}]'
Only include fields you want to change. Omitted fields are not modified.
Available transitions
Use the schema endpoint to discover which actions are available for an app:
GET /api/schema/{workspace}!{app}
The transitions array in the response lists available actions with their aliases:
| Common alias | Purpose |
|---|---|
edit | General edit (most apps) |
add | Create a new record |
delete | Delete the record |
| App-specific | Custom actions like approve, reject, close, assign |
Adding a comment
Include the comment field to add a comment alongside the update:
{
"id": "record-guid",
"transition": "edit",
"comment": "<!-- html --><p>Updating per client request</p>",
"minor_change": false
}
Set minor_change: true to suppress notifications for the update.
Deleting records
curl --request POST \
--url "https://acme.comind.work/api/tickets/multi" \
--header "Authorization: CMW_AUTH_CODE YOUR-TOKEN" \
--header "Content-Type: application/json" \
--data '[{"id": "record-guid", "transition": "delete"}]'
Batch operations
The endpoint accepts an array, so you can create, update, and delete multiple records in a single request:
[
{ "transition": "add", "app_alias": "TASK", "workspace_alias": "IT", "title": "Task 1" },
{ "transition": "add", "app_alias": "TASK", "workspace_alias": "IT", "title": "Task 2" },
{ "id": "existing-guid", "transition": "edit", "priority": "high" },
{ "id": "old-guid", "transition": "delete" }
]
The response is an array with one result per operation, in the same order.
Field names and values
The API expects internal (db) field names and values:
| What | Format | Example |
|---|---|---|
| Field name | db name | keeper_id, c_priority, state |
| Lookup value | db value | "high", "open", "approved" |
| Person field | user GUID | "a1b2c3d4-..." |
| Link field | record GUID | "e5f6g7h8-..." |
Use GET /api/schema/{WS}!{APP} to discover field names and lookup values for your target app.
The MCP tools layer adds automatic resolution on top of the raw API - it accepts field captions instead of db names, lookup display values (case-insensitive), person names instead of GUIDs, and record slugs ("IT/TASK123") instead of GUIDs. If you're working through MCP, these conveniences are available automatically.
TypeScript SDK example
Load deals over $1000, double the price, and save:
async function doubleBigDeals() {
const deals = await comind.records.retrieve(
"w/CRM/a/DEAL/tickets/list",
{ limitRecords: 1000, listOfFields: "id,title,c_amount", rlx: "c_amount>1000" }
);
for (const deal of deals) {
deal.c_amount = deal.c_amount * 2;
deal.transition = "edit";
}
await comind.records.save(deals);
console.log(`Updated ${deals.length} deals`);
}