API Reference
This article covers the API endpoints used between your systems and DataGrail for Data Broker Compliance. There are two dispatch patterns — implement whichever matches your infrastructure. Both patterns support deletion (DROP status code 3) and opt-out (DROP status code 4) outcomes, and share the same authentication summary and error codes documented at the end of this article.
Before implementing a dispatch pattern, ensure you have:
- Completed the Quickstart and chosen your dispatch method
- Completed Identifier Configuration and selected your DROP list types
- Completed Ingestion Format and begun delivering consumer identifiers to DataGrail
Webhook
This section covers DROP-specific request and callback formats and builds on the standard Webhooks documentation.
Deletion Dispatch
DataGrail POSTs to a URL you configure when a DROP match occurs.
Deletion Dispatch Headers
DataGrail includes two custom headers in the request for identification and security purposes.
| Name | Description |
|---|---|
| X-Webhook-Signature | HMAC-SHA256 signature to verify the request originated from DataGrail. |
| X-Webhook-Timestamp | Timestamp of when the request was sent. |
Deletion Dispatch Body
The DROP deletion notification body includes the following parameters:
| Name | Description |
|---|---|
| integration_name | string The integration display name in the DataGrail application. |
| integration_kind | string Always webhook. |
| webhook_request_id | string(UUID) A unique identifier for the webhook request. |
| request_type | string Always drop_deletion — distinguishes from DSR webhooks. |
| topic | string Always drop.deletion:create. |
| request_uuid | string(UUID) DataGrail's internal tracking ID for this deletion — echo this back in your outcome callback. |
| integration_id | string(UUID) The UUID of your configured webhook integration. |
| identifier_hash | string SHA-256 hash of the matched consumer identifier. |
| hash_type | enum Which list type matched: email, phone, ndz, name_vin, maid, ctvid. |
| drop_session_id | string(UUID) The specific DROP session/cycle this match came from. |
| match_date | string Date the match occurred. |
| broker_id | string Your four-digit CalPrivacy data broker registration number. |
| mode | enum Broker Registration mode: test or production. |
| remote_identifier | string Your consumer pointer — the same value you sent during ingestion (omitted if none was provided). |
| webhook_callback_url | string The URL to PUT your outcome to once the deletion is complete. |
{
"broker_id": "4821",
"drop_session_id": "f0e1d2c3-b4a5-6789-0fed-cba987654321",
"hash_type": "email",
"identifier_hash": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d",
"integration_id": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
"integration_kind": "webhook",
"integration_name": "Your Integration Name",
"match_date": "2026-05-30",
"mode": "test",
"remote_identifier": "0035f00000A1B2CAAZ",
"request_type": "drop_deletion",
"request_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"topic": "drop.deletion:create",
"webhook_callback_url": "https://acme.datagrail.io/api/v2/webhooks/callback"
}
Deletion Dispatch Responses
Return 2xx to acknowledge receipt, then process the deletion asynchronously.
Deletion Outcome Callback
After processing the deletion, notify DataGrail of completion by sending a callback. Use ticket_uuid from the original request to correlate the callback.
Deletion Outcome Method
The callback must be an HTTP PUT request to the webhook_callback_url provided in the deletion dispatch.
Deletion Outcome API Key
The callback request must include an API key with the Webhook Callback scope. You can create an API key in DataGrail by navigating to Settings > API Keys > Create API Key.
Deletion Outcome Body
| Name | Description |
|---|---|
| schema_version | string The schema version of the callback body, currently 1.0. |
| status | string Always completed. |
| request_uuid | string(UUID) Echoes request_uuid from the original deletion dispatch. |
| drop_outcome | enum(Deletion Outcome Values) The outcome of the deletion. |
| error_message | string (optional) Required when drop_outcome is failed. |
{
"schema_version": "1.0",
"status": "completed",
"request_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"drop_outcome": "deleted",
"error_message": null
}
Deletion Outcome Values
| Enum | DROP Status Code | Description |
|---|---|---|
| deleted | 3 | Consumer's non-exempt personal information was deleted. |
| not_found | 5 | Consumer not found in your system. |
| opted_out | 4 | Multiple consumers are linked to this identifier and all were opted out of sale or sharing. |
| exempt | 2 | All personal information for this consumer is exempt per Civil Code §1798.99.86. |
| failed | — | Processing failed (provide error_message). |
Reporting a Webhook Opt-Out
An opt-out occurs when multiple consumers are linked to the same identifier and all are opted out of the sale or sharing of their personal information — rather than having their data deleted. This is DROP status code 4, as defined in CCR Title 11, §7614(b)(2)(D).
Return drop_outcome: "opted_out" when the matched identifier resolves to multiple consumers, and your system opts all of them out of sale or sharing rather than deleting their data. Include the resolved consumer email in identifiers.email:
| Name | Description |
|---|---|
| identifiers.email[0].email | string Required when drop_outcome is opted_out. The resolved consumer email address. |
{
"schema_version": "1.0",
"status": "completed",
"request_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"drop_outcome": "opted_out",
"identifiers": {
"email": [{ "email": "consumer@example.com" }]
},
"error_message": null
}
Opt-out does not remove data — it suppresses sale and sharing. Use opted_out when you retain the consumer's data under an opt-out rather than performing a full deletion. If you delete the data entirely, use deleted (code 3) instead.
Return the consumer email address exactly as stored in your system. Do not trim whitespace, lowercase, or otherwise normalize the email value. DataGrail uses the exact value you return to create the opt-out record.
Sequence Diagram
DROP Identifier Retrieval
DataGrail sends this notification to your webhook endpoint to retrieve clear identifiers for a matched consumer so it can issue deletions to 3rd-party SaaS systems (Salesforce, HubSpot, etc.) on your behalf. It uses the same Deletion Dispatch Headers as the Deletion Dispatch notification.
Only after a DROP match, and only if you have 3rd-party SaaS connections configured in DataGrail that require clear identifiers to process deletions. If you only need internal deletions handled by the Deletion Dispatch notification above, this notification is not sent.
Identifier Retrieval Body
In addition to the Deletion Dispatch Body parameters, the DROP identifier retrieval notification body includes the following:
| Name | Description |
|---|---|
| broker_id | string Your four-digit CalPrivacy data broker registration number. |
| drop_session_id | string(UUID) The specific DROP session/cycle this match came from. |
| identifiers.external_id[0].external_id | string Your consumer pointer — the same value you sent during ingestion. |
| integration_id | string(UUID) The UUID of your configured webhook integration. |
| match_date | string Date the match occurred. |
| mode | enum Broker Registration mode: test or production. |
| request_type | string Always drop_resolution — distinguishes from the deletion dispatch. |
| request_uuid | string(UUID) DataGrail's internal tracking ID for this resolution. |
| results_token | string Hexadecimal string to echo back on your outcome callback. |
| topic | string Always drop.resolution:create. |
{
"broker_id": "4821",
"drop_session_id": "f0e1d2c3-b4a5-6789-0fed-cba987654321",
"identifiers": {
"external_id": [{ "external_id": "0035f00000A1B2CAAZ" }]
},
"integration_id": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
"integration_kind": "webhook",
"integration_name": "Your Integration Name",
"match_date": "2026-05-30",
"mode": "test",
"request_type": "drop_resolution",
"request_uuid": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"results_token": "a1b2c3d4e5f67890",
"topic": "drop.resolution:create",
"webhook_callback_url": "https://acme.datagrail.io/api/v2/webhooks/callback",
"webhook_request_id": "8b6b1f2a-7f3e-4b9a-9c3d-2e6f7a8b9c0d"
}
Identifier Retrieval Responses
Return 2xx to acknowledge receipt, then resolve the identifiers asynchronously.
Identifier Retrieval Outcome Callback
PUT the resolved identifiers to the webhook_callback_url provided in the notification. Use results_token from the original request to correlate the callback — DataGrail matches inbound resolution outcomes by this token rather than by ticket ID.
| Name | Description |
|---|---|
| status | string Always completed. |
| results_token | string Echoes results_token from the original notification. |
| drop_outcome | enum (optional) opted_out or exempt — set when the resolved consumer should not be deleted directly. |
| exemption_basis | string (optional) Required when drop_outcome is exempt (e.g. first_party, glba, legal_hold). |
| identifiers | object The resolved consumer identifiers, keyed by category (e.g. email). |
Send resolved email addresses exactly as they exist in your system — do not lowercase or trim them. DataGrail matches DROP identifiers on the verbatim value.
{
"status": "completed",
"results_token": "a1b2c3d4e5f67890",
"identifiers": {
"email": [{ "email": "alice@example.com" }, { "email": "alice.work@example.com" }]
}
}
ISI (Internal Systems Integration)
ISI is a customer-hosted REST API that DataGrail calls into. DROP adds two new endpoints to the existing ISI spec.
This section covers DROP-specific endpoints and builds on the standard API Specification documentation.
Prerequisites
Your ISI API must:
- Serve over HTTPS with TLS 1.2+
- Authenticate via OAuth 2.0 Client Credentials or static bearer token
- Advertise DROP capabilities in
/api/v1/connections/list:
{
"results": [
{
"uuid": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
"capabilities": [
"privacy/access",
"privacy/delete",
"privacy/drop/identifiers",
"privacy/drop/delete"
]
}
]
}
DROP Delete Endpoint
DataGrail will call this endpoint when a DROP match occurs and your system needs to perform the deletion. This endpoint is asynchronous and should not return results.
When the request has been processed, results should be returned by triggering the DataGrail Webhook Callback.
DROP Delete Endpoint URL
POST /api/v1/privacy/drop/delete/:connection-uuid
DROP Delete Headers
| Parameter | Description |
|---|---|
| Authorization | string Your bearer token. |
DROP Delete Path Parameters
| Parameter | Description |
|---|---|
| connection-uuid | UUID The connection UUID |
DROP Delete Body Parameters
| Parameter | Description |
|---|---|
| request_uuid | string(UUID) Request in DataGrail. |
| results_token | string Hexadecimal string used to retrieve the results of this request. |
| callback_path | string URL path to use for the Webhook Callback. Append to your customer domain. |
| drop_context.broker_id | string Your four-digit CalPrivacy data broker registration number. |
| drop_context.drop_session_id | string(UUID) The specific DROP session/cycle this match came from. |
| drop_context.hash_type | string Which list type matched. |
| drop_context.match_date | string Date the match occurred. |
| remote_identifier | string Your consumer pointer — the same value sent during ingestion. |
| remote_identifier_kind | string The kind of remote identifier provided. |
DROP Delete Success Response
The request was accepted and the process to respond to the request will be initiated.
{
"status": "processing"
}
Your callback when deletion completes:
{
"status": "completed",
"results_token": "a1b2c3d4e5f67890",
"drop_outcome": "deleted",
"completed_at": "2026-05-30T18:45:00Z"
}
DROP deletions have different requirements than standard DSR deletions — different regulatory timelines, audit trails, and customer-side workflows. A separate endpoint ensures you can implement DROP-specific handling without affecting your DSR pipeline.
Reporting an ISI Opt-Out
An opt-out occurs when multiple consumers are linked to the same identifier and all are opted out of the sale or sharing of their personal information — rather than having their data deleted. This is DROP status code 4, as defined in CCR Title 11, §7614(b)(2)(D).
Return drop_outcome: "opted_out" when the matched identifier resolves to multiple consumers, and your system opts all of them out of sale or sharing rather than deleting their data. Include the resolved consumer email in identifiers.email:
{
"status": "completed",
"results_token": "a1b2c3d4e5f67890",
"drop_outcome": "opted_out",
"identifiers": {
"email": [{ "email": "consumer@example.com" }]
},
"completed_at": "2026-05-30T18:45:00Z"
}
Opt-out does not remove data — it suppresses sale and sharing. Use opted_out when you retain the consumer's data under an opt-out rather than performing a full deletion. If you delete the data entirely, use deleted (code 3) instead.
Return the consumer email address exactly as stored in your system. Do not trim whitespace, lowercase, or otherwise normalize the email value. DataGrail uses the exact value you return to create the opt-out record.
DROP Identifier Retrieval Endpoint
DataGrail will call this endpoint to retrieve clear identifiers for a matched consumer so it can issue deletions to 3rd-party SaaS systems (Salesforce, HubSpot, etc.) on your behalf. This endpoint is synchronous and must return results in the response.
DROP Identifier Retrieval Endpoint URL
POST /api/v2/privacy/drop/identifiers/:connection-uuid
DROP Identifier Retrieval Headers
| Parameter | Description |
|---|---|
| Authorization | string Your bearer token. |
DROP Identifier Retrieval Path Parameters
| Parameter | Description |
|---|---|
| connection-uuid | UUID The connection UUID |
DROP Identifier Retrieval Body Parameters
| Parameter | Description |
|---|---|
| request_uuid | string(UUID) Request in DataGrail. |
| remote_identifier | string Your consumer pointer — the same value sent during ingestion. |
| remote_identifier_kind | string The kind of remote identifier provided. |
| identifier_categories | array The identifier categories to retrieve. |
DROP Identifier Retrieval Success Response
The request was accepted and the results are available in the response body.
{
"identifiers": {
"email": [{ "email": "alice@example.com" }, { "email": "alice.work@example.com" }],
"phone": [{ "phone": "+15551234567" }]
}
}
Only after a DROP match, and only if you have 3rd-party SaaS connections configured in DataGrail that require clear identifiers to process deletions. If you only need internal deletions handled by the DELETE endpoint above, this endpoint is not required.
Disclaimer: The information contained in this message does not constitute as legal advice. We would advise seeking professional counsel before acting on or interpreting any material.