Skip to main content

Essential Backend Integration Tasks

While the Entrupy Android SDK handles the client-side user experience, your backend plays a crucial role in the authentication ecosystem. This guide outlines the essential backend tasks required for a complete integration.

1. User Authorization Endpoint

Your backend must provide an endpoint to handle SDK user authorization requests.

Endpoint Specification

URL: /api/entrupy/authorize-user (or your preferred path)
Method: POST
Authentication: Your app's authentication system

Request Format

{
"sdk_authorization_request": "raw_request_string_from_android_sdk"
}

Backend Implementation Example (Node.js)

app.post('/api/entrupy/authorize-user', async (req, res) => {
try {
// 1. Authenticate your user
const user = await authenticateUser(req.headers.authorization);
if (!user) {
return res.status(401).json({ error: 'Unauthorized' });
}

// 2. Call Entrupy's authorization API
const entrupyResponse = await fetch('https://api.entrupy.com/v2/integrations/authorize-user', {
method: 'POST',
headers: {
'Authorization': `Token ${process.env.ENTRUPY_API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
sdk_authorization_request: req.body.sdk_authorization_request,
unique_user_id: user.id,
email: user.email,
first_name: user.firstName,
last_name: user.lastName
})
});

const result = await entrupyResponse.json();

if (!entrupyResponse.ok) {
throw new Error(`Entrupy API error: ${result.error}`);
}

// 3. Return signed request to Android app
res.json({
signed_authorization_request: result.signed_authorization_request,
username: result.username
});

} catch (error) {
console.error('Authorization error:', error);
res.status(500).json({ error: 'Authorization failed' });
}
});

Backend Implementation Example (Python/Django)

import requests
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required

@csrf_exempt
@login_required
def authorize_entrupy_user(request):
if request.method != 'POST':
return JsonResponse({'error': 'Method not allowed'}, status=405)

try:
data = json.loads(request.body)
sdk_request = data.get('sdk_authorization_request')

if not sdk_request:
return JsonResponse({'error': 'Missing SDK request'}, status=400)

# Call Entrupy API
entrupy_response = requests.post(
'https://api.entrupy.com/v2/integrations/authorize-user',
headers={
'Authorization': f'Token {settings.ENTRUPY_API_TOKEN}',
'Content-Type': 'application/json'
},
json={
'sdk_authorization_request': sdk_request,
'unique_user_id': str(request.user.id),
'email': request.user.email,
'first_name': request.user.first_name,
'last_name': request.user.last_name
}
)

if entrupy_response.status_code != 200:
return JsonResponse({'error': 'Entrupy authorization failed'}, status=500)

result = entrupy_response.json()

return JsonResponse({
'signed_authorization_request': result['signed_authorization_request'],
'username': result['username']
})

except Exception as e:
return JsonResponse({'error': str(e)}, status=500)

2. Webhook Handler

Set up webhook endpoints to receive real-time updates about authentication results.

Webhook Endpoint

URL: /api/entrupy/webhooks (or your preferred path)
Method: POST
Authentication: Webhook signature verification

Webhook Implementation Example (Node.js)

app.post('/api/entrupy/webhooks', async (req, res) => {
try {
// 1. Verify webhook signature (recommended)
const signature = req.headers['x-entrupy-signature'];
if (!verifyWebhookSignature(req.body, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}

const webhookData = req.body;

// 2. Process webhook based on event type
switch (webhookData.event_type) {
case 'authentication.completed':
await handleAuthenticationCompleted(webhookData);
break;
case 'authentication.failed':
await handleAuthenticationFailed(webhookData);
break;
case 'authentication.requires_action':
await handleAuthenticationRequiresAction(webhookData);
break;
default:
console.log('Unknown webhook event:', webhookData.event_type);
}

res.status(200).json({ received: true });

} catch (error) {
console.error('Webhook error:', error);
res.status(500).json({ error: 'Webhook processing failed' });
}
});

async function handleAuthenticationCompleted(data) {
const { item_id, customer_item_id, result, certificate_url } = data;

// Update your database
await updateItemStatus(customer_item_id, 'completed', result);

// Send push notification to user (if applicable)
await sendPushNotification(customer_item_id, 'Authentication completed');

// Update your inventory system
await updateInventorySystem(customer_item_id, result);
}

async function handleAuthenticationFailed(data) {
const { item_id, customer_item_id, reason } = data;

// Update your database
await updateItemStatus(customer_item_id, 'failed', { reason });

// Notify user about failure
await sendPushNotification(customer_item_id, 'Authentication failed');
}

async function handleAuthenticationRequiresAction(data) {
const { item_id, customer_item_id, required_action } = data;

// Update your database
await updateItemStatus(customer_item_id, 'requires_action', { required_action });

// Notify user about required action
await sendPushNotification(customer_item_id, 'Action required for authentication');
}

3. Item Status Synchronization

Implement endpoints to sync authentication status with your Android app.

Status Endpoint

URL: /api/entrupy/items/:customer_item_id/status
Method: GET
Authentication: Your app's authentication system

Implementation Example

app.get('/api/entrupy/items/:customerItemId/status', async (req, res) => {
try {
const { customerItemId } = req.params;
const user = await authenticateUser(req.headers.authorization);

// Get item status from your database
const itemStatus = await getItemStatus(customerItemId, user.id);

if (!itemStatus) {
return res.status(404).json({ error: 'Item not found' });
}

res.json({
customer_item_id: customerItemId,
status: itemStatus.status,
result: itemStatus.result,
created_at: itemStatus.createdAt,
updated_at: itemStatus.updatedAt,
eta: itemStatus.eta
});

} catch (error) {
console.error('Status check error:', error);
res.status(500).json({ error: 'Status check failed' });
}
});

4. Database Schema

Design your database to store authentication data efficiently.

-- Items table
CREATE TABLE entrupy_items (
id SERIAL PRIMARY KEY,
customer_item_id VARCHAR(255) NOT NULL,
entrupy_item_id VARCHAR(255),
user_id INTEGER NOT NULL,
brand VARCHAR(100),
style_name VARCHAR(255),
status VARCHAR(50) DEFAULT 'pending',
result JSONB,
metadata JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(customer_item_id, user_id)
);

-- Webhook events table
CREATE TABLE entrupy_webhook_events (
id SERIAL PRIMARY KEY,
event_id VARCHAR(255) UNIQUE,
event_type VARCHAR(100),
item_id VARCHAR(255),
customer_item_id VARCHAR(255),
payload JSONB,
processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Indexes for performance
CREATE INDEX idx_entrupy_items_user_id ON entrupy_items(user_id);
CREATE INDEX idx_entrupy_items_status ON entrupy_items(status);
CREATE INDEX idx_entrupy_items_customer_id ON entrupy_items(customer_item_id);

5. Error Handling and Monitoring

Implement comprehensive error handling and monitoring.

Error Handling

// Global error handler
app.use((error, req, res, next) => {
console.error('Backend error:', error);

// Log to monitoring service
logError(error, {
endpoint: req.path,
method: req.method,
userId: req.user?.id
});

// Return appropriate error response
res.status(500).json({
error: 'Internal server error',
requestId: req.id // For debugging
});
});

// Webhook error handling
async function processWebhookSafely(webhookData) {
try {
await processWebhook(webhookData);
} catch (error) {
// Log error but don't fail the webhook
console.error('Webhook processing error:', error);

// Store failed webhook for retry
await storeFailedWebhook(webhookData, error);
}
}

Monitoring

// Health check endpoint
app.get('/api/health', async (req, res) => {
try {
// Check database connectivity
await db.query('SELECT 1');

// Check Entrupy API connectivity
const entrupyHealth = await checkEntrupyAPI();

res.json({
status: 'healthy',
database: 'connected',
entrupy_api: entrupyHealth ? 'connected' : 'disconnected',
timestamp: new Date().toISOString()
});
} catch (error) {
res.status(503).json({
status: 'unhealthy',
error: error.message
});
}
});

6. Security Considerations

API Key Management

// Store API keys securely
const entrupyApiKey = process.env.ENTRUPY_API_TOKEN;

// Rotate keys periodically
async function rotateApiKey() {
// Implement key rotation logic
const newKey = await generateNewApiKey();
await updateApiKey(newKey);
}

Webhook Security

// Verify webhook signatures
function verifyWebhookSignature(payload, signature) {
const expectedSignature = crypto
.createHmac('sha256', process.env.ENTRUPY_WEBHOOK_SECRET)
.update(JSON.stringify(payload))
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}

7. Testing

Test Webhook Endpoint

// Test webhook locally
app.post('/api/entrupy/test-webhook', (req, res) => {
const testData = {
event_type: 'authentication.completed',
item_id: 'test_item_123',
customer_item_id: 'test_customer_item_456',
result: { authenticity: 'authentic', confidence: 0.95 }
};

// Process test webhook
handleAuthenticationCompleted(testData);

res.json({ message: 'Test webhook processed' });
});

This comprehensive backend integration ensures your Android app can seamlessly work with Entrupy's authentication services while maintaining data consistency and providing a smooth user experience.