Create a consent link
POST /api/consent/consent-links
Authentication
Section titled “Authentication”This endpoint accepts two authentication methods. Use whichever fits your integration:
| Method | Header | When to use |
|---|---|---|
| Bearer token | Authorization: Bearer <token> | Dashboard user session token — typically used from the dashboard or when calling on behalf of a logged-in user. |
| API key | X-API-Key: <key> | Server-to-server calls from your backend. Requires a key with the consent (or admin) scope. |
To generate an API key, go to Settings → API Settings in the truConsent dashboard. See Get API key and org ID for step-by-step instructions.
Bearer token
Section titled “Bearer token”curl -X POST "https://api.truconsent.io/api/consent/consent-links" \ -H "Authorization: Bearer YOUR_SESSION_TOKEN" \ -H "X-Org-Id: YOUR_ORG_ID" \ -H "Content-Type: application/json" \ -d '{ "collection_point_id": "550e8400-e29b-41d4-a716-446655440000", "asset_id": "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "phone": "+919876543210", "expiry_hours": 24 }'const response = await fetch("https://api.truconsent.io/api/consent/consent-links", { method: "POST", headers: { "Authorization": `Bearer ${sessionToken}`, "X-Org-Id": YOUR_ORG_ID, "Content-Type": "application/json", }, body: JSON.stringify({ collection_point_id: "550e8400-e29b-41d4-a716-446655440000", asset_id: "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", phone: "+919876543210", expiry_hours: 24, }),});
const data = await response.json();console.log(data.consent_link);interface ConsentLinkResponse { request_id: string; event_id: string; consent_link: string; expires_at: string; delivery_status: { email?: "sent" | "failed" };}
const response = await fetch("https://api.truconsent.io/api/consent/consent-links", { method: "POST", headers: { "Authorization": `Bearer ${sessionToken}`, "X-Org-Id": YOUR_ORG_ID, "Content-Type": "application/json", }, body: JSON.stringify({ collection_point_id: "550e8400-e29b-41d4-a716-446655440000", asset_id: "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", phone: "+919876543210", expiry_hours: 24, }),});
const data: ConsentLinkResponse = await response.json();console.log(data.consent_link);import httpx
resp = httpx.post( "https://api.truconsent.io/api/consent/consent-links", headers={ "Authorization": f"Bearer {session_token}", "X-Org-Id": YOUR_ORG_ID, "Content-Type": "application/json", }, json={ "collection_point_id": "550e8400-e29b-41d4-a716-446655440000", "asset_id": "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "phone": "+919876543210", "expiry_hours": 24, },)data = resp.json()print(data["consent_link"])$headers = @{ "Authorization" = "Bearer $SESSION_TOKEN" "X-Org-Id" = $YOUR_ORG_ID "Content-Type" = "application/json"}
$body = @{ collection_point_id = "550e8400-e29b-41d4-a716-446655440000" asset_id = "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx" phone = "+919876543210" expiry_hours = 24} | ConvertTo-Json
Invoke-RestMethod -Method Post ` -Uri "https://api.truconsent.io/api/consent/consent-links" ` -Headers $headers ` -Body $bodyAPI key
Section titled “API key”curl -X POST "https://api.truconsent.io/api/consent/consent-links" \ -H "X-API-Key: YOUR_API_KEY" \ -H "X-Org-Id: YOUR_ORG_ID" \ -H "Content-Type: application/json" \ -d '{ "collection_point_id": "550e8400-e29b-41d4-a716-446655440000", "asset_id": "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "phone": "+919876543210", "expiry_hours": 24 }'const response = await fetch("https://api.truconsent.io/api/consent/consent-links", { method: "POST", headers: { "X-API-Key": API_KEY, "X-Org-Id": YOUR_ORG_ID, "Content-Type": "application/json", }, body: JSON.stringify({ collection_point_id: "550e8400-e29b-41d4-a716-446655440000", asset_id: "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", phone: "+919876543210", expiry_hours: 24, }),});
const data = await response.json();console.log(data.consent_link);interface ConsentLinkResponse { request_id: string; event_id: string; consent_link: string; expires_at: string; delivery_status: { email?: "sent" | "failed" };}
const response = await fetch("https://api.truconsent.io/api/consent/consent-links", { method: "POST", headers: { "X-API-Key": API_KEY, "X-Org-Id": YOUR_ORG_ID, "Content-Type": "application/json", }, body: JSON.stringify({ collection_point_id: "550e8400-e29b-41d4-a716-446655440000", asset_id: "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", phone: "+919876543210", expiry_hours: 24, }),});
const data: ConsentLinkResponse = await response.json();console.log(data.consent_link);import httpx
resp = httpx.post( "https://api.truconsent.io/api/consent/consent-links", headers={ "X-API-Key": API_KEY, "X-Org-Id": YOUR_ORG_ID, "Content-Type": "application/json", }, json={ "collection_point_id": "550e8400-e29b-41d4-a716-446655440000", "asset_id": "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "phone": "+919876543210", "expiry_hours": 24, },)data = resp.json()print(data["consent_link"])$headers = @{ "X-API-Key" = $API_KEY "X-Org-Id" = $YOUR_ORG_ID "Content-Type" = "application/json"}
$body = @{ collection_point_id = "550e8400-e29b-41d4-a716-446655440000" asset_id = "79bf87f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx" phone = "+919876543210" expiry_hours = 24} | ConvertTo-Json
Invoke-RestMethod -Method Post ` -Uri "https://api.truconsent.io/api/consent/consent-links" ` -Headers $headers ` -Body $bodyRequest body
Section titled “Request body”| Field | Type | Description |
|---|---|---|
collection_point_id * | UUID or string | UUID of the collection point, or its display_id (e.g. CP010). |
asset_id * | UUID | Asset the collection point belongs to. Must match the collection point’s asset. |
phone * | string | Data principal’s phone number. Use E.164 format (+919876543210) or a 10-digit number (automatically prefixed with +91). |
email | string | If provided, a branded consent email is also sent to this address. |
expiry_hours | integer | How long the link stays valid. Defaults to 24. Maximum 24. |
data_collection_timestamp | ISO 8601 datetime | When the underlying data was originally collected. Defaults to the current time. |
Responses
Section titled “Responses”Link created successfully. The consent_link is ready to send to the data principal.
{ "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "event_id": "e5f6a7b8-c9d0-1234-efab-567890abcdef", "consent_link": "{COLLECTOR_BASE_URL}/your-subdomain/CP010/e5f6a7b8-c9d0-1234-efab-567890abcdef", "expires_at": "2025-05-13T10:00:00+00:00", "delivery_status": {}}When email is provided, delivery_status contains the send result:
{ "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "event_id": "e5f6a7b8-c9d0-1234-efab-567890abcdef", "consent_link": "{COLLECTOR_BASE_URL}/your-subdomain/CP010/e5f6a7b8-c9d0-1234-efab-567890abcdef", "expires_at": "2025-05-13T10:00:00+00:00", "delivery_status": { "email": "sent" }}| Field | Description |
|---|---|
consent_link | The URL to share with the data principal. Format: {base}/{org-subdomain}/{cp-display-id}/{event-id}. |
event_id | Unique ID for this consent event. Use it to query the audit log. |
request_id | Unique ID for this link request. |
expires_at | ISO 8601 UTC timestamp after which the link is no longer valid. |
delivery_status | Empty {} when no email was given. {"email": "sent"} or {"email": "failed"} when email was provided. |
Returned when required fields are missing, the tenant context cannot be resolved, or the asset and collection point do not match.
Missing phone or collection_point_id:
{ "detail": "Phone and Collection Point ID are required" }X-Org-Id missing or unresolvable:
{ "detail": "Tenant context not found" }Asset / Collection Point mismatch:
{ "detail": "Asset / Collection Point mismatch: the selected collection point does not belong to the specified asset. Please provide a valid Collection Point ID for the selected asset."}Returned when no valid credential is provided.
Missing or malformed Authorization header (Bearer token path):
{ "detail": "Authorization token required" }Expired or invalid Bearer token:
{ "detail": "Invalid or expired auth token" }Invalid or inactive API key (X-API-Key path):
{ "detail": "Invalid or inactive API key" }Returned when the credential is valid but does not have access.
Bearer token — user is not a member of the organization:
{ "detail": "User is not a member of this organization in PropelAuth" }API key — key does not have the consent scope:
{ "detail": "API key does not have the 'consent' scope" }Returned when the collection_point_id does not match any collection point in your organization.
{ "detail": "Collection point not found" }