TwinMind Local Dev Loop
Overview
Configure a productive local development environment for TwinMind API integration.
Prerequisites
- TwinMind Pro or Enterprise account (API access)
- Node.js 18+ or Python 3.10+
- API key from TwinMind dashboard
- Local development environment
Instructions
Step 1: Project Setup
# Create project directory
mkdir twinmind-integration && cd twinmind-integration
# Initialize Node.js project
npm init -y
# Install dependencies
npm install dotenv axios zod typescript ts-node @types/node
# Initialize TypeScript
npx tsc --init
Step 2: Configure Environment
# Create environment file
cat > .env << 'EOF'
TWINMIND_API_KEY=your-api-key-here
TWINMIND_API_URL=https://api.twinmind.com/v1
TWINMIND_WEBHOOK_SECRET=your-webhook-secret
NODE_ENV=development
EOF
# Add to .gitignore
echo ".env" >> .gitignore
echo "node_modules" >> .gitignore
Step 3: Create TwinMind Client
// src/twinmind/client.ts
import axios, { AxiosInstance } from 'axios';
import { z } from 'zod';
// Response schemas
const TranscriptSchema = z.object({
id: z.string(),
text: z.string(),
duration_seconds: z.number(),
language: z.string(),
speakers: z.array(z.object({
id: z.string(),
name: z.string().optional(),
segments: z.array(z.object({
start: z.number(),
end: z.number(),
text: z.string(),
confidence: z.number(),
})),
})),
created_at: z.string(),
});
const SummarySchema = z.object({
id: z.string(),
transcript_id: z.string(),
summary: z.string(),
action_items: z.array(z.object({
text: z.string(),
assignee: z.string().optional(),
due_date: z.string().optional(),
})),
key_points: z.array(z.string()),
});
export type Transcript = z.infer<typeof TranscriptSchema>;
export type Summary = z.infer<typeof SummarySchema>;
export class TwinMindClient {
private client: AxiosInstance;
constructor(apiKey: string, baseUrl?: string) {
this.client = axios.create({
baseURL: baseUrl || 'https://api.twinmind.com/v1',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
timeout: 30000,
});
}
async healthCheck(): Promise<boolean> {
const response = await this.client.get('/health');
return response.status === 200;
}
async transcribe(audioUrl: string, options?: {
language?: string;
diarization?: boolean;
model?: 'ear-3' | 'ear-2';
}): Promise<Transcript> {
const response = await this.client.post('/transcribe', {
audio_url: audioUrl,
language: options?.language || 'auto',
diarization: options?.diarization ?? true,
model: options?.model || 'ear-3',
});
return TranscriptSchema.parse(response.data);
}
async summarize(transcriptId: string): Promise<Summary> {
const response = await this.client.post('/summarize', {
transcript_id: transcriptId,
});
return SummarySchema.parse(response.data);
}
async search(query: string, options?: {
limit?: number;
date_from?: string;
date_to?: string;
}): Promise<Transcript[]> {
const response = await this.client.get('/search', {
params: {
q: query,
limit: options?.limit || 10,
date_from: options?.date_from,
date_to: options?.date_to,
},
});
return z.array(TranscriptSchema).parse(response.data.results);
}
}