User Management APIs
This guide covers the APIs for creating, retrieving, updating, and linking consent users in Redacto CMP.
Overview
Consent users represent data principals (individuals whose data you process) in your system. The User Management APIs allow you to:
- Create users with explicit identifiers
- Retrieve user information
- Update user details
- Link multiple user records to a single identity
Base URL
All user management endpoints use the following base path:
/consent/organisations/{organisation_uuid}/workspaces/{workspace_uuid}/consent-ledger/consent-users/
Authentication: All endpoints require either JWT Auth or CMS API Key authentication.
Create User
Create a new consent user with an explicit identifier.
Endpoint:
POST /consent-ledger/consent-users/
Request Body:
{
"org_user_id": "user123",
"primary_email": "[email protected]",
"primary_mobile": "+1234567890",
"name": "John Doe",
"metadata": {
"account_type": "premium",
"signup_source": "web"
}
}| Field | Type | Required | Description |
|---|---|---|---|
org_user_id | string | Yes | Your unique identifier for the user |
primary_email | string | No | User's email address |
primary_mobile | string | No | User's phone number |
name | string | No | User's full name |
metadata | object | No | Custom key-value pairs |
Response (201 Created):
{
"detail": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"organisation_uuid": "org-uuid-here",
"workspace_uuid": "ws-uuid-here",
"org_user_id": "user123",
"org_user_id_type": "UCID",
"primary_email": "[email protected]",
"primary_mobile": "+1234567890",
"name": "John Doe",
"metadata": {
"account_type": "premium",
"signup_source": "web"
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}Response (409 Conflict):
If a user with the same identifier already exists:
{
"detail": {
"conflict_type": "ORG_USER_ID_EXISTS",
"message": "User with org_user_id 'user123' already exists",
"existing_user": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"org_user_id": "user123",
// ... full user object
}
}
}Conflict Types:
| Type | Description |
|---|---|
ORG_USER_ID_EXISTS | A user with this org_user_id already exists |
EMAIL_EXISTS_SAME_USER | Email exists with same org_user_id type (likely same person) |
EMAIL_EXISTS_DIFFERENT_USER | Email exists with different org_user_id type |
PHONE_EXISTS_SAME_USER | Phone exists with same org_user_id type |
PHONE_EXISTS_DIFFERENT_USER | Phone exists with different org_user_id type |
Get User
Retrieve a user by their UUID or org_user_id.
By UUID
Endpoint:
GET /consent-ledger/consent-users/{user_uuid}
Response (200 OK):
{
"detail": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"organisation_uuid": "org-uuid-here",
"workspace_uuid": "ws-uuid-here",
"org_user_id": "user123",
"org_user_id_type": "UCID",
"primary_email": "[email protected]",
"primary_mobile": "+1234567890",
"name": "John Doe",
"metadata": { "account_type": "premium" },
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}Response (404 Not Found):
{
"message": "User not found"
}By org_user_id
Endpoint:
GET /consent-ledger/consent-users/by-org-user-id/{org_user_id}
Response: Same as Get by UUID.
Note: This endpoint only works with the current org_user_id. Old org_user_ids (from before an update) are preserved as aliases but cannot be directly queried.
Update User
Update an existing user's information.
Endpoint:
PATCH /consent-ledger/consent-users/{user_uuid}
Request Body:
Only include fields you want to update:
{
"primary_email": "[email protected]",
"name": "John Updated",
"metadata": {
"account_type": "enterprise"
}
}| Field | Type | Description |
|---|---|---|
org_user_id | string | Update the user's identifier |
primary_email | string | Update email address |
primary_mobile | string | Update phone number |
name | string | Update display name |
metadata | object | Merged with existing metadata |
Response (200 OK):
Returns the updated user object.
Response (409 Conflict):
{
"message": "org_user_id 'xyz' already exists"
}Key Behaviors:
- Only provided fields are updated (partial update)
- Metadata is merged, not replaced
- Old identifiers are preserved as aliases
Link Users
Link multiple consent users to a primary user for identity resolution. This is useful when the same person has multiple records from different channels or systems.
Endpoint:
POST /consent-ledger/consent-users/link-users
Request Body:
{
"primary_org_user_id": "user_primary_123",
"alias_org_user_ids": ["user_alias_1", "user_alias_2", "anon_session_abc"]
}| Field | Type | Required | Description |
|---|---|---|---|
primary_org_user_id | string | Yes | The org_user_id of the primary user |
alias_org_user_ids | array | Yes | List of org_user_ids to link as aliases |
Response (200 OK):
{
"detail": {
"primary_user_uuid": "550e8400-e29b-41d4-a716-446655440000",
"linked": ["user_alias_1", "anon_session_abc"],
"already_linked": [],
"not_found": [],
"conflicts": [
{
"org_user_id": "user_alias_2",
"existing_primary_org_user_id": "user_other_primary"
}
]
}
}Response Categories:
| Field | Description |
|---|---|
linked | Successfully linked org_user_ids |
already_linked | Already aliased to this primary user |
not_found | org_user_ids that don't exist as users |
conflicts | Already aliased to a different primary user |
Response (404 Not Found):
{
"message": "Primary user with org_user_id 'xyz' not found"
}Response (422 Unprocessable Entity):
{
"message": "Cannot use 'xyz' as primary user - it is already an alias of 'abc'"
}Key Behaviors:
- The primary user cannot itself be an alias
- All aliases from alias users are transferred to the primary
- The operation is idempotent (safe to call multiple times)
- Linking is transactional per user
User Lifecycle
org_user_id Types
When users are created, they're assigned an org_user_id_type that indicates how they were identified:
| Type | Description |
|---|---|
UCID | User Created ID - explicitly provided org_user_id |
EMAIL | Derived from email when org_user_id not provided |
PHONE | Derived from phone when org_user_id not provided |
When you create a user with an explicit org_user_id, the type is set to UCID.
Alias Management
The system automatically manages aliases for identity resolution:
Automatic Alias Creation:
org_user_idis always added as an alias- Email addresses are added as aliases (if provided)
- Phone numbers are added as aliases (if provided)
Alias Preservation:
- When
org_user_idis updated, the old value is preserved as an alias - When email/phone is updated, old values are preserved as aliases
- All historical identifiers can be used for internal lookups
Common Use Cases
1. Create User During Registration
// After user completes registration
const response = await fetch(
`${API_URL}/consent-ledger/consent-users/`,
{
method: "POST",
headers: {
"X-CMS-API-Key": CMS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
org_user_id: newUser.id,
primary_email: newUser.email,
name: newUser.name,
metadata: { signup_date: new Date().toISOString() },
}),
}
);2. Link Anonymous Session to Registered User
// After user registers/logs in
const response = await fetch(
`${API_URL}/consent-ledger/consent-users/link-users`,
{
method: "POST",
headers: {
"X-CMS-API-Key": CMS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
primary_org_user_id: user.id,
alias_org_user_ids: [sessionAnonymousId],
}),
}
);3. Merge Multi-Channel Users
// User consented via web (email) and mobile app (phone)
const response = await fetch(
`${API_URL}/consent-ledger/consent-users/link-users`,
{
method: "POST",
headers: {
"X-CMS-API-Key": CMS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
primary_org_user_id: "customer_123",
alias_org_user_ids: [
"[email protected]",
"phone_+1234567890"
],
}),
}
);Error Handling
| Status | Description |
|---|---|
| 200 | Success |
| 201 | User created |
| 400 | Bad request (malformed data) |
| 401 | Authentication required |
| 404 | User not found |
| 409 | Conflict (duplicate user) |
| 422 | Validation error |
| 500 | Internal server error |
Updated 9 days ago