Integration Examples¶
Working code examples showing Dxtra API integration patterns for common use cases.
GraphQL-First API
Dxtra uses a GraphQL API for managing privacy data. All examples use standard GraphQL clients - no proprietary SDK required.
Authentication Setup¶
All API calls require JWT authentication. First, exchange your Personal Access Token for a JWT:
import { GraphQLClient } from 'graphql-request';
// Exchange PAT for JWT token
async function getAuthenticatedClient(personalAccessToken) {
const response = await fetch('https://auth.dxtra.ai/v1/signin/pat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ personalAccessToken })
});
if (!response.ok) {
throw new Error(`Authentication failed: ${response.statusText}`);
}
const { session } = await response.json();
return new GraphQLClient('https://api.dxtra.ai/v1/graphql', {
headers: {
'Authorization': `Bearer ${session.accessToken}`,
'X-Hasura-Role': 'user'
}
});
}
import requests
from gql import Client
from gql.transport.requests import RequestsHTTPTransport
def get_authenticated_client(personal_access_token):
"""Exchange PAT for JWT and create GraphQL client."""
response = requests.post(
'https://auth.dxtra.ai/v1/signin/pat',
json={'personalAccessToken': personal_access_token}
)
response.raise_for_status()
session = response.json()['session']
transport = RequestsHTTPTransport(
url='https://api.dxtra.ai/v1/graphql',
headers={
'Authorization': f'Bearer {session["accessToken"]}',
'X-Hasura-Role': 'user'
}
)
return Client(transport=transport, fetch_schema_from_transport=True)
# Step 1: Get JWT token
JWT=$(curl -s -X POST https://auth.dxtra.ai/v1/signin/pat \
-H "Content-Type: application/json" \
-d '{"personalAccessToken": "YOUR_PAT"}' \
| jq -r '.session.accessToken')
# Step 2: Use JWT for API calls
curl -X POST https://api.dxtra.ai/v1/graphql \
-H "Authorization: Bearer $JWT" \
-H "X-Hasura-Role: user" \
-H "Content-Type: application/json" \
-d '{"query": "{ dataControllers { id title } }"}'
Data Controller Operations¶
List Data Controllers¶
Retrieve all data controllers accessible to the authenticated user.
Get Data Controller Details¶
Fetch detailed information for a specific data controller.
const query = `
query GetDataControllerDetails($id: uuid!) {
dataController(id: $id) {
id
title
did
description
industry
createdAt
updatedAt
users {
userId
role
}
}
}
`;
const data = await client.request(query, {
id: 'your-controller-uuid'
});
Data Subject Operations¶
Query Data Subjects¶
Retrieve data subjects for a data controller.
const query = `
query GetDataSubjects($controllerId: uuid!, $limit: Int = 50) {
dataSubjects(
where: { dataControllerId: { _eq: $controllerId } }
limit: $limit
orderBy: { createdAt: desc }
) {
id
did
createdAt
updatedAt
doNotTrack
globalPrivacyControl
}
}
`;
const data = await client.request(query, {
controllerId: 'your-controller-uuid',
limit: 100
});
Get Data Subject with Consent Values¶
Query a data subject along with their consent form values.
const query = `
query GetDataSubjectWithConsents($dataSubjectId: uuid!) {
dataSubject(id: $dataSubjectId) {
id
did
createdAt
doNotTrack
globalPrivacyControl
}
dataSubjectConsentFormValues(
where: { dataSubjectId: { _eq: $dataSubjectId } }
) {
id
value
createdAt
updatedAt
dataControllerProcessingPurposeId
}
}
`;
const data = await client.request(query, {
dataSubjectId: 'data-subject-uuid'
});
Rights Request Operations¶
Submit a Rights Request¶
Create a data subject rights request (DSAR).
const mutation = `
mutation SubmitRightsRequest($input: data_subject_rights_requests_insert_input!) {
insertDataSubjectRightsRequest(object: $input) {
id
requestType
status
createdAt
}
}
`;
const data = await client.request(mutation, {
input: {
dataSubjectId: 'data-subject-uuid',
requestType: 'access', // access, erasure, rectification, portability
status: 'submitted'
}
});
List Rights Requests¶
Query rights requests for a data subject.
const query = `
query GetRightsRequests($dataSubjectId: uuid!) {
dataSubjectRightsRequests(
where: { dataSubjectId: { _eq: $dataSubjectId } }
orderBy: { createdAt: desc }
) {
id
requestType
status
verified
createdAt
updatedAt
}
}
`;
const data = await client.request(query, {
dataSubjectId: 'data-subject-uuid'
});
Consent Management¶
Upsert Consent Values¶
Update or insert consent values for a data subject using the upsertDataSubjectConsents action.
const mutation = `
mutation UpsertConsents($input: UpsertDataSubjectConsentsInput!) {
upsertDataSubjectConsents(
dataControllerId: $input.dataControllerId
purposes: $input.purposes
dataSubjectId: $input.dataSubjectId
) {
status
message
data {
dataSubjectId
upsertedCount
consentCookie
}
}
}
`;
const data = await client.request(mutation, {
input: {
dataControllerId: 'controller-uuid',
dataSubjectId: 'data-subject-uuid',
purposes: {
'purpose-uuid-1': true,
'purpose-uuid-2': false
}
}
});
Webhook Integration¶
Configure Incoming Webhooks¶
Third-party services can send events to Dxtra via webhooks.
Webhook URL Pattern:
https://conduit.dxtra.ai/api/v1/integrations/{service}/event?did={YOUR_DID}&dxKey={YOUR_DX_KEY}
Supported Services:
| Service | Webhook Events |
|---|---|
| Shopify | Customer created/updated, orders, GDPR requests |
| Stripe | Customer created/updated/deleted |
| Mailchimp | Subscriber events, consent updates |
| WooCommerce | Customer and order events |
Handle Outgoing Event Notifications¶
Implement a webhook handler to receive Dxtra event notifications.
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhooks/dxtra', (req, res) => {
const { event, data } = req.body;
switch (event) {
case 'consent.granted':
// Handle consent granted
console.log('Consent granted:', data.dataSubjectId, data.purposes);
break;
case 'consent.revoked':
// Handle consent revoked
console.log('Consent revoked:', data.dataSubjectId, data.purposes);
break;
case 'rights_request.created':
// Handle new rights request
console.log('Rights request:', data.requestId, data.requestType);
break;
case 'data_subject.created':
// Handle new data subject
console.log('New data subject:', data.dataSubjectId);
break;
default:
console.log('Unknown event:', event);
}
res.status(200).json({ received: true });
});
app.listen(3000);
Privacy Widget Embedding¶
Embed Dxtra privacy widgets in your website.
Transparency Center Widget¶
<!-- Load the widget script -->
<script
src="https://transparencycenter.dxtra.ai/widgets/transparency-app.js"
type="module"
></script>
<!-- Embed the transparency center -->
<transparency-app
data-controller-id="your-controller-uuid"
></transparency-app>
Individual Components¶
<!-- Privacy overview -->
<dx-overview data-controller-id="your-controller-uuid"></dx-overview>
<!-- Consent management -->
<dx-consents data-controller-id="your-controller-uuid"></dx-consents>
<!-- Rights request form -->
<dx-rights-management data-controller-id="your-controller-uuid"></dx-rights-management>
<!-- Privacy notices -->
<dx-privacy data-controller-id="your-controller-uuid"></dx-privacy>
<!-- Data processor map -->
<dx-data-map data-controller-id="your-controller-uuid"></dx-data-map>
Error Handling¶
Implement proper error handling for API calls.
async function safeQuery(client, query, variables = {}) {
try {
return await client.request(query, variables);
} catch (error) {
// Handle GraphQL errors
if (error.response?.errors) {
const graphqlError = error.response.errors[0];
console.error('GraphQL error:', graphqlError.message);
// Check for specific error types
if (graphqlError.extensions?.code === 'access-denied') {
throw new Error('Permission denied. Check your role permissions.');
}
throw new Error(`Query failed: ${graphqlError.message}`);
}
// Handle HTTP errors
if (error.response?.status === 401) {
throw new Error('Authentication expired. Please re-authenticate.');
}
if (error.response?.status === 429) {
throw new Error('Rate limit exceeded. Please retry later.');
}
throw error;
}
}
Token Refresh Pattern¶
Implement automatic token refresh for long-running applications.
class DxtraClient {
constructor(personalAccessToken) {
this.pat = personalAccessToken;
this.client = null;
this.tokenExpiry = 0;
}
async getClient() {
const now = Date.now();
// Refresh token 5 minutes before expiration
if (!this.client || now >= this.tokenExpiry - 300000) {
await this.refreshToken();
}
return this.client;
}
async refreshToken() {
const response = await fetch('https://auth.dxtra.ai/v1/signin/pat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ personalAccessToken: this.pat })
});
if (!response.ok) {
throw new Error('Failed to refresh token');
}
const { session } = await response.json();
this.client = new GraphQLClient('https://api.dxtra.ai/v1/graphql', {
headers: {
'Authorization': `Bearer ${session.accessToken}`,
'X-Hasura-Role': 'user'
}
});
// Token expires in 1 hour (3600 seconds)
this.tokenExpiry = Date.now() + session.accessTokenExpiresIn * 1000;
}
async query(queryString, variables = {}) {
const client = await this.getClient();
return client.request(queryString, variables);
}
}
// Usage
const dxtra = new DxtraClient(process.env.DXTRA_PAT);
const data = await dxtra.query('{ dataControllers { id title } }');
Next Steps¶
- API Authentication - Complete authentication guide
- GraphQL Reference - Full schema documentation
- Webhooks - Configure integrations
- Error Handling - Error code reference