Skip to main content

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.

Prerequisites

Before implementing a dispatch pattern, ensure you have:


Webhook

DataGrail POSTs to a URL you configure when a DROP match occurs.

Deletion Dispatch (DataGrail → You)

POST <your-webhook-url>
Content-Type: application/json
X-Datagrail-Event: drop.deletion
X-Webhook-Timestamp: 1717027200
X-Webhook-Signature: v1=<base64(HMAC-SHA256(shared_secret, "<timestamp>:<body>"))>

Request body:

{
"schema_version": "1.0",
"event": "drop.deletion",
"ticket_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"broker_id": "4821",
"drop_session_id": "f0e1d2c3-b4a5-6789-0fed-cba987654321",
"hash_type": "email",
"match_date": "2026-05-30",
"remote_identifier": "0035f00000A1B2CAAZ",
"remote_identifier_kind": "external_id",
"callback_url": "https://yourcompany.datagrail.io/api/v2/webhooks/callback"
}

Fields:

FieldDescription
eventAlways "drop.deletion" — distinguishes from DSR webhooks
ticket_uuidDataGrail's internal tracking ID for this deletion
broker_idYour CalPrivacy data broker registration number
drop_session_idThe specific DROP session/cycle this match came from
hash_typeWhich list type matched: email, phone, ndz, name_vin, maid, ctvid
remote_identifierYour consumer pointer — the same value you sent during ingestion
remote_identifier_kindHow to interpret the pointer: external_id, row_uuid, email, phone
callback_urlURL to POST your outcome to when deletion is complete

Return 2xx to acknowledge receipt. Process the deletion asynchronously.

Signature verification: Compute HMAC-SHA256(shared_secret, "<X-Webhook-Timestamp>:<raw-body>"), Base64-encode, and compare to the value after v1= in X-Webhook-Signature.

Deletion Outcome Callback (You → DataGrail)

After processing the deletion, POST the outcome to the callback_url provided in the webhook. Use ticket_uuid from the original request to correlate the callback.

POST <callback_url>
Content-Type: application/json
Authorization: Bearer <your-datagrail-api-token>
{
"schema_version": "1.0",
"status": "completed",
"ticket_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"drop_outcome": "deleted",
"completed_at": "2026-05-30T18:45:00Z",
"failure_reason": null
}

drop_outcome values:

ValueDROP Status CodeMeaning
deleted3Consumer's non-exempt personal information was deleted
not_found5Consumer not found in your system
opted_out4Multiple consumers are linked to this identifier and all were opted out of sale or sharing (see Opt-Out Processing)
exempt2All personal information for this consumer is exempt per Civil Code §1798.99.86
failedProcessing failed (provide failure_reason)

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.

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 calls this when a DROP match occurs and your system needs to perform the deletion.

POST /api/v1/privacy/drop/delete/<connection-uuid>
Authorization: Bearer <token>
Content-Type: application/json

Request body:

{
"request_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"results_token": "a1b2c3d4e5f67890",
"callback_path": "/api/v2/internal_systems/request_callback",
"drop_context": {
"broker_id": "4821",
"drop_session_id": "f0e1d2c3-b4a5-6789-0fed-cba987654321",
"hash_type": "email",
"match_date": "2026-05-30"
},
"remote_identifier": "0035f00000A1B2CAAZ",
"remote_identifier_kind": "external_id"
}

Your immediate response:

HTTP/1.1 200 OK
{"status": "processing"}

Your callback when deletion completes:

{
"status": "completed",
"results_token": "a1b2c3d4e5f67890",
"drop_outcome": "deleted",
"completed_at": "2026-05-30T18:45:00Z"
}
Why is this separate from /privacy/delete?

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.

DROP Identifier Retrieval Endpoint

DataGrail calls this to retrieve clear identifiers for a matched consumer so it can issue deletions to 3rd-party SaaS systems (Salesforce, HubSpot, etc.) on your behalf.

POST /api/v2/privacy/drop/identifiers/<connection-uuid>
Authorization: Bearer <token>
Content-Type: application/json

Request body:

{
"request_uuid": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"remote_identifier": "0035f00000A1B2CAAZ",
"remote_identifier_kind": "external_id",
"identifier_categories": ["email", "phone"]
}

Your synchronous response:

HTTP/1.1 200 OK
{
"identifiers": {
"email": [{"email": "alice@example.com"}, {"email": "alice.work@example.com"}],
"phone": [{"phone": "+15551234567"}]
}
}
When is this endpoint called?

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.


Opt-Out Processing

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).

When to Return opted_out

Return drop_outcome: "opted_out" in your callback when:

  • The matched identifier resolves to multiple consumers in your system
  • Your system opts all of those consumers out of sale or sharing rather than deleting their data
  • The consumer's data is retained but no longer sold to or shared with third parties
Opt-Out vs. Deletion

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.

Opt-Out Callback Format

The callback fields are the same across both dispatch patterns — the only difference is the correlation field used to match the response to the original request. Return drop_outcome: "opted_out" with the resolved consumer email:

{
"schema_version": "1.0",
"status": "completed",
"ticket_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"results_token": "a1b2c3d4e5f67890",
"drop_outcome": "opted_out",
"identifiers": {
"email": [{"email": "consumer@example.com"}]
},
"completed_at": "2026-05-30T18:45:00Z"
}
FieldRequiredDescription
statusYesMust be "completed"
ticket_uuidWebhook onlyCorrelates the response to the original webhook dispatch
results_tokenISI onlyCorrelates the response to the original ISI request
drop_outcomeYes"opted_out" for opt-out processing
identifiers.email[0].emailYesThe resolved consumer email address
completed_atYesISO 8601 timestamp of when the opt-out was applied
Correlation Field

Use ticket_uuid for webhook callbacks and results_token for ISI callbacks. Include whichever field was provided in the original dispatch request.

Email Formatting

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.

Opt-Out Processing Lifecycle

The following diagram illustrates the end-to-end flow when your system responds with an opt-out outcome:

  1. DataGrail downloads the deletion list from the DROP registry and matches hashed identifiers against your stored consumer records.
  2. A match is found and DataGrail dispatches the request to your system using your configured dispatch method.
  3. Your system resolves the identifier and determines that multiple consumers are linked to it.
  4. Your system applies an opt-out (suppresses sale/sharing) for all linked consumers.
  5. Your system POSTs the callback to DataGrail with drop_outcome: "opted_out" and the resolved consumer email.
  6. DataGrail creates an opt-out record, updates the request status, and reports code 4 to the DROP registry.

Opt-Out Outcome by Pattern

Both patterns use the same callback fields — the only difference is how the callback reaches DataGrail:

PatternHow to respond with opt-out
WebhookPOST to the callback_url from the original webhook with drop_outcome: "opted_out" and ticket_uuid
ISIPOST to callback_path with drop_outcome: "opted_out" and results_token

Authentication Summary

The following table summarizes the authentication method for each dispatch pattern:

PatternAuth Method
Webhook (DataGrail → you)HMAC-SHA256 signature on each request
Webhook callback (you → DataGrail)Bearer token (provided by DataGrail)
ISI (DataGrail → you)OAuth 2.0 Client Credentials or static bearer token

Error Codes

The following HTTP status codes may be returned by DataGrail endpoints:

CodeMeaning
200Success
202Accepted (async processing started)
400Bad request — check response body for validation details
401Authentication failed
403Insufficient permissions
404Resource not found
409Conflict (e.g., duplicate upload in progress)
429Rate limited — respect Retry-After header
500Internal server error

Error response body:

{
"error": "validation_failed",
"message": "schema_version '2.0' is not supported",
"supported_versions": ["1.0"]
}

 

Need help?
If you have any questions, please reach out to your dedicated Account Manager or contact us at support@datagrail.io.

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.