Getting Recent Calls
Retrieve the most recent calls from your workspace with participant information.- Query
- Response
- Implementation
Copy
query GetRecentCalls {
interview(limit: 5, order_by: { started_at: desc }) {
id
name
started_at
duration_sec
type {
name
}
attendees {
person {
first_name
last_name
email
}
}
}
}
Copy
{
"data": {
"interview": [
{
"id": 12345,
"name": "Product Review Meeting",
"started_at": "2025-01-15T14:00:00Z",
"duration_sec": 1800,
"type": {
"name": "Internal Meeting"
},
"attendees": [
{
"person": {
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com"
}
}
]
}
]
}
}
Copy
// JavaScript/Node.js example
const axios = require('axios');
async function getRecentCalls() {
const query = `
query GetRecentCalls {
interview(limit: 5, order_by: { started_at: desc }) {
id
name
started_at
attendees {
person {
first_name
last_name
}
}
}
}
`;
const response = await axios.post(
'https://api.buildbetter.app/graphql',
{ query },
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
}
);
return response.data;
}
Extracting Call Insights
Get signals and key moments from a specific call.- Query
- Variables
- Python Implementation
Copy
query GetCallInsights($callId: bigint!) {
extraction(
where: { interview_id: { _eq: $callId } }
order_by: { start_sec: asc }
) {
id
summary
context
start_sec
end_sec
types {
type {
name
}
}
topics {
topic {
text
}
}
attendee {
person {
first_name
last_name
}
}
}
}
Copy
{
"callId": 12345
}
Copy
import requests
import json
def get_call_insights(call_id):
url = "https://api.buildbetter.app/graphql"
query = """
query GetCallInsights($callId: bigint!) {
extraction(
where: { interview_id: { _eq: $callId } }
order_by: { start_sec: asc }
) {
id
summary
context
types {
type {
name
}
}
}
}
"""
variables = {"callId": call_id}
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
response = requests.post(
url,
json={"query": query, "variables": variables},
headers=headers
)
return response.json()
# Usage
insights = get_call_insights(12345)
for signal in insights['data']['extraction']:
print(f"Signal: {signal['summary']}")
print(f"Type: {signal['types'][0]['type']['name']}")
Building a Call Dashboard
Create a comprehensive dashboard showing calls, participants, and key metrics.- Dashboard Query
- React Component
Copy
query DashboardData($startDate: timestamptz!, $endDate: timestamptz!) {
# Get calls in date range
calls: interview(
where: {
started_at: { _gte: $startDate, _lte: $endDate }
}
order_by: { started_at: desc }
) {
id
name
started_at
duration_sec
attendee_count: attendees_aggregate {
aggregate {
count
}
}
signal_count: extractions_aggregate {
aggregate {
count
}
}
}
# Get top participants
participants: person(
limit: 10
order_by: { attendances_aggregate: { count: desc } }
) {
first_name
last_name
email
call_count: attendances_aggregate {
aggregate {
count
}
}
}
# Get signal statistics
signals: extraction_aggregate(
where: {
interview: {
started_at: { _gte: $startDate, _lte: $endDate }
}
}
) {
aggregate {
count
}
}
}
Copy
import React, { useEffect, useState } from 'react';
import { useQuery, gql } from '@apollo/client';
const DASHBOARD_QUERY = gql`
query DashboardData($startDate: timestamptz!, $endDate: timestamptz!) {
calls: interview(
where: {
started_at: { _gte: $startDate, _lte: $endDate }
}
order_by: { started_at: desc }
) {
id
name
started_at
duration_sec
}
}
`;
function CallDashboard() {
const [startDate] = useState(new Date(Date.now() - 7 * 24 * 60 * 60 * 1000));
const [endDate] = useState(new Date());
const { loading, error, data } = useQuery(DASHBOARD_QUERY, {
variables: {
startDate: startDate.toISOString(),
endDate: endDate.toISOString()
}
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h2>Recent Calls</h2>
<ul>
{data.calls.map(call => (
<li key={call.id}>
{call.name} - {new Date(call.started_at).toLocaleDateString()}
</li>
))}
</ul>
</div>
);
}
Searching and Filtering
Find specific calls or content across your workspace.- Search Query
- Advanced Filter
Copy
query SearchCalls(
$searchTerm: String!
$participantEmail: String
$startDate: timestamptz
$endDate: timestamptz
) {
interview(
where: {
_and: [
{ name: { _ilike: $searchTerm } }
{ started_at: { _gte: $startDate } }
{ started_at: { _lte: $endDate } }
{
attendees: {
person: {
email: { _eq: $participantEmail }
}
}
}
]
}
order_by: { started_at: desc }
) {
id
name
started_at
attendees {
person {
first_name
last_name
email
}
}
}
}
Copy
# Find calls with specific signal types
query CallsWithPainPoints {
interview(
where: {
extractions: {
types: {
type: {
name: { _eq: "Pain Point" }
}
}
}
}
) {
id
name
pain_points: extractions(
where: {
types: {
type: {
name: { _eq: "Pain Point" }
}
}
}
) {
summary
context
}
}
}
Document Generation Status
Monitor AI-generated document creation and status.- Document Query
- Polling Implementation
Copy
query GetDocumentStatus($docId: bigint!) {
document_by_pk(id: $docId) {
id
name
status
content
created_at
updated_at
creator {
person {
first_name
last_name
}
}
# Source calls used to generate this document
input_data {
call {
id
name
started_at
}
}
}
}
Copy
// TypeScript implementation with polling
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
class DocumentMonitor {
private client: ApolloClient<any>;
constructor(apiKey: string) {
this.client = new ApolloClient({
uri: 'https://api.buildbetter.app/graphql',
cache: new InMemoryCache(),
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
}
async pollDocumentStatus(
docId: number,
onComplete: (doc: any) => void,
interval: number = 5000
): Promise<void> {
const query = gql`
query GetDocumentStatus($docId: bigint!) {
document_by_pk(id: $docId) {
id
name
status
content
}
}
`;
const checkStatus = async () => {
const result = await this.client.query({
query,
variables: { docId },
fetchPolicy: 'network-only'
});
const doc = result.data.document_by_pk;
if (doc.status === 'completed') {
onComplete(doc);
} else {
setTimeout(checkStatus, interval);
}
};
await checkStatus();
}
}
// Usage
const monitor = new DocumentMonitor('YOUR_API_KEY');
monitor.pollDocumentStatus(12345, (doc) => {
console.log('Document ready:', doc.name);
console.log('Content:', doc.content);
});
Pagination Patterns
Handle large datasets efficiently with cursor-based or offset pagination.- Offset Pagination
- Implementation
Copy
query GetCallsPaginated($limit: Int!, $offset: Int!) {
interview(
limit: $limit
offset: $offset
order_by: { started_at: desc }
) {
id
name
started_at
}
# Get total count for pagination controls
interview_aggregate {
aggregate {
count
}
}
}
Copy
class CallPaginator {
constructor(apiClient, pageSize = 10) {
this.client = apiClient;
this.pageSize = pageSize;
this.currentPage = 0;
}
async getPage(pageNumber) {
const offset = pageNumber * this.pageSize;
const query = `
query GetCallsPaginated($limit: Int!, $offset: Int!) {
interview(
limit: $limit
offset: $offset
order_by: { started_at: desc }
) {
id
name
started_at
}
interview_aggregate {
aggregate {
count
}
}
}
`;
const result = await this.client.query({
query,
variables: {
limit: this.pageSize,
offset
}
});
const totalCount = result.data.interview_aggregate.aggregate.count;
const totalPages = Math.ceil(totalCount / this.pageSize);
return {
data: result.data.interview,
pageInfo: {
currentPage: pageNumber,
totalPages,
totalCount,
hasNext: pageNumber < totalPages - 1,
hasPrev: pageNumber > 0
}
};
}
}
Error Handling
Properly handle errors and edge cases in your GraphQL implementations.Copy
async function safeGraphQLQuery(query, variables = {}) {
try {
const response = await fetch('https://api.buildbetter.app/graphql', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ query, variables })
});
const result = await response.json();
// Check for GraphQL errors
if (result.errors) {
console.error('GraphQL Errors:', result.errors);
// Handle specific error types
result.errors.forEach(error => {
if (error.message.includes('permission denied')) {
throw new Error('Access denied. Check your API key permissions.');
}
if (error.message.includes('not found')) {
throw new Error('Resource not found.');
}
});
throw new Error('GraphQL query failed');
}
return result.data;
} catch (error) {
// Handle network errors
if (error.name === 'NetworkError') {
console.error('Network error:', error);
throw new Error('Unable to connect to API');
}
// Re-throw other errors
throw error;
}
}
Tips
- Request only needed fields - GraphQL returns exactly what you ask for
- Use pagination for large datasets to avoid timeouts
- Store API keys securely - never expose them in client-side code
- Test queries first in a GraphQL playground before implementing