OpenDSR (GDPR) API Reference

Learn how to use the Singular API to support GDPR requests.

For how data subject requests fit into a broader consent architecture — and why erasure is not the same as stopping tracking — see Consent Management with the Singular SDK: A Decision Framework .

Erasure is not an opt-out.

This API deletes the user-level data Singular has collected for an identifier. It does not stop the SDK on the user's device from sending future events. A user who exercises erasure and should also stop being tracked needs the app to call stopAllTracking() (or gate SDK initialization) in addition to submitting the API request. Handle both in the same user flow.

GDPR Endpoints

Endpoint Method URL Description
Discovery GET https://gdpr.singular.net/gdpr/discovery Returns all currently supported request types that Singular can process through the GDPR API.
Requests POST https://gdpr.singular.net/gdpr/requests Use this endpoint to send new GDPR requests, sent through an HTTP POST request while specifying the Device IDs for the requested data subjects.
Status GET https://gdpr.singular.net/gdpr/requests/request_id Returns the current status for a previously sent request, identified by its Request ID.
Cancellation DELETE https://gdpr.singular.net/gdpr/requests/request_id Use this endpoint to cancel a previous request. This is possible as long as the request is in "pending" status.

Discovery Endpoint

GET https://gdpr.singular.net/api/gdpr/discovery

Usage

The OpenDSR Discovery endpoint returns all currently supported request types that Singular can process through the GDPR API.

Sample Query

import requests
  response = requests.get("https://gdpr.singular.net/api/gdpr/discovery")
  print(response.text)

Sample Output

{
    "api_version": "0.1.4",
    "supported_identities": [
      {"identity_format": "raw","identity_type": "android_advertising_id"},
      {"identity_format": "raw","identity_type": "android_id"},
      {"identity_format": "raw","identity_type": "ios_advertising_id"},
      {"identity_format": "raw","identity_type": "ios_vendor_id"},
      {"identity_format": "raw","identity_type": "user_id"}
    ],
    "supported_subject_request_types": [
        "erasure",
        "access"
    ]
  }

Requests Endpoint

POST https://gdpr.singular.net/api/gdpr/requests

Usage

The OpenDSR Requests endpoint handles new GDPR requests, sent through an HTTP POST request while specifying the Device IDs for the requested data subjects.

Completion time: Erasure requests complete within up to 30 days of submission. The response returns an expected_completion_time; use it to set your GDPR Article 12 response commitments.

Supported Requests

The OpenDSR Requests endpoint supports the following types of requests, corresponding to different GDPR rights:

  • `erasure` - supporting user requests for data erasure as part of the GDPR's Article 17, Right to erasure
  • `access` - supporting user requests for data access as part of the GDPR's Article 15, Right to access

Supported IDs

The OpenDSR Requests endpoint supports the following types of IDs:

  • `android_advertising_id` - requests made by providing the Google Advertising ID, which is also known as GAID or AIFA
  • `android_id` - requests made by providing the Android ID, which is also known as ANDI
  • `ios_advertising_id` - requests made by providing IDFA, which is the iOS Advertising ID
  • `ios_vendor_id` - requests made by providing IDFV, which is the iOS ID for Vendors
  • `user_id` - requests made by providing the Custom User ID

Zeroed IDFAs are silently ignored.

On devices with limit-ad-tracking enabled or an ATT AuthorizationStatus of denied, the IDFA is zeroed ("00000000-0000-0000-0000-000000000000"). Requests keyed to a zeroed IDFA are ignored and the API does not return an error. Submit the `ios_vendor_id` (IDFV) for these users instead. Because the failure is silent, your DSR pipeline must carry and submit the IDFV for ATT-denied iOS users.

Sample Query

import requests
  
  url = "https://gdpr.singular.net/api/gdpr/requests"
  
  payload = {
    "subject_request_id": "1c8b23f4-12eb-4fe8-af1c-0f72807dfec2",
    "subject_request_type": "access",
    "submitted_time": "2018-05-25T10:00:00Z",
    "subject_identities": [
      {
        "identity_type": "android_advertising_id",
        "identity_value": "38400000-8cf0-11bd-b23e-10b96e40000d",
        "identity_format": "raw"
      }
    ],
    "property_id": "Android:com.myapp.xyz",
  }
  
  headers = {
    "content-type": "application/json",
    "Authorization": "[API_KEY]"
  }
  
  response = requests.post(url, json=payload, headers=headers)
  print(response.text)

Query Parameters

Parameter Format Description Example
subject_request_id String UUIDv4 string
subject_request_type String String value representing the type of OpenDSR Request. Singular currently supports the values: "erasure", "access"
subject_identities Array A list of identity objects describing the type, value and format for each Device ID to fulfill the request for. A request can contain up to 100 Device IDs.
[
  {
    "identity_type":
"android_advertising_id", "identity_value":
"38400-8cf0-11bd-b23e-1000d", "identity_format": "raw" } ]
submitted_time RFC 3339 date string representing the time of the original request by the data subject 2010-05-25T10:00:00Z
property_id String The [platform]:[longname] pair to specify the relevant app. iOS:com.myapp.xyz

Sample Output

{
    "controller_id":"example_controller_id",
    "received_time":"2018-05-25T10:00:01Z",
    "expected_completion_time": "2018-06-24T10:00:01Z",
    "encoded_request":"<BASE64 ENCODED REQUEST>",
    "subject_request_id":"1c8b23f4-12eb-4fe8-af1c-0f72807dfec2",
    "results_url": "https://url-to-results-in-json-format",
    "api_version": "0.1.4"
  }

Scope of deletion

Erasure removes the user-level records — logs and attribution detail — that Singular holds for the identifier. Aggregated data (for example, cohort rollups) is not device-addressable once aggregated and is unaffected by erasure. Describe this distinction in your own privacy documentation.

Status Endpoint

GET https://gdpr.singular.net/api/gdpr/requests/<REQUEST_ID>

Usage

Returns the current status for a previously sent request, identified by its Request ID.

Sample Query

import requests
  url = "https://gdpr.singular.net/api/gdpr/requests/"
  subject_request_id = "1c8b23f4-12eb-4fe8-af1c-0f72807dfec2"
  headers = {"Authorization": "<API KEY>"}
  response = requests.get(url+subject_request_id, headers=headers)
  print(response.text)

Sample Output

{
      "controller_id": "example_controller_id",
      "request_status": "completed",
      "expected_completion_time": "2018-06-24T10:00:01Z",
      "subject_request_id": "1c8b23f4-12eb-4fe8-af1c-0f72807dfec2",
      "api_version": "0.1.4"
  }

Cancellation Endpoint

DELETE https://gdpr.singular.net/gdpr/requests/<REQUEST_ID>

Usage

Use this endpoint to cancel a previous request. This is possible as long as the request is in "pending" status.

Sample Query

import requests
  url = "https://gdpr.singular.net/api/gdpr/requests/"
  subject_request_id = "1c8b23f4-12eb-4fe8-af1c-0f72807dfec2"
  headers = {"Authorization": "<API KEY>"}
  response = requests.delete(url+subject_request_id, headers=headers)
  print(response.text)

Sample Output

{
    "controller_id":"example_controller_id",
    "subject_request_id":"1c8b23f4-12eb-4fe8-af1c-0f72807dfec2",
    "received_time":"2018-05-25T10:00:01Z",
    "api_version":"0.1"
  }