Integrating with California's DROP API
What a data broker's engineering team actually has to build to satisfy the Delete Act's deletion cycle: three endpoints, two file formats, four status codes, and a clock that never stops.
The shape of the obligation
Since August 1, 2026, every registered California data broker must access DROP at least once every 45 calendar days, retrieve the consumer deletion lists it has selected, match them against its own records, delete what matches, and report a status for every request. Failure to process carries $200 per deletion request, per day.
Integration via API is optional — the full cycle can be completed manually through the portal — but the file formats and matching rules are identical either way.
Authentication and environments
Keys are issued in the Data Broker Portal after you select your consumer deletion lists. A separate sandbox key is issued for testing. Every request carries the key in a header; issuing a new key deactivates the old one.
GET https://api.drop.privacy.ca.gov/data/download X-API-KEY: <your key> Accept: application/zip, application/json # sandbox: https://api.drop.privacy.ca.gov/sandbox/data/download
Note the account model: DROP supports a single login per broker, and the account must belong to the broker itself — not to a vendor in its own capacity. A service provider operates as the broker's authorized agent.
The three endpoints
| Endpoint | Purpose | Notes |
|---|---|---|
| GET /data/download | Retrieve the deletion lists | Returns a ZIP, or 202 + Retry-After while the package builds. 409 means the previous batch's responses are incomplete. |
| POST /data/upload | Report statuses | multipart files; CSVs only, never a ZIP. 202 = queued; row-level validation continues after the response. |
| POST /data/amend | Correct a submitted status | Identical request shape to upload. Needed when a "not found" consumer later appears in newly collected data. |
File formats — the casing matters
The download archive contains one CSV per selected list type, plus a Removed file when previously delivered identifiers are withdrawn. Header casing differs between download and upload, and the upload header is validated strictly.
20260801_4821_DROP.zip ├── 20260801_4821_Email.csv ID,Hash ├── 20260801_4821_NDZ.csv ID,Hash └── 20260801_4821_Removed.csv ID,Hash,ListType # your response file — note "Id", not "ID" Id,Status A7kP2xQ9Lm4R,3 B2mN8vR4Kp7Q,5
File names follow YYYYMMDD_<brokerId>_<DataType>[_<suffix>].csv. Uploading two files with the same name inside one download is rejected, so split large responses with the optional suffix (_part01, _part02).
Status codes
| Code | Meaning | When |
|---|---|---|
| 2 | Exempted | Match found, but all the personal information is exempt under the CCPA. Self-asserted — audited later. |
| 3 | Deleted | Match found, non-exempt information deleted — including inferences, archives, and backups. |
| 4 | Opted out | Multiple consumers share the identifier; all were opted out of sale and sharing instead. |
| 5 | Not found | No match — but you must retain the identifier and screen future data against it. |
Codes 0 and 1 are unused.
Webhooks
Register an HTTPS endpoint in the portal and DROP will notify you when a download is ready or an upload is processed. Signature verification is easy to get subtly wrong — the signing string is the timestamp, a literal dot, then the raw body, and the digest is hex, not Base64.
const expected = hmacSha256Hex(secret, `${timestamp}.${rawBody}`);
const received = header["X-Webhook-Signature"].replace("sha256=", "");
if (!constantTimeEqual(expected, received)) reject();
// also reject timestamps older than ~5 minutes; respond 204The cycle clock
Downloads are incremental: after the first, each one returns only requests received since your last completed download. The rules that trip teams up:
- Access at least once every 45 calendar days — this is a rolling maximum interval, not a fixed window.
- Report the previous session's statuses before downloading a new list.
- You may change your list selection only once every 45 days.
- Retry policy: honour Retry-After on 429 (default 30s) and poll on 202; do not retry other 4xx.
Or skip the build
PrivacyClock implements all of this — validated against every published test vector — for $299/mo.
Try it on sample data →