Purge all feedback records for a tenant
Permanently deletes every feedback record for the specified tenant_id, everything derived from those records — embeddings and the enrichment stored on each record (sentiment, emotions, translations) — and the taxonomy built on them: runs, clusters, nodes, cluster memberships, active-run pointers and node events.
This is intended for emptying a dataset that stays in use, so it removes the tenant's DATA but
never its CONFIGURATION: webhooks and tenant settings are left untouched. That is the difference
from DELETE /v1/tenants/{tenant_id}/data, which additionally deletes both and is meant for
offboarding a deprovisioned tenant.
The taxonomy is removed rather than preserved because it describes records that no longer exist:
its per-node counts are derived from memberships and would all read zero, while a run's own stored
counters (record_count, cluster_count, a cluster's size) are historical and would keep
advertising the old numbers. A new taxonomy can be generated once the dataset has enough feedback
again; manual node renames and removals are per-run and do not survive a regeneration in any case.
The tenant is a required path segment, so it cannot be omitted the way a filter on a collection delete could be — dropping it routes elsewhere rather than widening the operation to every tenant.
Asynchronous: the request schedules the purge and returns 202 immediately, because the deletion is
unbounded and can outlive a request. There is therefore no deleted count in the response. Poll
GET /v1/feedback-records/count?tenant_id=... to observe progress.
The purge removes only the records that existed when it started — it takes a high-water mark up front — so feedback ingested while it runs is never deleted. For a dataset that is no longer receiving feedback the count reaching zero means the purge is complete; for one still ingesting, a nonzero count is those newer records. Note this means the count alone cannot distinguish "finished" from "failed" on an active dataset.
Idempotent and safe to repeat. Requesting a purge while one is already running for the same tenant joins the running purge rather than queueing a second one, and still returns 202. A purge requested after an earlier one finished starts a new run.
Records are deleted in committed batches, so a purge interrupted by a restart or a timeout keeps
the progress it made and resumes on retry; the taxonomy is removed in a final step once the records
are gone. While each step runs, the tenant's write lock is held exclusively and Hub-owned writes
for that tenant are rejected with HTTP 409 (code tenant_write_conflict); the lock is released
between steps, and writes for other tenants are never affected. This does not apply to the request below — scheduling a purge takes no lock, so
this endpoint does not return 409. A batch that cannot acquire the lock is retried by the job
queue without any caller action, up to a bounded number of attempts.
No webhook events are published for a purge, and no webhooks are deleted. Enrichment jobs already queued for purged records no-op when they run, since the record they reference is gone.
Parameters
Returns
Purge all feedback records for a tenant
import FormbricksHub from '@formbricks/hub';
const client = new FormbricksHub({
apiKey: process.env['HUB_API_KEY'], // This is the default and can be omitted
});
const response = await client.tenants.purgeFeedbackRecords('org-123');
console.log(response.tenant_id);{
"tenant_id": "org-123",
"status": "accepted",
"message": "Feedback records purge accepted for org-123"
}Returns Examples
{
"tenant_id": "org-123",
"status": "accepted",
"message": "Feedback records purge accepted for org-123"
}