Managing grievances
The DPDP Accelerator provides a tenant-scoped grievance (complaint) service for Data Principals and the people who handle their cases. The Consent Portal is the ready-made user interface; the same operations are available through the complaint API for an application or an integration.
Complete the Quickstart first. Assign users and roles as described in the Role Management Guide, then sign in again so new role scopes are present in their access tokens.
1. Understand the two access surfaces
The API has two deliberately separate namespaces:
| Surface | Who uses it | What it permits |
|---|---|---|
/me/complaints/* | The authenticated Data Principal | Create, view, reply to, and add public attachments to their own complaints |
/complaints/* | A complaint officer, DPO, administrator, or trusted system | Search and manage complaints across the tenant, add public replies or internal notes, change status, and manage attachments |
The service derives the Data Principal from the bearer token on the me
surface. Do not put a userId in a self-service request. A complaint officer
can create a complaint on behalf of a Data Principal through the management
surface when a complaint was received by phone, in person, or on paper.
All complaints and attachments are isolated by the Identity Server tenant. The examples below use:
https://<host>:9443/api/dpdp/complaints/v1
The examples below use these shell variables:
BASE_URL="https://localhost:9443"
ACCESS_TOKEN="<data-principal-access-token>"
OFFICER_ACCESS_TOKEN="<complaint-officer-access-token>"
2. Assign the required roles and scopes
The automatically provisioned roles grant these complaint permissions:
| Operation | Scope | Role |
|---|---|---|
| Create, list, view and reply to own complaints | complaints:read:self, complaints:write:self | dpdp-consent-user |
| List, view and manage all complaints | complaints:read:any, complaints:write:any | dpdp-consent-dpo |
Organization-wide complaint handling belongs to dpdp-consent-dpo alone —
dpdp-consent-admin does not receive complaint scopes, keeping complaint
oversight separate from portal administration (catalog, consent, and Event
Notification management). For machine-to-machine use, assign
complaints:read:self, complaints:write:self, complaints:read:any, or
complaints:write:any as appropriate to a dedicated integration role instead
of using a portal administrator role.
The examples use certificates trusted by the client. For a local Identity
Server using a self-signed certificate, add -k to a curl command only for
that local test. Do not use -k in a deployed environment; configure a trusted
CA or pass it explicitly with --cacert instead.
3. Configure deadlines and attachments
Set these values in deployment.toml under
[dpdp_accelerator.complaints]:
statutory_due_period_days = 90
attachment_max_size_bytes = 10485760
attachment_max_files_per_upload = 5
The due date is calculated from submission time. Each attachment must be a PDF, DOCX, PNG, or JPEG and must stay within the configured size limit. An upload request can contain up to the configured number of files. Restart Identity Server after changing these server-side limits.
4. Customize complaint notification emails
ComplaintCreated, ComplaintCommentAdded, and ComplaintAcknowledged are standard IS
notification templates — edit them in Console under Email Templates, per tenant.
Placeholders: {{reference-id}}, {{message-excerpt}}, {{data-principal-name}},
{{actor-name}}, {{category-label}}, {{priority-label}}, {{status-label}},
{{sla-label}}, {{action-url}}, {{recipient-role-label}}, {{headline-html}},
{{footer-text}}, {{action-badge-html}}, {{logo-url}}.
A template is written once, on first provisioning, and never rewritten — a Console edit is
permanent. The bundled default comes from
<IS_HOME>/repository/conf/email/email-dpdp-config.xml (edit it for new tenants, no rebuild
needed), but only affects tenants provisioned after the edit. The file is read once and cached
for the server's lifetime — restart the server after editing it, or new tenants keep
getting the old default until you do.
5. Submit and track a grievance in the portal
Portal: Sign in as a user with dpdp-consent-user, open My Complaints,
and select Submit New Complaint.
- Choose a category and describe the issue without unnecessary personal data.
- Optionally add one or more supported files within the configured limits.
- Submit the complaint and retain its generated reference ID.
- Open the case to see its status, statutory due date, public activity, and public attachments.
- Use the reply composer to send a public follow-up. If the case is waiting
for information, the portal sends the transition to
AWAITING_INTERNAL_REVIEWwith the reply.
The self-service create request is:
curl -X POST \
"${BASE_URL}/api/dpdp/complaints/v1/me/complaints" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"subjectCategory": "DATA_ACCESS_DENIED",
"description": "I cannot obtain the information associated with my consent."
}'
The server derives userId from the token and returns 201 Created with the
complaint ID, reference ID, category, priority, status, description,
timestamps, and statutory due date. Upload evidence afterward with multipart
form data; self-service uploads are always public:
curl -X POST \
"${BASE_URL}/api/dpdp/complaints/v1/me/complaints/<complaint-id>/attachments" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-F "file=@incident-screenshot.png;type=image/png" \
-F "file=@supporting-report.pdf;type=application/pdf"
Use GET /me/complaints/<complaint-id>/timeline to retrieve the public
activity and the attachments associated with each timeline entry. Internal
officer notes are never returned on this surface.
6. Handle a grievance in Complaint Management
Portal: Sign in as a DPO or administrator and open Complaint Management.
- Find the case by reference ID, Data Principal, status, or priority.
- Open it to inspect the description, attachments, and complete activity timeline.
- Send a public reply when the Data Principal should see the message.
- Add an Internal Note for officer-only information.
- Use the status menu to choose a permitted next state.
- Resolve the case after the review is complete, then confirm that the public view contains no internal note.
The officer endpoint can add a public reply and transition the case in one request:
curl -X POST \
"${BASE_URL}/api/dpdp/complaints/v1/complaints/<complaint-id>/comments" \
-H "Authorization: Bearer ${OFFICER_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"message": "We are reviewing your request.",
"isPublic": true,
"toStatus": "IN_PROGRESS"
}'
Set isPublic to false for an internal note. Management attachments may be
marked public or internal with the multipart isPublic field. Only public
entries and attachments are visible to the Data Principal.
7. Follow the permitted status lifecycle
The service validates every requested transition:
| Current status | Permitted next status |
|---|---|
OPEN | IN_PROGRESS, WAITING_ON_CLIENT |
IN_PROGRESS | WAITING_ON_CLIENT, RESOLVED |
WAITING_ON_CLIENT | AWAITING_INTERNAL_REVIEW |
AWAITING_INTERNAL_REVIEW | IN_PROGRESS, WAITING_ON_CLIENT, RESOLVED |
RESOLVED | AWAITING_INTERNAL_REVIEW through a valid self-service API transition |
The portal hides resolved cases from the officer queue by default, but a Data Principal can still post a public reply to a resolved case. The current portal reply action does not automatically reopen it; use the self-service status API explicitly when a reopening workflow is required.
For example, a Data Principal can request the valid reopening transition with:
curl -X POST \
"${BASE_URL}/api/dpdp/complaints/v1/me/complaints/<complaint-id>/status" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"toStatus":"AWAITING_INTERNAL_REVIEW"}'
An attempt to skip a required transition returns the complaint error response
with HTTP 409.
8. Protect tenant and personal data
- Use a token issued for the same tenant as the URL.
- Use
meendpoints for user-driven actions so identity is resolved server-side. - Keep internal notes and internal attachments off the public surface.
- Store the reference ID, not unnecessary personal data, in support workflows.
- Treat uploaded files as personal data and protect them in transit and at rest.
The management API returns the full timeline for authorized officers; the self-service timeline filters out internal entries. A caller who does not own a complaint receives no confirmation that another user's complaint ID exists on the self-service surface.
9. Troubleshoot common problems
| Symptom | Check |
|---|---|
403 Forbidden | Check the operation's exact scope: complaints:read:self or complaints:write:self for self-service, and complaints:read:any or complaints:write:any for tenant-wide management. Sign in again after role assignment. |
404 Not Found on /me | The complaint belongs to another user, or the ID is incorrect. |
| Attachment rejected | Confirm the MIME type, file size, and number of files against the configured limits. |
409 on a status change | The requested target is not permitted from the current status. |
| Internal note visible to a Data Principal | Verify that the note was posted through /complaints/* with isPublic: false, and that the reader is using the /me/* timeline. |
For a complete end-to-end walkthrough, see Try Out. For server-side deadline and upload settings, see Configuration Guide.