Integration
Complete guide for integrating the Credit Engine with your applications and services.
Integration with Earna Console
The Credit Engine is designed to work seamlessly with the main Earna Console application.
Console Integration Setup
// console/lib/credit-engine/client.ts
import { CreditEngineClient } from './types';
export class CreditEngine implements CreditEngineClient {
private baseUrl: string;
private apiKey: string;
constructor() {
this.baseUrl = process.env.NEXT_PUBLIC_CREDIT_ENGINE_URL || 'http://localhost:3004';
this.apiKey = process.env.CREDIT_ENGINE_API_KEY!;
}
async chat(messages: Message[], context?: CreditContext) {
const response = await fetch(`${this.baseUrl}/api/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({ messages, context })
});
if (!response.ok) {
throw new Error(`Credit Engine error: ${response.statusText}`);
}
return response.json();
}
}
Using in Console Components
// console/components/credit-coach.tsx
import { useCreditEngine } from '@/hooks/use-credit-engine';
export function CreditCoach() {
const { chat, isLoading } = useCreditEngine();
const [messages, setMessages] = useState<Message[]>([]);
const handleSubmit = async (content: string) {
const newMessage = { role: 'user', content };
const updatedMessages = [...messages, newMessage];
const response = await chat(updatedMessages, {
creditScore: user.creditScore,
creditGoal: user.creditGoal
});
setMessages([...updatedMessages, response]);
};
return (
<div className="credit-coach">
<ChatInterface
messages={messages}
onSubmit={handleSubmit}
isLoading={isLoading}
/>
</div>
);
}
Third-Party Integrations
REST API Integration
Basic integration using any HTTP client:
// JavaScript/Node.js
const axios = require('axios');
class CreditEngineAPI {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://credit-api.earna.sh';
}
async makeRequest(endpoint, method = 'GET', data = null) {
const config = {
method,
url: `${this.baseUrl}${endpoint}`,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
};
if (data) {
config.data = data;
}
try {
const response = await axios(config);
return response.data;
} catch (error) {
console.error('API Error:', error.response?.data || error.message);
throw error;
}
}
// Example methods
async getCreditAnalysis(userId) {
return this.makeRequest(`/api/analyze/user/${userId}`);
}
async generateDispute(disputeData) {
return this.makeRequest('/api/generate/dispute', 'POST', disputeData);
}
}
Python Integration
# Python integration example
import requests
import json
from typing import Dict, List, Optional
class CreditEngineClient:
def __init__(self, api_key: str, base_url: str = "https://credit-api.earna.sh"):
self.api_key = api_key
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
})
def chat(self, messages: List[Dict], context: Optional[Dict] = None):
"""Send chat messages to credit coach"""
payload = {
"messages": messages,
"context": context or {}
}
response = self.session.post(
f"{self.base_url}/api/chat",
json=payload
)
response.raise_for_status()
return response.json()
def analyze_impact(self, current_score: int, actions: List[Dict]):
"""Analyze impact of actions on credit score"""
payload = {
"currentScore": current_score,
"actions": actions,
"timeframe": 6
}
response = self.session.post(
f"{self.base_url}/api/analyze/impact",
json=payload
)
response.raise_for_status()
return response.json()
# Usage
client = CreditEngineClient(api_key="your_api_key")
response = client.chat([
{"role": "user", "content": "How can I improve my credit score?"}
])
print(response["response"]["content"])
Webhook Integration
Setting Up Webhooks
Configure webhooks to receive real-time notifications:
// Setup webhook endpoint
const webhookConfig = {
url: 'https://your-app.com/webhooks/credit-engine',
events: [
'score.changed',
'alert.created',
'goal.achieved'
],
secret: 'your_webhook_secret'
};
// Register webhook
await creditEngine.webhooks.create(webhookConfig);
Handling Webhook Events
// Express.js webhook handler
app.post('/webhooks/credit-engine', (req, res) => {
const signature = req.headers['x-credit-engine-signature'];
const payload = JSON.stringify(req.body);
// Verify signature
if (!verifySignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process event
const event = req.body;
switch (event.type) {
case 'score.changed':
handleScoreChange(event.data);
break;
case 'alert.created':
sendAlertNotification(event.data);
break;
case 'goal.achieved':
celebrateGoalAchievement(event.data);
break;
}
res.status(200).send('OK');
});
function verifySignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
Mobile App Integration
React Native
// React Native integration
import AsyncStorage from '@react-native-async-storage/async-storage';
class CreditEngineService {
private apiKey: string;
private baseUrl = 'https://credit-api.earna.sh';
async initialize() {
this.apiKey = await AsyncStorage.getItem('credit_engine_api_key');
}
async chat(messages: Message[]): Promise<ChatResponse> {
const response = await fetch(`${this.baseUrl}/api/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({ messages })
});
if (!response.ok) {
throw new Error('Credit Engine request failed');
}
return response.json();
}
// Stream responses for better UX
async *streamChat(messages: Message[]) {
const response = await fetch(`${this.baseUrl}/api/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({
messages,
options: { streamResponse: true }
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
yield chunk;
}
}
}
Flutter Integration
// Flutter integration
import 'package:http/http.dart' as http;
import 'dart:convert';
class CreditEngineClient {
final String apiKey;
final String baseUrl = 'https://credit-api.earna.sh';
CreditEngineClient({required this.apiKey});
Future<Map<String, dynamic>> chat(List<Map<String, String>> messages) async {
final response = await http.post(
Uri.parse('$baseUrl/api/chat'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $apiKey',
},
body: jsonEncode({
'messages': messages,
}),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load credit advice');
}
}
Future<Map<String, dynamic>> analyzeImpact({
required int currentScore,
required List<Map<String, dynamic>> actions,
}) async {
final response = await http.post(
Uri.parse('$baseUrl/api/analyze/impact'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $apiKey',
},
body: jsonEncode({
'currentScore': currentScore,
'actions': actions,
'timeframe': 6,
}),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to analyze impact');
}
}
}
Banking API Integration
Plaid Integration (Planned)
// Planned Plaid integration for bank data
import { PlaidClient } from 'plaid';
class BankingIntegration {
private plaid: PlaidClient;
private creditEngine: CreditEngineClient;
constructor() {
this.plaid = new PlaidClient({
clientId: process.env.PLAID_CLIENT_ID,
secret: process.env.PLAID_SECRET,
env: process.env.PLAID_ENV
});
}
async analyzeBankStatements(accessToken: string) {
// Get transactions from Plaid
const transactions = await this.plaid.transactions.get({
access_token: accessToken,
start_date: '2024-01-01',
end_date: '2024-12-31'
});
// Send to Credit Engine for analysis
const analysis = await this.creditEngine.analyzeBankData({
transactions: transactions.transactions,
accounts: transactions.accounts
});
return {
spending_patterns: analysis.patterns,
credit_impact: analysis.creditImpact,
recommendations: analysis.recommendations
};
}
}
Credit Bureau Integration
Bureau API Integration (Planned)
// Planned credit bureau integration
interface BureauIntegration {
fetchReport(userId: string, bureau: string): Promise<CreditReport>;
subscribeToUpdates(userId: string): Promise<Subscription>;
disputeItem(itemId: string, reason: string): Promise<DisputeStatus>;
}
class ExperianIntegration implements BureauIntegration {
async fetchReport(userId: string) {
// Fetch from Experian API
const report = await experianAPI.getCreditReport(userId);
// Send to Credit Engine for processing
const processed = await creditEngine.processReport({
bureau: 'experian',
rawReport: report
});
return processed;
}
}
GraphQL Integration
GraphQL Schema
type Query {
creditScore(userId: ID!): CreditScore
creditAnalysis(userId: ID!): CreditAnalysis
creditHistory(userId: ID!, limit: Int): [CreditHistoryItem]
}
type Mutation {
sendCreditChat(input: ChatInput!): ChatResponse
generateDispute(input: DisputeInput!): Document
analyzeImpact(input: ImpactInput!): ImpactAnalysis
}
type Subscription {
scoreUpdates(userId: ID!): ScoreUpdate
creditAlerts(userId: ID!): Alert
}
type CreditScore {
score: Int!
bureau: String!
date: String!
factors: [ScoreFactor]
}
type ChatResponse {
content: String!
recommendations: [Recommendation]
analysis: Analysis
}
input ChatInput {
messages: [MessageInput!]!
context: ContextInput
}
input MessageInput {
role: String!
content: String!
}
GraphQL Client
// Apollo Client integration
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://credit-api.earna.sh/graphql',
cache: new InMemoryCache(),
headers: {
authorization: `Bearer ${apiKey}`
}
});
// Query example
const CREDIT_CHAT = gql`
mutation SendCreditChat($input: ChatInput!) {
sendCreditChat(input: $input) {
content
recommendations {
action
impact
priority
}
}
}
`;
const result = await client.mutate({
mutation: CREDIT_CHAT,
variables: {
input: {
messages: [
{ role: 'user', content: 'How to improve my score?' }
]
}
}
});
SDK Development
TypeScript SDK Structure
// @earna/credit-engine-sdk
export class CreditEngineSDK {
private client: HttpClient;
public chat: ChatAPI;
public analysis: AnalysisAPI;
public documents: DocumentsAPI;
public monitoring: MonitoringAPI;
public webhooks: WebhooksAPI;
constructor(config: SDKConfig) {
this.client = new HttpClient(config);
this.chat = new ChatAPI(this.client);
this.analysis = new AnalysisAPI(this.client);
this.documents = new DocumentsAPI(this.client);
this.monitoring = new MonitoringAPI(this.client);
this.webhooks = new WebhooksAPI(this.client);
}
}
// Usage
import { CreditEngineSDK } from '@earna/credit-engine-sdk';
const sdk = new CreditEngineSDK({
apiKey: 'your_api_key',
environment: 'production'
});
const response = await sdk.chat.send({
messages: [{ role: 'user', content: 'Help me improve my credit' }]
});
Testing Integration
Integration Testing
// Integration test example
import { CreditEngineClient } from '@/lib/credit-engine';
describe('Credit Engine Integration', () => {
let client: CreditEngineClient;
beforeAll(() => {
client = new CreditEngineClient({
apiKey: process.env.TEST_API_KEY,
baseUrl: process.env.TEST_BASE_URL
});
});
test('should return credit advice', async () => {
const response = await client.chat([
{ role: 'user', content: 'Test message' }
]);
expect(response).toHaveProperty('response');
expect(response.response).toHaveProperty('content');
});
test('should handle errors gracefully', async () => {
const invalidClient = new CreditEngineClient({
apiKey: 'invalid_key',
baseUrl: process.env.TEST_BASE_URL
});
await expect(invalidClient.chat([])).rejects.toThrow('Unauthorized');
});
});
Monitoring Integration
Application Performance Monitoring
// Sentry integration for error tracking
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
],
tracesSampleRate: 1.0,
});
// Wrap Credit Engine calls
async function chatWithMonitoring(messages: Message[]) {
const transaction = Sentry.startTransaction({
op: 'credit-engine.chat',
name: 'Credit Engine Chat'
});
try {
const result = await creditEngine.chat(messages);
transaction.setStatus('ok');
return result;
} catch (error) {
Sentry.captureException(error);
transaction.setStatus('internal_error');
throw error;
} finally {
transaction.finish();
}
}
Last updated on