Grievances
Grievance tickets represent formal privacy rights requests submitted by data principals — for example, requests for data access, correction, or deletion. Each ticket is assigned a unique human-readable identifier in the format GRV-XXXXXXXX and progresses through a status lifecycle that you manage via the update endpoint.
All three endpoints authenticate with X-API-Key.
List grievances for a user
/grievance/user/{user_id}Retrieve all grievance tickets filed by a specific user, ordered by creation date descending.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | The client_user_id of the user whose tickets you want to retrieve |
Headers
| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your tenant API key |
Response
200 OK — an array of GrievanceTicket objects ordered by created_at descending. Returns an empty array if the user has no tickets.
| Field | Type | Description |
|---|---|---|
id | string | Internal UUID of the ticket record |
ticket_id | string | Human-readable ticket identifier (for example, "GRV-ABC12345") |
client_user_id | string | Your application’s identifier for the user who filed the ticket |
user_id | string or null | Internal user identifier, if mapped |
subject | string | Brief summary of the rights request |
description | string | Full description of the request |
category | string | Category (for example, "data_access" or "erasure") |
status | string | Current ticket status (for example, "open", "in_progress", or "resolved") |
attachment_url | string or null | URL of any file attached to the ticket |
created_at | string | ISO 8601 timestamp when the ticket was created |
updated_at | string | ISO 8601 timestamp of the most recent update |
curl --request GET \ --url https://api.truConsent.io/grievance/user/usr_abc123 \ --header "X-API-Key: YOUR_API_KEY"const response = await fetch('https://api.truConsent.io/grievance/user/usr_abc123', { headers: { 'X-API-Key': 'YOUR_API_KEY', },});const data = await response.json();import requests
response = requests.get( 'https://api.truConsent.io/grievance/user/usr_abc123', headers={ 'X-API-Key': 'YOUR_API_KEY', },)data = response.json()[ { "id": "c3d4e5f6-a7b8-9012-cdef-234567890123", "ticket_id": "GRV-A1B2C3D4", "client_user_id": "usr_abc123", "user_id": null, "subject": "Request to delete my account data", "description": "I would like all personal data associated with my account to be permanently deleted.", "category": "erasure", "status": "open", "attachment_url": null, "created_at": "2024-10-15T09:30:00", "updated_at": "2024-10-15T09:30:00" }]Create a grievance ticket
/grievanceSubmit a new privacy rights request on behalf of a data principal. The API automatically generates a unique ticket_id and sets the initial status to "open".
Headers
| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your tenant API key |
Body
| Field | Type | Required | Description |
|---|---|---|---|
client_user_id | string | Yes | Your application’s identifier for the user filing the request |
subject | string | Yes | Brief summary of the rights request |
description | string | Yes | Full description of the request |
category | string | Yes | Category (for example, "data_access", "rectification", or "erasure") |
attachment_url | string | No | Optional URL pointing to a supporting document |
Response
201 Created — the newly created GrievanceTicket. The ticket_id is auto-generated. status is always "open" on creation.
curl --request POST \ --url https://api.truConsent.io/grievance \ --header "X-API-Key: YOUR_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "client_user_id": "usr_abc123", "subject": "Request to delete my account data", "description": "I would like all personal data associated with my account to be permanently deleted.", "category": "erasure" }'const response = await fetch('https://api.truConsent.io/grievance', { method: 'POST', headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ client_user_id: 'usr_abc123', subject: 'Request to delete my account data', description: 'I would like all personal data associated with my account to be permanently deleted.', category: 'erasure', }),});const data = await response.json();import requests
response = requests.post( 'https://api.truConsent.io/grievance', headers={ 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json', }, json={ 'client_user_id': 'usr_abc123', 'subject': 'Request to delete my account data', 'description': 'I would like all personal data associated with my account to be permanently deleted.', 'category': 'erasure', },)data = response.json(){ "id": "c3d4e5f6-a7b8-9012-cdef-234567890123", "ticket_id": "GRV-A1B2C3D4", "client_user_id": "usr_abc123", "user_id": null, "subject": "Request to delete my account data", "description": "I would like all personal data associated with my account to be permanently deleted.", "category": "erasure", "status": "open", "attachment_url": null, "created_at": "2024-10-15T09:30:00", "updated_at": "2024-10-15T09:30:00"}Update a grievance ticket
/grievance/{ticket_id}Update the status or attachment_url of an existing ticket. At least one field must be provided. The ticket is identified by its human-readable ticket_id.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
ticket_id | string | Yes | The human-readable ticket identifier (for example, "GRV-A1B2C3D4"), not the internal UUID |
Headers
| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your tenant API key |
Body
At least one of the following fields is required. Omitted fields are not modified.
| Field | Type | Description |
|---|---|---|
status | string | New status (for example, "in_progress" or "resolved") |
attachment_url | string | Updated URL for the supporting document |
Response
200 OK — the full updated GrievanceTicket object.
curl --request PUT \ --url https://api.truConsent.io/grievance/GRV-A1B2C3D4 \ --header "X-API-Key: YOUR_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "status": "in_progress" }'const response = await fetch('https://api.truConsent.io/grievance/GRV-A1B2C3D4', { method: 'PUT', headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ status: 'in_progress' }),});const data = await response.json();import requests
response = requests.put( 'https://api.truConsent.io/grievance/GRV-A1B2C3D4', headers={ 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json', }, json={'status': 'in_progress'},)data = response.json(){ "id": "c3d4e5f6-a7b8-9012-cdef-234567890123", "ticket_id": "GRV-A1B2C3D4", "client_user_id": "usr_abc123", "user_id": null, "subject": "Request to delete my account data", "description": "I would like all personal data associated with my account to be permanently deleted.", "category": "erasure", "status": "in_progress", "attachment_url": null, "created_at": "2024-10-15T09:30:00", "updated_at": "2024-10-15T10:05:00"}Errors
| Status | Classification | Details |
|---|---|---|
400 | Validation Error | Request body failed validation, or no updatable fields were provided |
401 | Unauthenticated | Invalid or missing API key |
403 | Forbidden | API key lacks required scope |
404 | Not Found | No ticket with the given ticket_id exists (PUT only) |
500 | Internal Error | Internal server error |