User Profile & User Events
The Synvo API provides intelligent user profiling and event tracking capabilities. Transform raw user data into actionable intelligence through structured profiles and chronological event records.
Authentication
All endpoints require authentication via:
- API Key:
X-API-Key: <token>
Base URL
https://api.synvo.aiGet User Profile
Retrieves comprehensive user profile with structured attributes across all categories.
Endpoint: GET /metadata/get_user_profile/
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
sub_user_name | string | default | Optional sub-user name under the authenticated account |
Example Request
curl -X GET "https://api.synvo.ai/metadata/get_user_profile/" \
-H "X-API-Key: ${API_TOKEN}" \
-H "Content-Type: application/json"import requests
api_token = "<API_TOKEN>"
url = "https://api.synvo.ai/metadata/get_user_profile/"
headers = {
"X-API-Key": api_token,
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())const apiToken = "<API_TOKEN>";
const response = await fetch("https://api.synvo.ai/metadata/get_user_profile/", {
method: "GET",
headers: {
"X-API-Key": apiToken,
"Content-Type": "application/json"
}
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
console.log(await response.json());Example Response
{
"education": {
"sub_topics": {
"school": {
"value": "Nanyang Technological University (NTU)"
},
"major": {
"value": "Artificial Intelligence"
}
}
},
"psychological": {
"sub_topics": {
"values": {
"value": "Values leadership and service in education, emphasises interactive learning, and places strong weight on financial literacy for better long-term decision-making."
},
"motivations": {
"value": "Motivated by improving learning quality and gaining financial knowledge that supports accurate decisions."
}
}
},
"interest": {
"sub_topics": {
"sports": {
"value": "Shows interest in self-care and wellness activities from event materials."
},
"books": {
"value": "Reads technical and analytical material, such as neural network explanations and financial summaries."
}
}
},
"work": {
"sub_topics": {
"work_skills": {
"value": "Shows familiarity with machine learning concepts and financial analysis principles."
}
}
}
}Response Codes
200- User profile retrieved successfully400- Bad request401- Unauthorized404- User not found
Get User Events
Retrieves chronological user events with flexible time-based filtering.
Endpoint: GET /metadata/get_user_event/
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
sub_user_name | string | default | Optional sub-user name under the authenticated account |
limit | integer | 10 | Maximum number of events to return |
start_time | datetime | - | Start time of the time window (ISO 8601 format) |
end_time | datetime | - | End time of the time window (ISO 8601 format) |
Example Request
curl -X GET "https://api.synvo.ai/metadata/get_user_event/?limit=5&start_time=2025-10-01T00:00:00Z" \
-H "X-API-Key: ${API_TOKEN}" \
-H "Content-Type: application/json"import requests
from datetime import datetime
api_token = "<API_TOKEN>"
url = "https://api.synvo.ai/metadata/get_user_event/"
params = {
"limit": 5,
"start_time": "2025-10-01T00:00:00Z"
}
headers = {
"X-API-Key": api_token,
"Content-Type": "application/json"
}
response = requests.get(url, params=params, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())const apiToken = "<API_TOKEN>";
const params = new URLSearchParams({
limit: "5",
start_time: "2025-10-01T00:00:00Z"
});
const response = await fetch(`https://api.synvo.ai/metadata/get_user_event/?${params}`, {
method: "GET",
headers: {
"X-API-Key": apiToken,
"Content-Type": "application/json"
}
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
console.log(await response.json());Example Response
[
{
"event_type": "personal",
"content": "User uploaded Nanyang Technological University (NTU) Annual Report for 2024.",
"happen_time": "2025-11-16T00:00:00",
"mention_time": "2025-11-16T15:29:18.344000"
},
{
"event_type": "personal",
"content": "User uploaded a video lecture presented by Andrew Ng about neural networks.",
"happen_time": "2025-11-16T00:00:00",
"mention_time": "2025-11-16T15:31:00.890000"
},
{
"event_type": "personal",
"content": "User saved an audio lecture explaining operating profit margin.",
"happen_time": "2025-11-16T00:00:00",
"mention_time": "2025-11-16T15:32:40.555000"
},
{
"event_type": "personal",
"content": "User received an invitation for the October WellFest event at Nanyang Technological University.",
"happen_time": "2025-10-23T00:00:00",
"mention_time": "2025-11-16T15:34:06.326000"
},
{
"event_type": "personal",
"content": "User encouraged colleagues to join the WellFest event focused on self-care and well-being.",
"happen_time": "2025-10-23T00:00:00",
"mention_time": "2025-11-16T15:34:06.326000"
},
{
"event_type": "financial",
"content": "User plans to attend the October WellFest event on 23rd October 2025.",
"happen_time": "2025-10-23T00:00:00",
"mention_time": "2025-11-16T15:34:06.326000"
}
]Response Codes
200- Events retrieved successfully400- Invalid parameters401- Unauthorized404- User not found
Profile Schema
The profiling system uses 8 main categories with 34 fine-grained subtopics, automatically populated when supporting evidence is found in user files.
Categories and Subtopics
The Synvo profiling schema defines 8 top-level categories and 34 subtopics.
Each category stores different types of long-term signals extracted from user files.
Only entries supported by clear evidence are included in the final profile.
| Category | Subtopics Count | Subtopics | Description |
|---|---|---|---|
| basic_info | 7 | Name, Age, Gender, birth_date, nationality, ethnicity, language_spoken | Core identity-related fields extracted only when explicitly present in files. These represent fundamental personal attributes. |
| contact_info | 4 | email, phone, city, country | Contact information derived from user-provided documents such as forms, resumes, or institutional material. |
| education | 3 | school, degree, major | Academic background and fields of study, inferred from certificates, lecture content, or university material. |
| demographics | 3 | marital_status, number_of_children, household_income | General demographic information included only when directly observable from the content. |
| work | 5 | company, title, working_industry, previous_projects, work_skills | Professional signals extracted from resumes, technical documents, project summaries, or workplace material. |
| interest | 5 | books, movies, music, foods, sports | Interests and preference patterns derived from media files, event posters, and activity-related content. |
| psychological | 5 | personality, values, beliefs, motivations, goals | Higher-level traits inferred from mission statements, reflective writing, or patterns across multiple documents. |
| life_event | 3 | marriage, relocation, retirement | Significant personal milestones extracted only when material explicitly describes a major event. |
| Total | 34 | — | — |
Event Types
Events are categorized by type to provide context about user activities:
- personal - Individual activities and preferences
- financial - Finance-related activities and decisions
- professional - Work and career-related events
- educational - Learning and academic activities
- social - Community and relationship interactions
Time Fields
Each event contains two timestamp fields:
- happen_time: When the event actually occurred (extracted from content)
- mention_time: When the file was uploaded by user
If no reliable date is found in the content, happen_time is set to null.
Complete Profile Workflow Example
Here's a complete example showing how to upload files and retrieve the resulting profile data:
import requests
import time
api_token = "<API_TOKEN>"
BASE_URL = "https://api.synvo.ai"
# Step 1: Upload files (using File Upload API)
print("📤 Uploading user documents...")
files_to_upload = [
"/path/to/resume.pdf",
"/path/to/transcript.pdf",
"/path/to/portfolio.zip"
]
file_ids = []
for file_path in files_to_upload:
with open(file_path, "rb") as f:
files = {"file": f}
response = requests.post(
f"{BASE_URL}/file/upload",
files=files,
headers={"X-API-Key": api_token},
timeout=60
)
result = response.json()
file_ids.append(result["file_id"])
print(f"✓ Uploaded: {result['filename']}")
# Step 2: Wait for processing (typically 30-60 seconds)
print("\n⏳ Processing files...")
time.sleep(45)
# Step 3: Retrieve user profile
print("\n📊 Fetching user profile...")
profile_response = requests.get(
f"{BASE_URL}/metadata/get_user_profile/",
headers={"X-API-Key": api_token},
timeout=30
)
profile = profile_response.json()
print("\n✨ Profile Summary:")
for category, data in profile.items():
if data:
print(f"\n{category.upper()}:")
for key, values in data.items():
if isinstance(values, list):
print(f" • {key}: {', '.join(values)}")
else:
print(f" • {key}: {values}")
# Step 4: Retrieve recent events
print("\n📅 Fetching recent events...")
events_response = requests.get(
f"{BASE_URL}/metadata/get_user_event/?limit=10",
headers={"X-API-Key": api_token},
timeout=30
)
events_data = events_response.json()
print(f"\n📍 Found {events_data['total_count']} events:")
for event in events_data["events"]:
time_str = event["happen_time"] or event["mention_time"]
print(f" • [{event['event_type']}] {event['content'][:80]}...")
print(f" Time: {time_str}")const apiToken = "<API_TOKEN>";
const BASE_URL = "https://api.synvo.ai";
async function profileWorkflow() {
// Step 1: Upload files (using File Upload API)
console.log("📤 Uploading user documents...");
const filesToUpload = [resumeFile, transcriptFile, portfolioFile]; // File objects
const fileIds = [];
for (const file of filesToUpload) {
const formData = new FormData();
formData.append("file", file);
const response = await fetch(`${BASE_URL}/file/upload`, {
method: "POST",
headers: { "X-API-Key": apiToken },
body: formData
});
const result = await response.json();
fileIds.push(result.file_id);
console.log(`✓ Uploaded: ${result.filename}`);
}
// Step 2: Wait for processing (typically 30-60 seconds)
console.log("\n⏳ Processing files...");
await new Promise(resolve => setTimeout(resolve, 45000));
// Step 3: Retrieve user profile
console.log("\n📊 Fetching user profile...");
const profileResponse = await fetch(
`${BASE_URL}/metadata/get_user_profile/`,
{
headers: { "X-API-Key": apiToken }
}
);
const profile = await profileResponse.json();
console.log("\n✨ Profile Summary:");
for (const [category, data] of Object.entries(profile)) {
if (data && Object.keys(data).length > 0) {
console.log(`\n${category.toUpperCase()}:`);
for (const [key, values] of Object.entries(data)) {
if (Array.isArray(values)) {
console.log(` • ${key}: ${values.join(", ")}`);
} else {
console.log(` • ${key}: ${values}`);
}
}
}
}
// Step 4: Retrieve recent events
console.log("\n📅 Fetching recent events...");
const eventsResponse = await fetch(
`${BASE_URL}/metadata/get_user_event/?limit=10`,
{
headers: { "X-API-Key": apiToken }
}
);
const eventsData = await eventsResponse.json();
console.log(`\n📍 Found ${eventsData.total_count} events:`);
for (const event of eventsData.events) {
const timeStr = event.happen_time || event.mention_time;
console.log(` • [${event.event_type}] ${event.content.substring(0, 80)}...`);
console.log(` Time: ${timeStr}`);
}
}
// Execute workflow
profileWorkflow();Best Practices
Profile Building
- Multiple Files: Upload diverse file types for comprehensive profiles
- Processing Time: Allow 30-60 seconds for profile extraction
- Regular Updates: Re-upload updated documents to keep profiles current
Event Tracking
- Time Windows: Use
start_timeandend_timefor specific periods - Pagination: Use
limitparameter to control response size - Event Types: Filter by
event_typein your application logic
Sub-Users
- Isolation: Each sub-user has completely separate profile and events
- Naming: Use consistent sub-user names across your application
- Default: Omitting
sub_user_nameuses the default profile
Error Handling
All endpoints return standard HTTP status codes. Error responses include a JSON object with error details:
{
"error": "Error description",
"detail": "Additional context about the error"
}Common error codes:
200- Success: Request completed successfully400- Bad Request: Invalid parameters or malformed request401- Unauthorized: Missing or invalid authentication404- Not Found: User or resource does not exist429- Too Many Requests: Rate limit exceeded500- Internal Server Error: Server-side error