Bulk Operations
Perform batch updates, add or remove relations on multiple records in a single API call.
The bulk endpoint lets you apply the same operation to multiple records at once. It supports field updates and relation management, with per-record permission checks.
Bulk Operation
POST /api/v1/bulkRequest Body
{
"action": "update_field",
"object_name": "contacts",
"record_ids": ["id-1", "id-2", "id-3"],
"field_name": "status",
"field_value": "qualified"
}Actions
| Action | Description | Extra Fields |
|---|---|---|
update_field | Set a field value on all specified records | field_name, field_value |
add_relation | Add related records to a relation field | relation_field, target_ids |
remove_relation | Remove related records from a relation field | relation_field, target_ids |
Common Fields
| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | One of update_field, add_relation, remove_relation |
object_name | string | Yes | The object to operate on (e.g. contacts, companies) |
record_ids | UUID[] | Yes | Array of record IDs to modify |
Action-Specific Fields
update_field:
| Field | Type | Description |
|---|---|---|
field_name | string | The field to update. Must exist on the object. |
field_value | any | The new value to set |
add_relation:
| Field | Type | Description |
|---|---|---|
relation_field | string | The relation field name |
target_ids | UUID[] | IDs of related records to add |
junction_data | object | Optional. Extra junction-table field values applied to each new link (for many-to-many relations with junction fields). |
remove_relation:
| Field | Type | Description |
|---|---|---|
relation_field | string | The relation field name. Must be a MANY_TO_MANY relation. |
target_ids | UUID[] | IDs of related records to remove |
Examples
Update a Field
Set the owner field on three contacts:
curl -X POST "https://kasar.app/api/v1/bulk" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"action": "update_field",
"object_name": "contacts",
"record_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f3ac-52e5-b827-557766551111",
"770a0622-a4bd-63f6-c938-668877662222"
],
"field_name": "owner",
"field_value": "alice-workspace-id"
}'Add Relations
Link two tags to multiple opportunities:
curl -X POST "https://kasar.app/api/v1/bulk" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"action": "add_relation",
"object_name": "opportunities",
"record_ids": ["opp-id-1", "opp-id-2"],
"relation_field": "tags",
"target_ids": ["tag-id-1", "tag-id-2"]
}'Remove Relations
curl -X POST "https://kasar.app/api/v1/bulk" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"action": "remove_relation",
"object_name": "contacts",
"record_ids": ["contact-id-1", "contact-id-2"],
"relation_field": "tags",
"target_ids": ["tag-id-1"]
}'Response
The response shape depends on the action performed. Every response includes an errors array (empty when nothing failed, capped at 50 entries) and a total.
update_field: total is the number of record IDs supplied.
{
"action": "update_field",
"updated": 3,
"failed": 0,
"errors": [],
"total": 3
}add_relation: the success counter is processed (the number of records that had relations added). total is the number of record IDs supplied.
{
"action": "add_relation",
"processed": 2,
"failed": 0,
"errors": [],
"total": 2
}remove_relation: removed is the count of links actually unlinked, and total is record_ids × target_ids (the number of attempted unlinks).
{
"action": "remove_relation",
"removed": 2,
"failed": 0,
"errors": [],
"total": 2
}Partial Failures
If some records fail (for example, due to permission checks), they appear in the errors array. Each entry has an id (the failing record ID) and a reason string:
{
"action": "update_field",
"updated": 2,
"failed": 1,
"errors": [
{
"id": "770a0622-a4bd-63f6-c938-668877662222",
"reason": "You do not have permission to update this record"
}
],
"total": 3
}RBAC checks are performed per record. If the user lacks permission on a specific record, that record fails but the rest of the batch proceeds.
Error Responses
These errors apply to the whole request and are returned with HTTP 400.
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_OBJECT | The object_name does not exist |
| 400 | MISSING_REQUIRED_FIELD | record_ids is empty, or an action is missing its required fields (field_name for update_field; relation_field and target_ids for relation actions) |
| 400 | INVALID_FIELD | field_name does not exist on the object, or relation_field is not a MANY_TO_MANY relation (for remove_relation) |