Document Type: API Integration Guide · Audience: Data Broker System Developers · Version: 2.0 · Last updated: 2026-05-29
This guide describes the integration between the DROP Portal and the IRM (Identity and Request Management) system for processing Data Subject deletion requests. It covers the API operations a Data Broker system performs to ingest, tag, close, and report on DROP-sourced requests.
This document focuses on the three steps that require direct API integration: creating a request in IRM (Step 4), closing it after deletion (Step 6), and polling for closed requests to report back to the DROP Portal (Step 7).
| Step | System | Action |
|---|---|---|
| 1 | DROP Portal | Data Subject submits a deletion request through the DROP Portal. |
| 2 | Data Broker | Downloads the deletion list periodically. |
| 3 | Data Broker | Prepares the payload for IRM ingestion. |
| 4 ★ | Data Broker → IRM | Creates the request in IRM and applies a label to tag it as DROP-sourced. |
| 5 | IRM | Request is created; associated tasks are generated per task-template configuration. |
| 6 ★ | Data Broker → IRM | Performs deletion in its own system and closes the IRM request. |
| 7 ★ | Data Broker → IRM | Polls IRM for closed DROP-labeled requests and reports completion back to the DROP Portal. |
★ Steps covered in this guide.
All endpoints use the IRM application base path /api/v1 on your deployed IRM host. Every request requires the following headers:
Authorization: Bearer <access_token> Content-Type: application/json Accept: application/json
Requests are created against a specific form, and the request body is keyed by that form's field IDs — not display labels. Always discover the form and its fields first, then build your create payload from those IDs.
GET /api/v1/external/forms/all Authorization: Bearer <access_token> Accept: application/json
Optional query parameters: name, statuses, brandName, brandIds.
Sample response:
[
{
"id": "8c2a1f3e-1111-4aaa-9bbb-1234567890ab",
"name": "DROP Deletion Intake",
"status": "PUBLISHED",
"brandName": "Acme"
}
]
Use the id of the appropriate form as your formId in subsequent calls.
GET /api/v1/external/requests?formId={formId}
Authorization: Bearer <access_token>
Accept: application/json
Optional query parameter: locale.
Sample response:
{
"name": "DROP Deletion Intake",
"fields": [
{ "id": "00000000-0000-0000-0000-00000000100a", "display": "First Name", "type": "string", "dataType": "text", "required": true, "values": [] },
{ "id": "00000000-0000-0000-0000-00000000100b", "display": "Last Name", "type": "string", "dataType": "text", "required": true, "values": [] },
{ "id": "00000000-0000-0000-0000-000000001003", "display": "Email", "type": "string", "dataType": "email", "required": true, "values": [] },
{ "id": "00000000-0000-0000-0000-000000001004", "display": "Country", "type": "string", "dataType": "select", "required": false,
"values": [
{ "id": "PH", "display": "Philippines" },
{ "id": "US", "display": "United States" }
]
},
{ "id": "7c9e6a1b-3d2f-4a5e-8b10-2f6c4d8a1e90", "display": "Account Number", "type": "string", "dataType": "text", "required": false, "values": [] }
]
}
Create the request against the form discovered in the previous step.
POST /api/v1/external/requests?formId={formId}&verifyEmail=false
Authorization: Bearer <access_token>
Content-Type: application/json
| Parameter | Required | Description |
|---|---|---|
formId
|
Yes | The form ID from Step 4.1. Defines the request type, data-subject type, and valid fields. |
verifyEmail
|
No |
Defaults
true.
Set
false
to skip email verification for DROP-sourced batches.
|
locale
|
No | Locale for the request. Defaults to the form's default locale. |
sourceWebsite
|
No | Origin website string for provenance tracking. |
ipAddress
|
No | Originating IP address for provenance tracking. |
A flat map of form field UUID → value, using the field IDs read in Step 4.1:
{
"00000000-0000-0000-0000-00000000100a": "Juan",
"00000000-0000-0000-0000-00000000100b": "Dela Cruz",
"00000000-0000-0000-0000-000000001003": "juan.delacruz@email.com",
"00000000-0000-0000-0000-000000001004": "PH",
"7c9e6a1b-3d2f-4a5e-8b10-2f6c4d8a1e90": "ACME-99231"
}
{
"seqId": "seq_001",
"resultType": "REQUEST_CREATED",
"message": "Request created successfully.",
"result": {
"id": "3f1c0a9e-7b2d-4c5a-9f10-2a8e6d4b1c77",
"status": "UNVERIFIED",
"...": "full request object"
}
}
Labels are tags identified by name. Apply the DROP label to the request you just created by addressing the label by name in the path. No request body is needed.
PUT /api/v1/external/requests/{requestId}/labels/name/{labelName}
Authorization: Bearer <access_token>
| Path Parameter | Required | Description |
|---|---|---|
requestId
|
Yes | The request UUID returned from Step 4.2. |
labelName
|
Yes |
The label to add. Use
DROP
for DROP-sourced requests.
|
Sample request:
PUT /api/v1/external/requests/3f1c0a9e-7b2d-4c5a-9f10-2a8e6d4b1c77/labels/name/DROP
Response — the applied label:
{ "id": "9f8e7d6c-...", "name": "DROP" }
# List labels on a request
GET /api/v1/external/requests/{id}/labels
# Remove a label
DELETE /api/v1/external/requests/{requestId}/labels/name/{labelName}
GET response:
{ "labels": [ { "id": "9f8e7d6c-...", "name": "DROP" } ] }
POST /api/v1/external/requests/{id}/close
Authorization: Bearer <access_token>
Content-Type: application/json
{
"status": "ACCEPT",
"sendEmail": false,
"rejectReason": null,
"noEmailReason": "Closed by Data Broker after deletion."
}
| Field | Required | Description |
|---|---|---|
status
|
Yes |
ACCEPT
to approve the deletion or
REJECT
to deny it.
|
sendEmail
|
No |
Whether to send a closure notification to the
data subject. Defaults
true;
set
false
for DROP batch closures.
|
rejectReason
|
Conditional |
Required when
status
is
REJECT.
|
noEmailReason
|
Conditional |
Required when
sendEmail
is
false.
|
emailTemplate
|
No | Optional template configuration for the closure email. |
The response returns the updated request object. Internally, ACCEPT resolves to CLOSED_ACCEPTED or CLOSED_ACCEPTED_NO_EMAIL, and REJECT to CLOSED_REJECTED or CLOSED_REJECTED_NO_EMAIL, depending on sendEmail. See the Status Lifecycle below.
There is no single "closed" status. Several closed-state values exist:
UNVERIFIED ──(verify)──► IN_PROGRESS ──(close)──► CLOSED_ACCEPTED
CLOSED_REJECTED
CLOSED_ACCEPTED_NO_EMAIL
CLOSED_REJECTED_NO_EMAIL
CLOSED_EXPIRED
CLOSED_ID_FAILED
CLOSED_LIMIT_EXCEEDED
...
Search for requests using a JSON filter body. Results are returned as a paginated response.
POST /api/v1/external/requests/search?page=0&size=100&sort=createdDate,desc Authorization: Bearer <access_token> Content-Type: application/json Accept: application/json
| Parameter | Description |
|---|---|
page
|
0-based page index. Defaults to
0.
|
size
|
Page size. Defaults to
25.
|
sort
|
Sort expression, e.g.
createdDate,desc.
|
{
"labelNames": ["DROP"],
"statuses": ["CLOSED_ACCEPTED", "CLOSED_REJECTED"],
"fromModifiedDate": "2026-05-01T00:00:00Z"
}
| Field | Type | Description |
|---|---|---|
labelNames
|
string set |
Filter by label name(s). Use
["DROP"].
|
statuses
|
enum set | One or more status values. Typically one or more closed states — see Status Lifecycle. |
fromModifiedDate / toModifiedDate
|
ISO-8601 |
Modified-date range. Use
fromModifiedDate
as an incremental cursor ("changed since last
poll").
|
fromCreatedDate / toCreatedDate
|
ISO-8601 | Created-date range. |
fromDueDate / toDueDate
|
ISO-8601 | Due-date range. |
email, name, ids, formIds, requestTypeIds, dataSubjectTypeIds
|
— | Additional optional filters. |
notLabelNames / notLabelIds
|
set | Exclude requests carrying these labels. |
{
"content": [
{
"id": "3f1c0a9e-7b2d-4c5a-9f10-2a8e6d4b1c77",
"status": "CLOSED_ACCEPTED",
"...": "request fields"
}
],
"pageable": { "pageNumber": 0, "pageSize": 100 },
"totalElements": 2,
"totalPages": 1,
"first": true,
"last": true,
"numberOfElements": 2
}
1. GET /api/v1/external/forms/all → find DROP formId
2. GET /api/v1/external/requests?formId=... → read field IDs
For each deletion_request in batch:
3. POST /api/v1/external/requests?formId=...&verifyEmail=false → obtain request UUID
4. PUT /api/v1/external/requests/{id}/labels/name/DROP → apply DROP label
5. Persist { drop_request_id, irm_request_uuid } locally for polling/reporting
| Operation | Access Required |
|---|---|
| List forms / read form fields | Form view access + external API access |
| Create request | Create-request access on the form + external API access |
| Apply / remove labels | Label-update access on the request + external API access |
| Close request | Close/complete access on the request + external API access |
| Poll requests | Request view access on the account + external API access |
| TrustArc · DROP Process to IRM — API Integration Guide · support.trustarc.com | v2.0 · 2026-05-29 |