Bulk End-User Deletion API

Overview

The Bulk End-User Deletion API erases all personal data associated with one or more end users across Ada’s systems. A single request can carry up to 1000 identifiers and is processed as an asynchronous job. Submit a request to receive a job_id, then poll the job to track progress and review the outcome for each identifier.

This API supports compliance with data deletion requirements under applicable laws, such as GDPR.

This API replaces the single-record Data Compliance API, which is now deprecated. Use the Bulk End-User Deletion API for all end-user data deletion.

Identifiers

Each request supplies a list of identifiers. Every identifier has a type, a value, and — for variable_match only — a variable naming the stored variable to match against.

TypeDescription
emailMatches end users by email address. Values are normalized and matched case-insensitively.
chatter_idMatches by a legacy Ada end-user record ID.
external_idMatches by the ID you assign to an end user. Values are trimmed and lowercased at intake.
end_user_idMatches by Ada’s end-user identifier.
variable_matchMatches every end user whose meta variable named variable currently equals value — for example an end user’s email, language, or any custom metadata key.

What variable_match matches: variable names a meta variable on the end user. When you set a profile through the End Users API, both the profile fields (first_name, last_name, display_name, avatar, email, language) and every key in the metadata object are stored as meta variables — variable_match can target any of them. It matches on the end user’s latest value for that variable (exact match). Global or session variables set during a conversation are not matched.

Limits. A single request accepts at most 1000 identifiers, and the request body may be at most 512 KB — a larger body returns 413. Each identifier may match at most 500 end users — this ceiling is shared by variable_match and by the fan-out of an email match. An identifier that matches more than 500 end users is reported as exceeds_limit and erases nothing; a variable_match that matches zero end users is reported as not_found.

Dispositions

The job records a disposition for every submitted identifier. Inspect the per-identifier dispositions to understand exactly what was erased.

DispositionMeaning
acceptedThe identifier matched end users who were queued for erasure.
not_foundNo end users matched the identifier.
invalidThe identifier was malformed or unusable. reason is populated.
exceeds_limitThe identifier matched more than 500 end users, so nothing was erased. reason is populated.
duplicateThe identifier repeated another identifier in the same request.

Each disposition also reports matched_chatters, the number of end users matched by that identifier. A non-accepted disposition may carry a reason explaining the outcome: it is always set for invalid and exceeds_limit, and for not_found on ID-based identifiers, but can be null for a not_found email or variable_match selector — so don’t rely on reason being present based on disposition alone.

Job lifecycle

A job moves through the following states:

StatusMeaning
queuedThe job was accepted and is waiting to be processed. Non-terminal.
in_progressErasure is underway. Non-terminal.
completedEvery matched end user was erased.
partialNot every identifier was accepted or fully erased. This includes the case where zero identifiers were accepted.
failedThe job could not be processed. failure_reason is set.

Because partial covers a range of outcomes — including none accepted — do not rely on the top-level status alone. Inspect the per-identifier disposition array to see what happened to each identifier.

On a failed job, failure_reason carries an opaque, machine-readable diagnostic. Its values are subject to change, so treat it as a signal rather than a stable contract; to understand outcomes per identifier, use each identifier’s disposition and reason.

accepted and completed mean different things. An accepted disposition means an identifier’s end users were queued and submitted to Ada’s erasure engine — not that they are erased yet. The job stays in_progress while the engine erases across every data store, and only reaches completed once Ada confirms that erasure finished. Because the engine runs downstream on a daily cycle, reaching completed can take up to 30 days. This delay is expected behavior.

Idempotency

Requests are idempotent for 24 hours. An identical request resubmitted within that window returns the original job instead of creating a new one.

Rate limit

The Bulk End-User Deletion API is subject to the global rate limits.