> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baanx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Link User to Consent Set

> Associate a userId with an existing consent set created during onboarding

## Overview

Links a permanent `userId` to an existing consent set that was created during onboarding. This endpoint completes the consent onboarding process by associating consent records with a user account.

<Note>
  Call this endpoint **after** user account creation is complete (e.g., after email verification, KYC completion, or registration finalization).
</Note>

## When to Use

<Steps>
  <Step title="After User Account Creation">
    Once you have a permanent `userId` from your system
  </Step>

  <Step title="After Email Verification">
    When user verifies their email and account is activated
  </Step>

  <Step title="After KYC Completion">
    When identity verification finalizes
  </Step>

  <Step title="Registration Complete">
    When the full registration workflow finishes
  </Step>
</Steps>

## Endpoint

```
PATCH https://api.baanx.com/v2/consent/onboarding/{consentSetId}
```

## Headers

| Header         | Required | Description                         |
| -------------- | -------- | ----------------------------------- |
| `x-client-key` | ✅        | Your public API key                 |
| `x-secret-key` | ✅        | Your secret API key                 |
| `Content-Type` | ✅        | Must be `application/json`          |
| `x-us-env`     | ❌        | Set to `true` for US region routing |

## Path Parameters

| Parameter      | Type          | Required | Description                                            |
| -------------- | ------------- | -------- | ------------------------------------------------------ |
| `consentSetId` | string (UUID) | ✅        | UUID of the consent set to link (from create response) |

## Request Body

| Parameter | Type   | Required | Description                                           |
| --------- | ------ | -------- | ----------------------------------------------------- |
| `userId`  | string | ✅        | Permanent user identifier to link to this consent set |

## Example Request

```json theme={null}
{
  "userId": "user_123abc456def"
}
```

## Response

### 200 OK

```json theme={null}
{
  "consentSetId": "550e8400-e29b-41d4-a716-446655440001",
  "userId": "user_123abc456def",
  "completedAt": "2024-01-15T10:35:00Z",
  "consentSet": {
    "consentSetId": "550e8400-e29b-41d4-a716-446655440001",
    "userId": "user_123abc456def",
    "onboardingId": "onboarding_abc123xyz",
    "tenantId": "tenant_baanx_prod",
    "policyType": "global",
    "completedAt": "2024-01-15T10:35:00Z",
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:35:00Z",
    "consents": [
      {
        "consentId": "consent_001",
        "consentType": "eSignAct",
        "consentStatus": "granted",
        "metadata": {
          "timestamp": "2024-01-15T10:30:00Z",
          "ipAddress": "192.168.1.1"
        },
        "createdAt": "2024-01-15T10:30:00Z",
        "updatedAt": "2024-01-15T10:30:00Z"
      },
      {
        "consentId": "consent_002",
        "consentType": "termsAndPrivacy",
        "consentStatus": "granted",
        "metadata": {
          "timestamp": "2024-01-15T10:30:00Z"
        },
        "createdAt": "2024-01-15T10:30:00Z",
        "updatedAt": "2024-01-15T10:30:00Z"
      }
    ]
  },
  "_links": {
    "self": {
      "href": "https://api.baanx.com/v2/consent/consentSet/550e8400-e29b-41d4-a716-446655440001",
      "method": "GET"
    },
    "audit": {
      "href": "https://api.baanx.com/v2/consent/user/user_123abc456def/audit",
      "method": "GET"
    }
  }
}
```

### 400 Bad Request

```json theme={null}
{
  "error": "Validation error",
  "details": [
    "userId is required and must not be empty"
  ]
}
```

### 404 Not Found

```json theme={null}
{
  "error": "Not found",
  "details": [
    "Consent set with ID '550e8400-e29b-41d4-a716-446655440001' not found"
  ]
}
```

### 409 Conflict

```json theme={null}
{
  "error": "Conflict",
  "details": [
    "This consent set is already linked to userId 'user_123abc456def'"
  ]
}
```

<Warning>
  A consent set can only be linked to **one user**. Attempting to link again will result in a 409 Conflict error.
</Warning>

## Code Examples

### TypeScript

```typescript theme={null}
async function linkUserToConsent(consentSetId: string, userId: string) {
  const response = await fetch(
    `https://api.baanx.com/v2/consent/onboarding/${consentSetId}`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'x-client-key': process.env.BAANX_CLIENT_KEY!,
        'x-secret-key': process.env.BAANX_SECRET_KEY!
      },
      body: JSON.stringify({ userId })
    }
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Linking failed: ${error.details.join(', ')}`);
  }

  return response.json();
}

const result = await linkUserToConsent(
  '550e8400-e29b-41d4-a716-446655440001',
  'user_123abc456def'
);

console.log(`User ${result.userId} linked to consent set ${result.consentSetId}`);
```

### Python

```python theme={null}
import requests

def link_user_to_consent(consent_set_id, user_id):
    response = requests.patch(
        f'https://api.baanx.com/v2/consent/onboarding/{consent_set_id}',
        headers={
            'Content-Type': 'application/json',
            'x-client-key': os.getenv('BAANX_CLIENT_KEY'),
            'x-secret-key': os.getenv('BAANX_SECRET_KEY')
        },
        json={'userId': user_id}
    )

    response.raise_for_status()
    return response.json()

result = link_user_to_consent(
    '550e8400-e29b-41d4-a716-446655440001',
    'user_123abc456def'
)

print(f"User {result['userId']} linked successfully")
```

### cURL

```bash theme={null}
curl -X PATCH https://api.baanx.com/v2/consent/onboarding/550e8400-e29b-41d4-a716-446655440001 \
  -H "Content-Type: application/json" \
  -H "x-client-key: your_client_key" \
  -H "x-secret-key: your_secret_key" \
  -d '{
    "userId": "user_123abc456def"
  }'
```

## Integration Workflow

```mermaid theme={null}
sequenceDiagram
    participant Client as Your Application
    participant API as Baanx API
    participant DB as Your Database

    Note over Client: 1. Create Consent Set
    Client->>API: POST /v2/consent/onboarding
    API-->>Client: consentSetId

    Note over Client,DB: 2. Store Temporarily
    Client->>DB: Store consentSetId + onboardingId

    Note over Client: 3. User Registration
    Client->>Client: Complete user registration
    Client->>DB: Create user account
    DB-->>Client: userId

    Note over Client,API: 4. Link User
    Client->>DB: Retrieve consentSetId
    Client->>API: PATCH /consent/onboarding/{consentSetId}
    API-->>Client: Linked consent set

    Note over Client: 5. Continue Onboarding
```

## Best Practices

<AccordionGroup>
  <Accordion title="Store ConsentSetId Temporarily">
    Store the `consentSetId` in your session or database until user registration completes:

    ```typescript theme={null}
    await sessionStore.set(`consent_${onboardingId}`, consentSetId);

    const storedConsentSetId = await sessionStore.get(`consent_${onboardingId}`);
    await linkUserToConsent(storedConsentSetId, userId);
    ```
  </Accordion>

  <Accordion title="Handle Idempotency">
    Check if linking has already occurred before attempting:

    ```typescript theme={null}
    async function linkUserIfNeeded(consentSetId: string, userId: string) {
      try {
        return await linkUserToConsent(consentSetId, userId);
      } catch (error) {
        if (error.status === 409) {
          const consentSet = await getConsentSetById(consentSetId);
          if (consentSet.userId === userId) {
            console.log('Already linked to this user');
            return consentSet;
          }
          throw new Error('Consent set linked to different user');
        }
        throw error;
      }
    }
    ```
  </Accordion>

  <Accordion title="Clean Up After Linking">
    Remove temporary data after successful linking:

    ```typescript theme={null}
    const result = await linkUserToConsent(consentSetId, userId);
    await sessionStore.delete(`consent_${onboardingId}`);
    ```
  </Accordion>
</AccordionGroup>

## Important Notes

<Warning>
  **One-Time Operation**: Each consent set can only be linked once. The linking action is recorded in the audit trail and cannot be undone.
</Warning>

<Info>
  **Audit Trail**: The linking action is automatically recorded in the user's consent audit trail with timestamp and metadata.
</Info>

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Create Onboarding Consent" icon="plus" href="/api-reference/consent/create-onboarding-consent">
    Create the initial consent set
  </Card>

  <Card title="Get User Consent Status" icon="circle-check" href="/api-reference/consent/get-user-consent">
    Check user's consent status after linking
  </Card>

  <Card title="Get Consent Set by ID" icon="magnifying-glass" href="/api-reference/consent/get-consent-set">
    Retrieve consent set details
  </Card>

  <Card title="Implementation Guide" icon="book" href="/guides/consent/implementation">
    Full integration guide
  </Card>
</CardGroup>
