Applies to:
- Plan -
- Deployment -
Summary
Goal: Delete project logs programmatically and have them actually disappear from the UI and BTQL queries.How deletion works
Deleting a log is done by re-inserting the event with_object_delete: true for each target row id:
_object_delete marker matches on the row id only. It does not match on span_id or root_span_id. Because the insert endpoint accepts any submitted id and echoes it back in row_ids, a 200 response means Braintrust recorded a delete tombstone for the IDs you sent, even when those IDs don’t correspond to any visible log row. That’s why a delete keyed on span_id or root_span_id “succeeds” but changes nothing.
id and span_id are different values: id is the system-assigned unique row identifier, while span_id is an arbitrary value you can set and reuse across projects.
Solution: resolve row IDs first, then delete
Use BTQL to look up the actual rowids, then submit those ids as delete events.
Important behaviors
- Delete the whole trace, not just the root span. Deleting a root span deletes only that one span. The child spans remain orphaned and still show up in the UI and BTQL. To fully remove a trace, query for all
ids under itsroot_span_idand delete each one (as shown above). - Deletions are eventually consistent. Rows may briefly reappear after a delete and take a few seconds plus a page refresh to disappear. This is more noticeable right after deletion, not a sign the delete failed.
- Use the correct API URL. For hosted Braintrust, use
https://api.braintrust.dev. For self-hosted or hybrid deployments, use the data plane API URL from Settings > Data plane. Being able to insert logs confirms the URL only for writes; deletion uses the same endpoint but still requires valid rowids. {project_id}must be the UUID, not the project name (e.g.,914981cd-29bc-4c94-936e-74bd91d8bef2). Passing the project name fails the request.
Verify a deletion
Re-run the BTQL lookup after deleting. If the delete succeeded, the query returns no rows for those IDs (allow a few seconds for consistency):ids, collect the delete response row_ids, a before/after BTQL result for one root_span_id, the request timestamp, the project ID, and your SDK version, and escalate.
Notes
- For recurring cleanup instead of one-off deletion, use a data retention automation to delete logs older than a configured window.