Transcend sends notifications to your server to determine additional metadata before the privacy request gets distributed across your Integrations.

Preflight check webhooks are useful for two reasons:

  1. Add in a programmatic hook to automatically cancel or place a request on hold
  2. Enrich additional identifiers for the user.

Under the "Privacy Requests > Identifiers" section of the Admin Dashboard, you can create a new enricher that is of type "server webhook". You will select which type of identifier should trigger your webhook, and whenever this identifier is queued up in a privacy request job, a webhook will be sent. If the privacy request job has multiple identifiers of the same type, multiple webhooks will be sent.

We recommend listening on a path such as /webhooks/transcend/preflight-request-job.

POST

to the webhook URL you specify in your integration settings

Request Authorization

Verify the Sombra token, which is a JWT asymmetrically signed with the ES384 algorithm, and can be found on the request header x-sombra-token. Read this guide for information on how to get Transcend's public key and verify the signature.

Request Parameters

Header Parameters

x-sombra-token string
A token used for webhook authentication, containing a JSON Web Token (JWT) asymetrically signed with the ES384 algorithm.
x-transcend-nonce string
A token sent in Transcend's webhook for this job, and returned by you when uploading the result of this job back to Transcend.

Request Body

application/json

coreIdentifier object(required)
type string(required)enum: "ACCESS" | "ERASURE" | "ACCOUNT_DELETION" | "AUTOMATED_DECISION_MAKING_OPT_OUT" | "CONTACT_OPT_OUT" | "SALE_OPT_OUT" | "TRACKING_OPT_OUT" | "RECTIFICATION" | "RESTRICTION"
The type of privacy request received. Only the request types you enable in Transcend will be sent. If your system does not need to perform the operation, you can configure the workflow such that the webhook is never sent for a particular request type in the Manager Datapoints on the Integrations page.
dataSubject object(required)
Information about the data subject making this request.
isTest boolean(required)
Whether or not the request is flagged as a test request in the platform. Your normally don't need to worry about this parameter.
extras object(required)
requestIdentifier object(required)
The user identifier that is the input to this preflight check. You should use the values here to preform your preflight check. Note: this field is present in the the preflight job webhook but not the privacy request job webhook. If you host both of these webhooks on the same endpoint, you can use the presence of this key to determine if the webhook is meant for a preflight check or a privacy request job.

Request Body Examples

Receive an access request:

{
"type": "ACCESS",
"dataSubject": {
"type": "customer"
},
"isTest": false,
"requestIdentifier": {
"name": "email",
"value": "test@transcend.io"
},
"extras": {
"identifier": {
"id": "06835a9c-160c-46fc-a1d1-9dec9bffbef2",
"name": "email",
"value": "email"
},
"enricher": {
"id": "a8166ee2-e196-4967-94f3-769e730f88dd"
},
"request": {
"details": "",
"id": "303b8129-70d9-47b9-b408-aa5ddca398e4",
"link": "https://app.transcend.io/request/303b8129-70d9-47b9-b408-aa5ddca398e4",
"createdAt": "2022-03-04T02:50:42.257Z",
"locale": "fr-FR",
"origin": "PRIVACY_CENTER"
},
"organization": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"uri": "e-shop-it",
"name": "eShopIt"
},
"requestEnricherId": "eaffecf6-f70a-46cf-bff5-09764288def2"
},
"coreIdentifier": {
"value": "jane.doe@example.com"
}
}

Receive an erasure request:

{
"type": "ERASURE",
"dataSubject": {
"type": "customer"
},
"isTest": false,
"requestIdentifier": {
"name": "user_id",
"value": "123456"
},
"extras": {
"identifier": {
"id": "407fb0db-b4e7-4649-95b5-56a9c8e063ff",
"name": "custom",
"value": "user_id"
},
"enricher": {
"id": "a8166ee2-e196-4967-94f3-769e730f88dd"
},
"request": {
"details": "",
"id": "8152397f-152e-4c80-896d-03ad9ebea832",
"link": "/request/8152397f-152e-4c80-896d-03ad9ebea832",
"createdAt": "2022-03-04T03:52:38.696Z",
"locale": "en",
"origin": "ADMIN_DASHBOARD"
},
"organization": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"uri": "e-shop-it",
"name": "eShopIt"
},
"dataSilo": {
"id": "12dd1fd8-b310-4712-ba6b-0e2e29ecd2ac",
"title": "My Custom integration",
"description": "Our production application backend. Calls a function that exports or deletes a user from our service.",
"link": "https://app.transcend.io/infrastructure/connected-services/configuration/12dd1fd8-b310-4712-ba6b-0e2e29ecd2ac"
},
"requestEnricherId": "66301191-aecb-49eb-9f9a-c06ccb2da118"
},
"coreIdentifier": {
"value": "jane.doe@example.com"
}
}

Response

200 (OK)

application/json

The webhook was received successfully. No response body is required. Typically, your job will run async, so the output of your job can be reported through a separate API request from your system to Transcend. In this case, Transcend will expect a follow up API request at some point in the future. If no job is received after some time, the webhook will be retried. The retry rate is variable but normally within 24 hours. You can optionally include a `status` in the response body, which transitions the request to that state. Note: if you want to specify an email template, you will have to follow up using one of the asynchronous routes.

Response Body

status stringenum: "CANCELED" | "ON_HOLD"
If your preflight check can respond immediately, you can respond directly to this webhook to either cancel the request entirely or place the request on hold and pause further processing. If your preflight check is async, then omit this field, and instead follow up asynchronously through a separate API request.

204 (No Content)

application/json

The job was received and no work needs to be done. Transcend should not expect a follow up response in the future. The job will be marked as SKIPPED and the webhook will not be retried.

400 (Bad Request)

application/json

Any 4xx error code indicates that your system failed receive our webhook. Transcend will retry the webhook up to 5 times, once per hour. After 5 attempts, you will have to go into the Admin Dashboard to manually restart the request.