> ## 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.

# Get Consent Audit Trail

> Retrieve paginated audit log of all consent changes for a user

## Overview

Retrieves the complete audit trail of all consent changes for a user. Essential for compliance reporting, regulatory audits, and investigating consent history.

<Note>
  The audit trail is **immutable** - all consent changes are permanently recorded with complete before/after snapshots for regulatory compliance.
</Note>

## Endpoint

```
GET https://api.baanx.com/v2/consent/user/{userId}/audit
```

## Headers

| Header         | Required | Description                         |
| -------------- | -------- | ----------------------------------- |
| `x-client-key` | ✅        | Your public API key                 |
| `x-us-env`     | ❌        | Set to `true` for US region routing |

## Path Parameters

| Parameter | Type   | Required | Description                                 |
| --------- | ------ | -------- | ------------------------------------------- |
| `userId`  | string | ✅        | User identifier to retrieve audit trail for |

## Query Parameters

| Parameter | Type    | Required | Description                          | Default |
| --------- | ------- | -------- | ------------------------------------ | ------- |
| `limit`   | integer | ❌        | Number of records per page (max 100) | 50      |
| `offset`  | integer | ❌        | Starting position for pagination     | 0       |

## Response

```json theme={null}
{
  "userId": "user_123abc456def",
  "auditRecords": [
    {
      "auditId": "audit_001",
      "action": "created",
      "timestamp": "2024-01-15T10:30:00Z",
      "consentSetId": "550e8400-e29b-41d4-a716-446655440001",
      "changes": {
        "before": null,
        "after": {
          "consentType": "termsAndPrivacy",
          "consentStatus": "granted"
        }
      },
      "metadata": {
        "ipAddress": "192.168.1.1",
        "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)",
        "timestamp": "2024-01-15T10:30:00Z",
        "clientId": "mobile-app-ios-v2.1.0"
      }
    },
    {
      "auditId": "audit_002",
      "action": "created",
      "timestamp": "2024-01-15T10:30:00Z",
      "consentSetId": "550e8400-e29b-41d4-a716-446655440001",
      "changes": {
        "before": null,
        "after": {
          "consentType": "marketingNotifications",
          "consentStatus": "granted"
        }
      },
      "metadata": {
        "ipAddress": "192.168.1.1",
        "userAgent": "Mozilla/5.0...",
        "timestamp": "2024-01-15T10:30:00Z"
      }
    },
    {
      "auditId": "audit_003",
      "action": "revoked",
      "timestamp": "2024-01-20T14:22:00Z",
      "consentSetId": "550e8400-e29b-41d4-a716-446655440001",
      "changes": {
        "before": {
          "consentType": "marketingNotifications",
          "consentStatus": "granted"
        },
        "after": {
          "consentType": "marketingNotifications",
          "consentStatus": "revoked"
        }
      },
      "metadata": {
        "ipAddress": "192.168.1.10",
        "userAgent": "Mozilla/5.0...",
        "timestamp": "2024-01-20T14:22:00Z"
      }
    }
  ],
  "pagination": {
    "total": 3,
    "limit": 50,
    "offset": 0
  },
  "_links": {
    "self": {
      "href": "https://api.baanx.com/v2/consent/user/user_123abc456def/audit?limit=50&offset=0",
      "method": "GET"
    },
    "next": null,
    "prev": null
  }
}
```

## Audit Record Structure

| Field            | Type              | Description                                  |
| ---------------- | ----------------- | -------------------------------------------- |
| `auditId`        | string            | Unique identifier for this audit record      |
| `action`         | string            | Action type: `created`, `updated`, `revoked` |
| `timestamp`      | string (ISO 8601) | When the change occurred                     |
| `consentSetId`   | string (UUID)     | Consent set containing this change           |
| `changes.before` | object\|null      | State before change (null for creation)      |
| `changes.after`  | object            | State after change                           |
| `metadata`       | object            | Additional context (IP, user agent, etc.)    |

## Action Types

| Action    | Description              | Before State     | After State      |
| --------- | ------------------------ | ---------------- | ---------------- |
| `created` | Initial consent creation | `null`           | Consent record   |
| `updated` | Consent status changed   | Original status  | New status       |
| `revoked` | Consent was revoked      | `granted` status | `revoked` status |

## Pagination

Use `limit` and `offset` to paginate through large audit trails:

```typescript theme={null}
async function getAllAuditRecords(userId: string) {
  let allRecords = [];
  let offset = 0;
  const limit = 100;

  while (true) {
    const response = await fetch(
      `https://api.baanx.com/v2/consent/user/${userId}/audit?limit=${limit}&offset=${offset}`,
      {
        headers: {
          'x-client-key': process.env.BAANX_CLIENT_KEY!
        }
      }
    );

    const { auditRecords, pagination } = await response.json();
    allRecords.push(...auditRecords);

    if (offset + limit >= pagination.total) break;
    offset += limit;
  }

  return allRecords;
}
```

## Code Examples

### TypeScript - Basic Audit Retrieval

```typescript theme={null}
async function getConsentAudit(
  userId: string,
  limit: number = 50,
  offset: number = 0
) {
  const response = await fetch(
    `https://api.baanx.com/v2/consent/user/${userId}/audit?limit=${limit}&offset=${offset}`,
    {
      headers: {
        'x-client-key': process.env.BAANX_CLIENT_KEY!
      }
    }
  );

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

  return response.json();
}

const audit = await getConsentAudit('user_123abc456def');
console.log(`Total audit records: ${audit.pagination.total}`);
```

### TypeScript - Export for Compliance

```typescript theme={null}
async function exportConsentAudit(userId: string) {
  const allRecords = await getAllAuditRecords(userId);

  const report = {
    userId,
    exportDate: new Date().toISOString(),
    totalChanges: allRecords.length,
    records: allRecords.map(record => ({
      date: record.timestamp,
      action: record.action,
      consentType: record.changes.after?.consentType,
      oldStatus: record.changes.before?.consentStatus,
      newStatus: record.changes.after?.consentStatus,
      ipAddress: record.metadata?.ipAddress
    }))
  };

  return report;
}

const complianceReport = await exportConsentAudit('user_123abc456def');
await saveToFile(`audit_${userId}.json`, JSON.stringify(complianceReport, null, 2));
```

### Python

```python theme={null}
import requests

def get_consent_audit(user_id, limit=50, offset=0):
    response = requests.get(
        f'https://api.baanx.com/v2/consent/user/{user_id}/audit',
        params={'limit': limit, 'offset': offset},
        headers={
            'x-client-key': os.getenv('BAANX_CLIENT_KEY')
        }
    )

    response.raise_for_status()
    return response.json()

audit = get_consent_audit('user_123abc456def')

print(f"Total audit records: {audit['pagination']['total']}")

for record in audit['auditRecords']:
    print(f"{record['timestamp']}: {record['action']} - {record['changes']['after'].get('consentType')}")
```

### cURL

```bash theme={null}
curl -X GET "https://api.baanx.com/v2/consent/user/user_123abc456def/audit?limit=50&offset=0" \
  -H "x-client-key: your_client_key"
```

## Use Cases

<AccordionGroup>
  <Accordion title="Regulatory Audits">
    Generate comprehensive audit reports for regulators:

    ```typescript theme={null}
    async function generateRegulatoryAudit(userId: string) {
      const { auditRecords } = await getConsentAudit(userId, 1000, 0);

      return {
        userIdentifier: userId,
        auditPeriod: {
          from: auditRecords[0]?.timestamp,
          to: auditRecords[auditRecords.length - 1]?.timestamp
        },
        totalChanges: auditRecords.length,
        consentGranted: auditRecords.filter(
          r => r.action === 'created' && r.changes.after.consentStatus === 'granted'
        ).length,
        consentRevoked: auditRecords.filter(r => r.action === 'revoked').length,
        detailedRecords: auditRecords
      };
    }
    ```
  </Accordion>

  <Accordion title="Data Subject Access Requests (DSAR)">
    Fulfill user requests for their consent history:

    ```typescript theme={null}
    async function handleDSAR(userId: string) {
      const { auditRecords } = await getConsentAudit(userId);

      return {
        requestDate: new Date().toISOString(),
        userId,
        consentHistory: auditRecords.map(record => ({
          date: record.timestamp,
          action: record.action,
          consentType: record.changes.after?.consentType,
          status: record.changes.after?.consentStatus,
          capturedFrom: {
            ipAddress: record.metadata?.ipAddress,
            device: record.metadata?.userAgent
          }
        }))
      };
    }
    ```
  </Accordion>

  <Accordion title="Consent Timeline Visualization">
    Display user's consent history in UI:

    ```typescript theme={null}
    async function getConsentTimeline(userId: string) {
      const { auditRecords } = await getConsentAudit(userId);

      return auditRecords.map(record => ({
        id: record.auditId,
        date: new Date(record.timestamp),
        action: record.action,
        description: formatAuditDescription(record),
        icon: getActionIcon(record.action)
      }));
    }

    function formatAuditDescription(record: AuditRecord): string {
      const { action, changes } = record;
      const type = changes.after?.consentType;

      if (action === 'created') {
        return `Granted consent for ${type}`;
      } else if (action === 'revoked') {
        return `Revoked consent for ${type}`;
      }
      return `Updated ${type}`;
    }
    ```
  </Accordion>

  <Accordion title="Legal Defense">
    Prove consent was properly obtained:

    ```typescript theme={null}
    async function proveLawfulConsent(userId: string, disputeDate: string) {
      const { auditRecords } = await getConsentAudit(userId);

      const relevantRecords = auditRecords.filter(
        record => new Date(record.timestamp) <= new Date(disputeDate)
      );

      return {
        disputeDate,
        consentWasGranted: relevantRecords.some(
          r => r.action === 'created' && r.changes.after.consentStatus === 'granted'
        ),
        consentWasRevoked: relevantRecords.some(r => r.action === 'revoked'),
        evidenceRecords: relevantRecords,
        captureDetails: relevantRecords.map(r => ({
          timestamp: r.timestamp,
          ipAddress: r.metadata?.ipAddress,
          userAgent: r.metadata?.userAgent
        }))
      };
    }
    ```
  </Accordion>
</AccordionGroup>

## Best Practices

<Warning>
  **Data Retention**: Audit trails should be retained according to regulatory requirements (typically 6-7 years). Never delete audit records even after user account closure.
</Warning>

<Info>
  **Performance**: For large audit trails, use pagination and process records in batches rather than loading all at once.
</Info>

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Get User Consent Status" icon="circle-check" href="/api-reference/consent/get-user-consent">
    Check current consent status
  </Card>

  <Card title="Revoke Consent" icon="ban" href="/api-reference/consent/revoke-consent">
    Create revocation audit records
  </Card>

  <Card title="Compliance Guide" icon="clipboard-check" href="/guides/consent/compliance">
    Regulatory compliance best practices
  </Card>

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