California DROP · Live for data brokers

Getting started with your DROP module.

Four things to wire up: your API key, how batches reach your records, a clean Sandbox run, and the flip to production. The first two are one-sitting config. The third is where you iterate, and the iteration is the whole point. The fourth is quick once the third runs clean.

Hey y'all, this is how you get your DROP module live. API key from CalPrivacy into Superset, a matching path picked, Sandbox running clean, production flipped on. DROP is live, and every download starts a 45-day clock: report back on that batch and pull the next list before it runs out.

Why this matters DROP is California's centralized deletion system, and it is live. Every California-registered data broker has to pull deletion requests from DROP at least every 45 days, match them against their records, and report back, for as long as they're registered. The fine for missed deletions is $200 per consumer per day, and with roughly 350,000 Californians signed up, the effective ceiling sits around $70 MILLION per day. This will only continue to grow, so please get this wired up a$ap. You do not want to be the first test case.

Here's the split. DROP is pull-based, which means California does not push deletion lists to you. Every registered broker is responsible for pulling them, and missing a pull is the same as missing a request. That side is on us. Superset polls DROP every day on your behalf, gets each batch to you in a predictable format, takes your status codes back, and uploads the response. What we never do is see your consumer records. They live in your systems, not ours, so the matching happens on your side: on your backend, or right in your browser with Normalize and Hash. The setup below is what wires the two halves together.

1

Connect to DROP

Subscribe to identifier lists in CalPrivacy's Data Broker Portal, generate a Sandbox API key, and paste it into Superset.

2

Get batches to your records

Pick how each batch reaches your data: Superset pushes to a webhook on your backend, your code pulls through the API, or you run it through Normalize and Hash in your browser.

3

Test in the Sandbox

Run a batch against the synthetic dataset, see what matched and what did not, fix your normalization, and rerun until clean.

4

Flip to production

Generate a Production API key, confirm your production matching setup, and start pulling real requests.

Steps 1 and 2 are config. Knock 'em out in a sitting. Step 3 is the iteration loop: run a batch, see what matched and what didn't, fix your normalization, rerun. Step 4 is going live for real.

Step 1: Connect to DROP

Subscribe in CalPrivacy. Paste the API key here.

Open ai.trustsuperset.com/drop/api-key.

Two things have to happen before Superset can pull anything from California: subscribe to identifier lists in CalPrivacy's Data Broker Portal, and paste the resulting API key into Superset.

Subscribe to identifier lists

DROP has six consumer identifier lists. Subscribe to every list you could plausibly use to match a consumer, and you need at least one to use DROP at all.

NDZ · Name + DOB + ZIP EMAIL PHONE MAID · Mobile ad ID NVIN · Name + Vehicle ID CTVID · Connected TV ID

Subscribe to the lists that match what you actually store. Don't store phone numbers? Don't subscribe to PHONE. Every list you subscribe to is one you're committing to match against on every batch, so be honest with yourself about what you've got.

Generate your Sandbox API key

The portal issues two API keys, Sandbox and Production, generated separately. The DROP module in Superset has the same two environments, switched with the Sandbox / Production toggle at the top of the module, and each stores its own key.

Start with a Sandbox key. California's Sandbox is the only environment that grades your matching performance, so it's the right place to prove your setup before real consumer data is in scope. The Production key comes in Step 4, once your Sandbox runs are clean.

In the Data Broker Portal, log in with your registered account, navigate to Sandbox Environment, confirm your list selection, and generate a new API key.

Where's my 2FA code? Your registered account uses your Superset forwarding address, so the portal's login emails and 2FA codes go to your Registry Forwarding Emails group, not your personal inbox. Add yourself on Portal logins & 2FA codes before you request a code.

Copy that key. Back in Superset on the API Key & Lists page, paste it into the Paste API key field and hit Continue. Your API key is encrypted in transit and at rest.

Sandbox downloads suddenly failing? California reset every Sandbox API key when production opened in August 2026. If your Sandbox runs stop working, generate a fresh Sandbox key in the portal and re-add it in Superset before you go looking anywhere else.
You're connected Once the key is saved, Superset can authenticate to DROP and pull Sandbox batches on your behalf. Next up: deciding how those batches reach your records.

Step 2: Get batches to your records

Push, pull, or hash it in your browser.

Three legs to this: Superset hands you California's deletion requests in batches → you match them against your records and settle on a status code per request → Superset uploads the result to CalPrivacy. You own the middle leg, and there are three ways to run it.

1
Superset hands off
Batched hashed identifiers from California
→
2
You match
On your backend, or in your browser
→
3
Superset uploads
Status codes back to CalPrivacy
  • Push to a matching endpoint on your backend Give Superset a URL and it POSTs each batch to you as it lands. Your endpoint matches and answers with a status code per request. Fully hands-off once it's wired. Details below.
  • Pull through the Superset API Leave the endpoint blank and have your own code fetch each batch's requests from the API, match them against your data, and report the codes back on your schedule. Details below.
  • Normalize and Hash in your browser No code. Load your dataset into the tool at ai.trustsuperset.com/drop/overview, and it hashes your records the way California requires and matches them against your outstanding DROP records, entirely inside your browser. Details below.
Which one? If you have engineers, push or pull. Both keep your records in your own systems and run without anyone touching the module once they're up. Normalize and Hash is there for teams that would rather not write code for this. Not sure which fits? Ping your Superset contact.

Option 1: Push to a matching endpoint on your backend

Open ai.trustsuperset.com/drop/endpoint.

To be crystal clear about whose endpoint this is: it's yours. You're giving Superset a URL on your own backend, and Superset pushes California's requests to it. Sandbox and production each keep their own endpoint configuration (Step 4 covers the production side), and both use the same authorization headers you set here. The endpoint is optional: leave it blank and Superset holds each batch for you to pull through the API or match in your browser instead.

What Superset sends you

Every day, Superset pulls the latest deletion requests from DROP and forwards them to your endpoint in batches. Recommended size: 500 records per request. Each record has exactly one populated identifier field. Every other field is null.

Example request body:

{
  "batch_id": "c2e4a6fa-8d44-4f6f-9ef9-7d4f1f1d8e6a",
  "sync_record_id": "c2e4a6fa-8d44-4f6f-9ef9-7d4f1f1d8e6a",
  "environment": "sandbox",
  "list_type": "EMAIL",
  "request_count": 500,
  "requests": [
    {
      "id": "7a3d9c73-39d8-40a5-bfcb-31d123456789",
      "drop_id": 679,
      "ndz": null,
      "email": "KA18MT/ph6IHYjzT9zwETySDQyvSh87YuoSBpOQtkhE=",
      "phone": null,
      "maid": null,
      "nvin": null,
      "ctvid": null
    }
  ]
}

Parse requests[]. Use id as Superset's canonical record ID in your response. Treat drop_id as California's work item ID. You'll need it if you ever audit a specific request back to the state.

The environment field tells you which pipeline a batch came from: sandbox identifiers are synthetic test data, production identifiers are real consumer requests. You can also use {{environment}} in your endpoint URL or headers to route the two apart on your side.

How matching works

For each record, hash your records using SHA-256 with Base64 output, following California's normalization rules, then compare against the hash Superset sent you. Normalization rules differ per identifier type. The full canonicalization rules live in CalPrivacy's official spec.

The most common normalization bugs are also the cheapest to catch: skipping transliteration on accented characters, holding onto whitespace, forgetting to lowercase before hashing. The Sandbox in Step 3 is built to surface those before they cost you a real consumer.

What you send back

Return JSON with one update per request. Each update needs just the Superset request id and the DROP outcome code. Four possible outcomes per record, mapped to California's official status codes:

  • Not found response_status_code: 5. No match after completing the matching process.
  • Deleted response_status_code: 3. Exactly one record matches; delete that consumer's non-exempt data on your side.
  • Opted out response_status_code: 4. Multiple consumers are linked to the same identifier; opt them all out of sale or sharing.
  • Exempted response_status_code: 2. The match is real but the data is retained under an exemption such as Civil Code §1798.99.86(c)(2).

Example response body:

{
  "updates": [
    { "id": "7a3d9c73-39d8-40a5-bfcb-31d123456789", "response_status_code": 3 },
    { "id": "16d9225f-b0c9-4a14-89ce-5b31abcdef12", "response_status_code": 5 },
    { "id": "d3f1f996-cd1e-4e4e-a3c6-82cdabcdef34", "response_status_code": 4 }
  ]
}

California's official result codes are 2, 3, 4, and 5. Full status code reference and file schemas in CalPrivacy's official spec.

Point Superset at your endpoint

On the Matching Endpoint page (also reachable from DROP Settings under Advanced), drop in the URL Superset should POST to, leave the method as POST, and add any headers you need (auth tokens, signing keys) as a JSON object. Then hit Send test batch to confirm Superset can reach your endpoint and parse a response.

If the test batch fails The error message in Superset will tell you which part of the contract broke. Usual suspects: endpoint unreachable, missing Content-Type: application/json, response not parseable as JSON, status codes outside the supported set.

Option 2: Pull through the Superset API

Same contract as the push path (same hashes, same four outcome codes), but your code sets the pace. Superset downloads each batch and holds it; you fetch the requests, match them, and report the codes back. Full endpoint, field, and example reference lives in the developer docs at docs.trustsuperset.com. Every call is authenticated with an API key passed as a bearer token (Authorization: Bearer <token>); to request a key, email [email protected].

Three endpoints, all scoped to an environment in the path (sandbox or production):

  • List DROP records GET /drop/{environment}/requests/. Filter by status, list_type, or batch_id. status=downloaded is your work queue: everything Superset has pulled that nobody has claimed yet.
  • Get a DROP record GET /drop/{environment}/requests/{id}/. One record by its Superset id.
  • Bulk update statuses POST /drop/{environment}/requests/status-update/. Mark records matching (claimed, answer coming) or completed with a response_status_code of 2, 3, 4, or 5.

Example status update:

POST /drop/production/requests/status-update/
{
  "updates": [
    { "id": "3559c8eb-d51f-4f24-8771-d542b232a59d", "status": "matching" },
    { "id": "c819ed3e-0efc-4349-8298-d5618beee6fd", "status": "completed", "response_status_code": 3 }
  ]
}

A record moves downloaded → matching → completed, and from completed Superset takes it the rest of the way to DROP. Use id (Superset's UUID) as your key everywhere; drop_id is California's work item ID and is only unique within an environment and list type. An id from the other environment returns a 404 on purpose, so an integration built against sandbox can't answer real consumer requests by accident.

Don't carry offset forward status=downloaded is a live filter, not a snapshot. Every record you claim or answer leaves the list, so if you also advance offset you'll step over records you were never handed and they'll sit in downloaded indefinitely. Fetch a page, claim it as matching (or report it), then fetch the next page at offset=0. Repeat until a page comes back empty.
Get it right before you report it Once Superset has delivered a record's answer to DROP, the API can't revise it. Matching is the moment to be sure.

Option 3: Normalize and Hash in your browser

Open ai.trustsuperset.com/drop/overview and click Normalize and Hash, next to Download Today's Batches.

If you've got your dataset as a file but nobody to write the hashing and matching code, this is the path. You load the file, the tool standardizes your identifiers and hashes them the way California's rules require, then matches the result against the DROP records waiting in the module. Everything runs in your browser. The file never leaves your device, and Superset never sees your data.

The DROP module in Production showing the Batches table (one row per list type and download date, with Deleted, Opted Out, Not Found, and Exempted counts) and the Normalize and Hash and Download Today's Batches buttons.
The Batches table on the DROP overview. Each download produces one batch per list type; Normalize and Hash sits above it.

Load your file

Drop in a CSV, TSV, JSON Lines, or SQL dump, gzipped or not. It's built for real tables, tens of millions of rows included, and a small file finishes in seconds.

The Normalize and Hash upload screen: a drop zone accepting CSV, TSV, JSON Lines, or a SQL dump (optionally gzipped), a Choose file button, and the notice that Superset cannot see this data because it stays on your device.
The upload screen. Note the lock line at the bottom: Superset cannot see this data. It stays on your device, in your browser, for processing.

Confirm the columns to hash

The tool reads a sample of your file, guesses which columns hold DROP identifiers, and shows you why (header says "FIRSTNAME", values look like postal codes). Check its guesses. Anything it missed, set yourself with the Treat as dropdown: first name, last name, date of birth, ZIP / postal code, email, phone, mobile ad ID, vehicle VIN, or connected-TV ID. A date-of-birth column with an unusual header is the typical one to fix by hand. Everything else stays Don't hash. Then click Hash and pick where to save the result.

What you get back is your file with a new column appended: the DROP-formatted identifier for each record, ready to compare against what California sends.

Match against DROP lists

On the finished screen, click Match against DROP lists. The tool compares your hashed identifiers against the outstanding DROP records in whichever environment the toggle is on, and the batch on the DROP overview fills in with the results: which requests found no record, which matched exactly one, and which matched more than one. Deleting the matched consumers' data in your own systems is still your job; the tool tells you which ones.

Heads up Matching runs against the environment you're standing in. Flip the Sandbox / Production toggle before you start, and if matching stops because there are no outstanding DROP records, that's the first thing to check.

Step 3: Test in the Sandbox

Iterate until your hashing is right.

Open ai.trustsuperset.com/drop/overview.

This is the iteration step, and it's highly recommended before you go anywhere near production: the Sandbox grades your matching against California's spec and tells you what you got wrong. Synthetic dataset on California's side, your own normalized copy on your side. Run a batch, see what matched and what didn't, fix your normalization, rerun.

The DROP module in the Sandbox environment: the three-step Sandbox guide (download the synthetic CSV, normalize, test), the upload notice, and the Add API Key prompt noting each environment has its own key.
The DROP module in Sandbox. The Sandbox / Production toggle at the top switches environments; each keeps its own key, endpoint, and settings.
No real consumers at risk The Sandbox is free and uncapped. Iterate as many times as you need. The whole point of being in here is to find your normalization bugs before a real consumer is on the line.

Download the synthetic CSV

Click Download CSV to grab the synthetic dataset. Same CSV the Sandbox environment is going to send requests against. Think of it as a fake customer database for testing.

Normalize the synthetic dataset

Apply California's normalization rules and SHA-256 Base64 hashing to the records in your copy of the synthetic CSV, and stand up your matching path to look up incoming hashes against this normalized set. On the browser path, this step is just running the synthetic CSV through Normalize and Hash.

This is where you commit, on your side, to the canonicalization rules in CalPrivacy's official spec. The Sandbox is graded against exact-match. No "close enough."

Run a Sandbox batch

In Superset, trigger a test batch. Superset pulls a batch from California's Sandbox API and hands it to your matching path exactly as it would in production: pushed to your endpoint, pulled by your code, or matched in the browser. You answer; Superset records the response.

For each data subject you'll see three things side by side: the hash that was submitted, the response you returned, and the response Superset expected. That last column is the one that matters. When they don't match, you've got a normalization bug, and Superset will tell you which records hit it so you can fix them on your side.

A typical first run: a mix of matches, mismatches, and not-founds. Some of the not-founds are real (the synthetic dataset doesn't contain everyone California's Sandbox asks about). Some of the mismatches are normalization bugs. The point of iteration is to drive the mismatches to zero.

Fix, rerun, repeat

Fix your normalization, save your changes, rerun. No cap on Sandbox runs and no consumer data on the line. Burn through as many cycles as it takes.

Good to know Reporting won't push to DROP until you click Upload on a batch. Ready batches wait for your review, so iterate as freely as you want. If you'd rather skip the click, turn on Auto-Upload Ready Sandbox Batches in DROP Settings (the gear at the top of the module); it's off by default.
The DROP Settings popup in the Sandbox environment: toggles for Run Sandbox DROP Daily and Auto-Upload Ready Sandbox Batches, the DROP API Key with Set Key, the optional Matching Endpoint field, DROP Notifications recipients, and the Forward DROP Updates toggle.
DROP Settings in Sandbox. Every setting applies to one environment; the daily run, auto-upload, API key, and matching endpoint each live per environment.

Step 4: Flip to production

A production key, a production matching setup, and you're live.

Once your Sandbox runs are clean, switch the module's Sandbox / Production toggle to Production and work through the same setup in the new environment:

The DROP module switched to the Production environment, prompting to connect a Production API key and noting each environment has its own key issued by the Data Broker Portal.
Flipped to Production. The module now wants a Production API key; your Sandbox key stays with the Sandbox.
  • Generate a Production API key Same flow as Step 1, but in the portal's production environment instead of the Sandbox. It's a separate key generated independently; your Sandbox key doesn't carry over.
  • Confirm your production matching setup Production keeps its own configuration. Pushing? The production endpoint still points at your own backend and uses the same authorization headers you set in Step 2. Pulling? Point your code at the production path of the API. Matching in the browser? The toggle has to be on Production before you match.
  • Set your run and upload behavior In DROP Settings, turn on Run Production DROP Daily so Superset polls every day, and decide whether to enable Auto-Upload Ready Production Batches or review and upload each batch yourself (the default).
  • Decide who hears about failures Under DROP Notifications, add the people to email when records in a batch fail and need someone to look. With nobody listed, those notices go to your registry recipients in Settings instead. Turn on Forward DROP Updates to also send CalPrivacy's own emails to the same recipients (lists ready to download, uploads received, upload responses and upload errors); that one applies to both environments.
The DROP Settings popup in the Production environment: Run Production DROP Daily and Auto-Upload Ready Production Batches toggles, the DROP API Key, the Matching Endpoint field, DROP Notifications recipients, and the Forward DROP Updates toggle.
Production's own DROP Settings. Sandbox keeps its settings; production keeps these.
A half-switched setup fails silently Sandbox and production return different data. If you add the production key and forget the matching side, or the other way around, everything looks fine while you process the wrong environment's data. Make both changes, then confirm a production batch flows end to end.

Once production is on:

  • Production sync runs daily
    With Run Production DROP Daily on, Superset polls DROP every day, downloads the latest batch, and hands it to your matching path. DROP itself processes new data on a daily cadence, so daily polling means you see requests the moment they're available.
  • Daily maintenance window
    California's DROP API closes between 1:00 AM and 3:00 AM Pacific Time for daily batch processing. Plan around it for time-sensitive integration testing.
  • You control uploads
    By default, a ready batch waits until you click Upload before anything goes back to California. Enable Auto-Upload Ready Production Batches in DROP Settings if you want clean batches sent automatically. Failed batches surface in your DROP dashboard for review either way.
  • A record of every batch
    For every batch Superset pulls, you've got a record of how many were deleted, opted out, not found, and exempted, plus the download and upload timestamps. That's your audit trail when CalPrivacy comes asking.

A few things to be clear about

You own normalization

We can't normalize your records for you on our side, because that data lives in your systems, not ours. We hand you correctly-formatted hashes from California; matching them against your records is yours, whether your backend does it or you run your file through Normalize and Hash in your browser (which is exactly why that tool never uploads anything). If you change your data formats (a CRM migration, a phone number cleanup, anything that touches identifier shape) you need to confirm your normalization still produces the same hashes California is sending. The Sandbox is the right place to verify after any change.

Treat the Sandbox as long-running, not a one-shot

Most customers spend more than one round in here before going live, and there's no downside to staying longer. The point is to drive your mismatches to zero on synthetic data before a real consumer is anywhere in scope.

DROP is distinct from your DSR Manager queue

Webform and email-submitted DSRs flow into your DSR Manager queue at ai.trustsuperset.com/dsars/manage. DROP requests come from California's centralized platform, arrive pre-hashed, and don't show up in the DSR Manager queue. Two systems running in parallel, not in sequence. If you haven't onboarded DSR Manager yet, the guide is at trustsuperset.com/docs/dsr-manager.

One identifier per request

Each DROP request has exactly one populated identifier field. If California asks about an email hash, every other field (phone, MAID, NVIN, NDZ, CTVID) is null on that request. Don't try to match across fields.

One 45-day cycle: download, report, download again

Per CalPrivacy, you must download your lists at least once every 45 days, and report the status of each request within 45 days of downloading it. Count the day you download as day 1. By day 45 you need to have reported back on every request in that batch and downloaded your next list, which starts the next count. We poll daily, which keeps you comfortably ahead of both obligations.

Welcome to Superset DROP If anything in this guide doesn't behave the way it says, email [email protected] and we'll dig in. 🫡