Skip to main content
GET
https://app.medisync.me
/
api
/
user
/
profile
Get User Profile
curl --request GET \
  --url https://app.medisync.me/api/user/profile \
  --header 'Authorization: <authorization>'
{
  "success": true,
  "data": {
    "name": "<string>",
    "email": "<string>",
    "firstName": "<string>",
    "lastName": "<string>",
    "title": "<string>",
    "specialty": "<string>",
    "ehr_system_type": "<string>",
    "ehr_system_name": "<string>",
    "isVerified": true,
    "subscriptionActive": true,
    "subscriptionExpiry": "<string>",
    "createdAt": "<string>",
    "updatedAt": "<string>"
  }
}

Overview

The user profile endpoint returns comprehensive information about the authenticated healthcare professional, including personal details, medical credentials, and account status.

Authentication

Authorization
string
required
Bearer token obtained from login
Authorization: Bearer YOUR_JWT_TOKEN

Parameters

uid
string
required
User ID of the authenticated user (obtained from login response)

Example Request

curl -X GET "https://app.medisync.me/api/user/profile?uid=user_123456" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response

success
boolean
Indicates whether the request was successful
data
object
User profile information

Success Response

{
  "success": true,
  "data": {
    "name": "Dr. John Doe",
    "email": "[email protected]",
    "firstName": "John",
    "lastName": "Doe",
    "title": "Dr.",
    "specialty": "Cardiology",
    "ehr_system_type": "Epic",
    "ehr_system_name": "Epic MyChart",
    "isVerified": true,
    "subscriptionActive": true,
    "subscriptionExpiry": "2024-12-31T23:59:59.000Z",
    "createdAt": "2024-01-01T10:00:00.000Z",
    "updatedAt": "2024-01-15T14:30:00.000Z"
  }
}

Error Responses

{
  "success": false,
  "error": "Authentication required",
  "code": "AUTH_REQUIRED"
}

Usage Examples

Basic Profile Retrieval

class UserProfile {
  constructor(token, userId) {
    this.token = token;
    this.userId = userId;
    this.profile = null;
  }

  async fetchProfile() {
    try {
      const response = await fetch(
        `https://app.medisync.me/api/user/profile?uid=${this.userId}`,
        {
          headers: {
            'Authorization': `Bearer ${this.token}`
          }
        }
      );

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const data = await response.json();
      this.profile = data.data;
      return this.profile;

    } catch (error) {
      console.error('Error fetching profile:', error);
      throw error;
    }
  }

  getDisplayName() {
    return this.profile?.name || 'Unknown User';
  }

  isSubscriptionActive() {
    if (!this.profile) return false;
    
    return this.profile.subscriptionActive && 
           new Date(this.profile.subscriptionExpiry) > new Date();
  }

  isEmailVerified() {
    return this.profile?.isVerified || false;
  }

  getSubscriptionStatus() {
    if (!this.profile) return 'unknown';
    
    if (!this.profile.subscriptionActive) return 'inactive';
    
    const expiry = new Date(this.profile.subscriptionExpiry);
    const now = new Date();
    
    if (expiry <= now) return 'expired';
    
    const daysUntilExpiry = Math.ceil((expiry - now) / (1000 * 60 * 60 * 24));
    
    if (daysUntilExpiry <= 7) return 'expiring_soon';
    
    return 'active';
  }
}

// Usage
const userProfile = new UserProfile('your_jwt_token', 'user_123456');

try {
  const profile = await userProfile.fetchProfile();
  console.log('User:', userProfile.getDisplayName());
  console.log('Subscription:', userProfile.getSubscriptionStatus());
  console.log('Email verified:', userProfile.isEmailVerified());
} catch (error) {
  console.error('Failed to load profile:', error.message);
}

Profile-Based Feature Access

class FeatureAccessManager {
  constructor(userProfile) {
    this.profile = userProfile;
  }

  canCreateAppointments() {
    // Requires active subscription and verified email
    return this.profile.isVerified && 
           this.profile.subscriptionActive &&
           new Date(this.profile.subscriptionExpiry) > new Date();
  }

  canUseAIFeatures() {
    // Premium AI features require active subscription
    return this.canCreateAppointments();
  }

  canUploadRecordings() {
    // Basic recording upload requires verification
    return this.profile.isVerified;
  }

  getUploadLimits() {
    if (!this.profile.subscriptionActive) {
      return {
        maxFileSize: '50MB',
        maxFiles: 5,
        allowedFormats: ['wav', 'mp3']
      };
    }

    return {
      maxFileSize: '500MB',
      maxFiles: 100,
      allowedFormats: ['wav', 'mp3', 'm4a']
    };
  }

  getFeatureFlags() {
    return {
      appointments: this.canCreateAppointments(),
      aiNotes: this.canUseAIFeatures(),
      recordings: this.canUploadRecordings(),
      realTimeTranscription: this.canUseAIFeatures(),
      doctorLetters: this.canUseAIFeatures(),
      analytics: this.profile.subscriptionActive
    };
  }
}

// Usage with profile
const userProfile = new UserProfile('token', 'user_id');
await userProfile.fetchProfile();

const accessManager = new FeatureAccessManager(userProfile.profile);
const features = accessManager.getFeatureFlags();

console.log('Available features:', features);

if (!features.appointments) {
  console.log('Upgrade subscription to create appointments');
}

if (!features.aiNotes) {
  console.log('AI features require active subscription');
}

Profile Validation

Required Information Check

Essential Fields:
  • Name and medical title
  • Email address (verified)
  • Medical specialty
  • EHR system information
Validation Example:
function validateProfileCompleteness(profile) {
  const required = ['firstName', 'lastName', 'title', 'email', 'specialty'];
  const missing = required.filter(field => !profile[field]);
  
  return {
    isComplete: missing.length === 0 && profile.isVerified,
    missingFields: missing,
    needsVerification: !profile.isVerified
  };
}
Status Checks:
  • Email verification status
  • Subscription validity
  • Account creation date
  • Last activity timestamp
Implementation:
function getAccountStatus(profile) {
  const now = new Date();
  const expiry = new Date(profile.subscriptionExpiry);
  
  return {
    verified: profile.isVerified,
    subscriptionActive: profile.subscriptionActive && expiry > now,
    daysSinceCreation: Math.floor((now - new Date(profile.createdAt)) / (1000 * 60 * 60 * 24)),
    daysUntilExpiry: Math.ceil((expiry - now) / (1000 * 60 * 60 * 24))
  };
}

Error Handling

Common Issues and Solutions

Problem: 401 Unauthorized responsesCommon Causes:
  • Expired JWT token
  • Invalid token format
  • Missing Authorization header
Solution:
async function fetchProfileWithRetry(token, userId) {
  try {
    return await fetchProfile(token, userId);
  } catch (error) {
    if (error.status === 401) {
      // Token expired, need to re-authenticate
      const newToken = await refreshToken();
      return await fetchProfile(newToken, userId);
    }
    throw error;
  }
}
Problem: 403 Forbidden responsesCommon Causes:
  • Trying to access another user’s profile
  • Account not fully activated
  • Insufficient permissions
Solution:
  • Verify uid parameter matches authenticated user
  • Check account verification status
  • Ensure proper user context

Caching Considerations

Profile data changes infrequently and can be cached for 5-15 minutes to improve performance. Always refresh after profile updates or subscription changes.
class CachedUserProfile {
  constructor(token, userId, cacheDuration = 300000) { // 5 minutes
    this.token = token;
    this.userId = userId;
    this.cacheDuration = cacheDuration;
    this.cache = {
      data: null,
      timestamp: null
    };
  }

  async getProfile(forceRefresh = false) {
    const now = Date.now();
    
    // Return cached data if valid and not forcing refresh
    if (!forceRefresh && 
        this.cache.data && 
        this.cache.timestamp && 
        (now - this.cache.timestamp) < this.cacheDuration) {
      return this.cache.data;
    }

    // Fetch fresh data
    const response = await fetch(
      `https://app.medisync.me/api/user/profile?uid=${this.userId}`,
      {
        headers: {
          'Authorization': `Bearer ${this.token}`
        }
      }
    );

    if (!response.ok) {
      throw new Error(`Profile fetch failed: ${response.status}`);
    }

    const data = await response.json();
    
    // Update cache
    this.cache = {
      data: data.data,
      timestamp: now
    };

    return this.cache.data;
  }

  clearCache() {
    this.cache = { data: null, timestamp: null };
  }
}

Testing

Integration Testing

# Test successful profile retrieval
curl -X GET "https://app.medisync.me/api/user/profile?uid=user_123456" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -w "\nHTTP Status: %{http_code}\n"

# Test with invalid user ID
curl -X GET "https://app.medisync.me/api/user/profile?uid=invalid_user" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -w "\nHTTP Status: %{http_code}\n"

# Test without authentication
curl -X GET "https://app.medisync.me/api/user/profile?uid=user_123456" \
  -w "\nHTTP Status: %{http_code}\n"

Next Steps