Delete data objects in bulk
/data_objects/objects
Use this endpoint to delete up to 50 data objects, of any mix of types, in one request.

Data Objects is generally available, but your workspace must be provisioned for Accounts before you can use this endpoint. To request provisioning, go to Data Settings > Accounts and complete the questionnaire. For details, see Enable Accounts.
Braze accepts the request and processes it in the background. A 202 response means the batch is queued, not applied. To delete one data object and see the change right away, use Delete data object. For when to use each, see Bulk endpoints.
Prerequisites
To use this endpoint, you need an API key with data_objects.bulk_delete. The single-record permissions, such as data_objects.delete, don’t grant access to this endpoint.
Rate limit
This endpoint is in the Data Objects bulk write bucket with a default limit of 1,000 requests per minute per workspace. The limit is shared across all six bulk endpoints and with Cloud Data Ingestion syncs of data objects, and is separate from the single-record write limit.
Request parameters
The following table lists and describes the JSON request body parameters for the /data_objects/objects endpoint.
| Parameter | Required | Data Type | Description |
|---|---|---|---|
records |
Required | Array | The data objects to delete. Must contain 1 to 50 records. Braze rejects any other top-level field. |
records[].type_name |
Required | String | The data object type machine name |
records[].object_id |
Required | String | Your identifier for the object, the same value as object_id in the single-record endpoint paths |
How Braze processes the batch
- Validation is all-or-nothing. If any record fails validation, Braze rejects the whole request with
400, stores nothing, and lists every error. Fix the errors and resend the whole request. - Lookups happen during processing. Braze checks whether each type and object exists when it processes the batch, so a request that returns
202can still produce failures for individual records later. See Processing failures. - Records are ordered by receipt time. Braze stamps every record with the time it received the request, so don’t send
updated_at. Braze rejects a request that includes it. When two requests change the same object, the one Braze received later wins, and Braze skips an older write that arrives afterward. - Deletes can wait. A delete of an object that doesn’t exist yet waits instead of failing right away. Braze retries for about 40 hours (10 attempts). If the object still doesn’t exist after that, the record fails with
data-object-dependency-not-found. - An upsert received after a delete of the same object recreates the object.
Example request
This section includes a sample JSON payload and a sample cURL request.
Sample request payload
{
"records": [
{"type_name": "account", "object_id": "acct-001"},
{"type_name": "opportunity", "object_id": "opp-001"}
]
}
Sample cURL request
This example deletes one account record and one opportunity record in the same request.
curl --location --request DELETE 'https://rest.iad-01.braze.com/data_objects/objects' \
--header 'Authorization: Bearer YOUR_REST_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"records": [
{"type_name": "account", "object_id": "acct-001"},
{"type_name": "opportunity", "object_id": "opp-001"}
]
}'
Response
This section includes a sample successful response and the response fields.
Example success response
The status code 202 could return the following response body.
{
"source_import_id": "api-20261022T153012123456-9f3a1c2b",
"status": "queued",
"record_count": 2
}
Response parameters
The following table lists and describes the fields in a successful response.
| Parameter | Required | Data Type | Description |
|---|---|---|---|
source_import_id |
Required | String | The identifier Braze generated for this request. Every request is its own import. |
status |
Required | String | Always queued. The batch is accepted and waiting to be processed. |
record_count |
Required | Integer | The number of records in the request |
Processing failures
Braze doesn’t return these codes from the endpoint. It records them for individual records when it processes a queued batch.
| Code | Meaning |
|---|---|
data-object-type-not-found |
type_name names no active type in the workspace. |
data-object-ingestion-rejected |
Any other rejection, such as a refused object_id. |
data-object-dependency-not-found |
The object was still missing after about 40 hours of retries. |
Errors
A 400 response means Braze stored nothing. Each error has an id, a message, the parameter at fault when there is one, and, for record-level errors, the record’s index (its 0-based position in records).
The following table lists common errors for this endpoint and how to resolve them.
| Status | Cause | Guidance |
|---|---|---|
400 |
Invalid request (invalid-request): the body isn’t a JSON object or is malformed JSON, records is missing or has fewer than 1 or more than 50 entries, or the body contains a field Braze sets (source_type, source_import_id, source_chunk_id, or record_type) |
Send a JSON object whose only field is records, with 1 to 50 records. |
400 |
Schema mismatch (schema-mismatch): a record is missing a required field, has an unrecognized field (including updated_at), or has a field of the wrong type or an empty string |
Fix every listed record and resend the whole request. |
401 |
Missing or invalid REST API key | Verify the Authorization header uses Bearer YOUR_REST_API_KEY and that the key is active. |
403 |
API key lacks permission or request is blocked by allowlist | Confirm the key has data_objects.bulk_delete and that your source IP is on the key allowlist, if configured. |
404 |
Data Objects isn’t enabled for your company | Confirm your workspace is provisioned for Accounts. |
429 |
Rate limit exceeded | Retry after X-RateLimit-Reset and reduce request frequency. |
500 |
The batch couldn’t be accepted (internal-error) |
Braze accepted nothing, so it’s safe to retry the request. |