API Integration Guide¶
Dxtra provides GraphQL and REST APIs for privacy compliance integration. No proprietary SDKs are required -- use standard GraphQL clients in your preferred language.
Integration Approach
Dxtra uses a GraphQL-first API architecture. Use any standard GraphQL client library (Apollo, graphql-request, gql, etc.) in your preferred language.
Integration Methods¶
GraphQL API (Primary)¶
Direct access to Dxtra's privacy data using GraphQL.
API Endpoint:
| Environment | GraphQL API | Authentication |
|---|---|---|
| Production | https://api.dxtra.ai/v1/graphql | https://auth.dxtra.ai |
Implementation Pattern:
// Use any GraphQL client -- Apollo Client, urql, graphql-request, etc.
import { GraphQLClient } from 'graphql-request';
// 1. Authenticate to get JWT token
const authResponse = await fetch('https://auth.dxtra.ai/v1/signin/pat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ personalAccessToken: process.env.DXTRA_PAT })
});
const { session } = await authResponse.json();
const jwtToken = session.accessToken;
// 2. Create GraphQL client with JWT
const client = new GraphQLClient('https://api.dxtra.ai/v1/graphql', {
headers: {
'Authorization': `Bearer ${jwtToken}`,
'X-Hasura-Role': 'user'
}
});
// 3. Execute queries
const data = await client.request(`
query GetDataSubjects($controllerId: uuid!) {
dataSubjects(where: {dataControllerId: {_eq: $controllerId}}) {
id
did
createdAt
}
}
`, { controllerId: 'your-controller-id' });
REST API¶
Selected GraphQL operations exposed as REST endpoints for simple HTTP access.
# Get data controller details
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Hasura-Role: user" \
"https://api.dxtra.ai/api/rest/getdatacontrollerdetails"
# Submit rights request
curl -X POST \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"dataSubjectId": "uuid", "requestType": "access"}' \
"https://api.dxtra.ai/api/rest/insertdatasubjectsrightsrequest"
REST vs GraphQL
REST endpoints are simpler for basic operations but less flexible than GraphQL. Use REST for quick prototypes, GraphQL for production applications requiring complex data access.
Webhook Integration¶
Configure third-party services to send data to Dxtra via webhooks.
Webhook URL Pattern:
https://conduit.dxtra.ai/api/v1/integrations/{service}/event?did={YOUR_DID}&dxKey={YOUR_DX_KEY}
Legacy vs. current authentication
The ?did=...&dxKey=... query parameter format applies to Shopify and legacy integrations. Newer integrations (Stripe, Xero, Salesforce) use a JWE token format instead: ?token={JWE_TOKEN}. See the integration-specific guides for the correct format.
See the Webhook Guide for platform-specific configuration.
Transparency Center (Web Component)¶
Embed the Transparency Center on your website as a custom element:
<!-- Load the Transparency Center -->
<script src="https://transparencycenter.dxtra.ai/assets/index.js" type="module"></script>
<!-- Embed the privacy portal -->
<transparency-app data-controller-id="YOUR_DATA_CONTROLLER_ID"></transparency-app>
The Transparency Center provides a self-service privacy portal where data subjects can:
- View processing purposes and legal basis
- Submit rights requests (access, deletion, portability)
- Manage consent preferences
- Access privacy notices and FAQs
See Transparency Center for configuration details.
Language-Specific Examples¶
Node.js / TypeScript¶
Recommended Libraries:
Implementation:
import { GraphQLClient } from 'graphql-request';
interface AuthSession {
session: {
accessToken: string;
refreshToken: string;
accessTokenExpiresIn: number;
};
}
class DXTRAClient {
private client: GraphQLClient;
private pat: string;
private accessToken: string | null = null;
private tokenExpiry: number = 0;
constructor(personalAccessToken: string) {
this.pat = personalAccessToken;
this.client = new GraphQLClient('https://api.dxtra.ai/v1/graphql');
}
private async refreshToken(): Promise<void> {
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(`Authentication failed: ${response.statusText}`);
}
const data: AuthSession = await response.json();
this.accessToken = data.session.accessToken;
this.tokenExpiry = Date.now() + (data.session.accessTokenExpiresIn - 120) * 1000;
this.client.setHeaders({
'Authorization': `Bearer ${this.accessToken}`,
'X-Hasura-Role': 'user'
});
}
async query<T>(query: string, variables?: Record<string, unknown>): Promise<T> {
if (!this.accessToken || Date.now() >= this.tokenExpiry) {
await this.refreshToken();
}
return this.client.request<T>(query, variables);
}
}
// Usage
const client = new DXTRAClient(process.env.DXTRA_PAT!);
const data = await client.query(`
query GetDataControllers {
dataControllers { id title did }
}
`);
Python¶
Recommended Libraries:
Implementation:
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
import requests
import os
from datetime import datetime, timedelta
class DXTRAClient:
def __init__(self, personal_access_token: str):
self.pat = personal_access_token
self.access_token = None
self.token_expiry = None
self.client = None
def _refresh_token(self):
response = requests.post(
'https://auth.dxtra.ai/v1/signin/pat',
json={'personalAccessToken': self.pat}
)
response.raise_for_status()
data = response.json()
self.access_token = data['session']['accessToken']
expires_in = data['session']['accessTokenExpiresIn'] - 120
self.token_expiry = datetime.now() + timedelta(seconds=expires_in)
transport = RequestsHTTPTransport(
url='https://api.dxtra.ai/v1/graphql',
headers={
'Authorization': f'Bearer {self.access_token}',
'X-Hasura-Role': 'user'
}
)
self.client = Client(transport=transport, fetch_schema_from_transport=True)
def query(self, query_string: str, variables: dict = None):
if not self.access_token or datetime.now() >= self.token_expiry:
self._refresh_token()
query = gql(query_string)
return self.client.execute(query, variable_values=variables)
# Usage
client = DXTRAClient(os.getenv('DXTRA_PAT'))
result = client.query("""
query GetDataControllers {
dataControllers { id title did }
}
""")
React Applications¶
Recommended Libraries:
Implementation:
import { NhostClient, NhostProvider, useAuthenticated, useNhostClient } from '@nhost/react';
import { NhostApolloProvider } from '@nhost/react-apollo';
import { useEffect } from 'react';
// Initialize Nhost client with custom domain
const nhost = new NhostClient({
authUrl: 'https://auth.dxtra.ai',
graphqlUrl: 'https://api.dxtra.ai/v1/graphql',
storageUrl: 'https://storage.dxtra.ai',
});
function App() {
return (
<NhostProvider nhost={nhost}>
<NhostApolloProvider nhost={nhost}>
<AuthenticatedApp />
</NhostApolloProvider>
</NhostProvider>
);
}
function AuthenticatedApp() {
const isAuthenticated = useAuthenticated();
const nhost = useNhostClient();
// Authenticate with PAT via direct HTTP exchange
useEffect(() => {
if (!isAuthenticated) {
// PATs are exchanged via POST to /v1/signin/pat
fetch(`${nhost.auth.url}/v1/signin/pat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
personalAccessToken: process.env.REACT_APP_DXTRA_PAT
})
})
.then(res => res.json())
.then(data => {
// Use the returned session to authenticate the Nhost client
if (data.session) {
nhost.auth.setSession(data.session);
}
});
}
}, [isAuthenticated, nhost]);
if (!isAuthenticated) {
return <div>Authenticating...</div>;
}
return <Dashboard />;
}
// Use Apollo Client hooks for queries
import { useQuery, gql } from '@apollo/client';
const GET_DATA_CONTROLLERS = gql`
query GetDataControllers {
dataControllers { id title did }
}
`;
function Dashboard() {
const { data, loading, error } = useQuery(GET_DATA_CONTROLLERS);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.dataControllers.map((controller: any) => (
<li key={controller.id}>{controller.title}</li>
))}
</ul>
);
}
Response Format¶
Dxtra's GraphQL API returns standard GraphQL response shapes:
- Success:
{ "data": { ... } } - Error:
{ "errors": [{ "message": "...", "extensions": { ... } }] }
Authentication¶
Dxtra uses a two-step authentication flow:
- Exchange Personal Access Token (PAT) for JWT
- Use JWT for API requests (valid 1 hour)
- Refresh JWT before expiration or on 401 errors
See the Authentication Guide for detailed implementation patterns.
Best Practices¶
Query Optimization¶
# Request only needed fields
query GetDataSubjects {
dataSubjects(limit: 50) {
id
did
createdAt
}
}
Error Handling¶
async function safeQuery<T>(client: DXTRAClient, query: string): Promise<T | null> {
try {
return await client.query<T>(query);
} catch (error) {
if (error.response?.status === 401) {
console.log('Token expired, retrying with fresh token');
return await client.query<T>(query);
}
if (error.response?.status === 429) {
console.error('Rate limit exceeded');
throw new Error('Rate limit exceeded. Please retry later.');
}
console.error('Query failed:', error);
return null;
}
}
Security¶
- Store PATs securely -- Use environment variables, never commit to source control
- Use HTTPS only -- All API calls must use encrypted connections
- Rotate credentials -- Change PATs regularly
- Validate input -- Sanitize all variables before passing to queries
- Respect rate limits -- Implement retry logic with exponential backoff
Next Steps¶
- Authentication Guide -- Set up API access with JWT tokens
- GraphQL Reference -- Complete schema documentation
- Webhook Guide -- Configure third-party integrations
- Code Samples -- Production-ready examples
- Error Handling -- Comprehensive error reference
For integration questions, email privacy@dxtra.ai.