Psyter Shared API (Tahoon API)

Overview

The Psyter Shared API (also known as Tahoon API) is a .NET 8.0 Web API that serves as a shared integration layer for external organizations partnering with the Psyter platform. This API enables third-party healthcare organizations to integrate with Psyter’s telemedicine services, allowing them to:

  • Register their patients/users within the Psyter ecosystem
  • Search and filter care providers based on various criteria
  • View provider availability and schedules
  • Book therapy sessions on behalf of their users
  • Manage session bookings (view, cancel)

Unlike the main Psyter API (which serves the core platform), the Tahoon API is specifically designed for B2B integrations where external organizations can offer Psyter’s mental health services to their own user base while maintaining their own UI/UX.

Key Characteristics:
- Authentication: OAuth 2.0 with JWT bearer tokens
- Multi-tenant: Supports multiple organizations with isolated data
- Security-focused: Hash validation, XSS protection, encrypted IDs
- Integration-ready: RESTful API with Swagger documentation


Architecture

Technology Stack

Component Technology Version
Framework .NET / ASP.NET Core 8.0
Language C# Latest
Authentication JWT Bearer Tokens 8.0.18
API Documentation Swagger / Swashbuckle 6.6.2
Database Access ADO.NET (SqlClient) 4.9.0
External Services Firebase Cloud Messaging v1
Serialization Newtonsoft.Json 13.0.3
Video SDK VideoSDK.live -

Architecture Pattern

Repository Pattern with Service Layer

Controllers
    ↓
Repositories (IRepository interfaces)
    ↓
BaseRepository (Database access)
    ↓
SQL Server (PsyterDatabase, SchedulingDatabase)

Helper Services:
- SecurityHelper - Encryption, hashing, ID obfuscation
- VideoSDKHelper - Video meeting room creation
- FCMNotificationHelper - Push notifications
- XmlHelper - XML serialization for legacy stored procedures


Project Structure

PsyterSharedAPI/
├── Controllers/              # API endpoint controllers
│   ├── AuthController.cs           # Token generation
│   ├── UserController.cs           # User registration & assessment
│   ├── CareProviderController.cs   # Provider listing & schedules
│   ├── SessionBookingController.cs # Booking & cancellation
│   └── SecurityController.cs       # Security utilities
├── Data/
│   ├── Model/                # Request/Response DTOs
│   │   ├── AuthRequest.cs
│   │   ├── UserRequest.cs
│   │   ├── CareProviderRequest.cs
│   │   ├── SessionBooking.cs
│   │   ├── Enumeration.cs
│   │   └── ...
│   └── Repositories/         # Data access layer
│       ├── Interfaces/
│       ├── BaseRepository.cs
│       ├── AuthRepository.cs
│       ├── UserRepository.cs
│       ├── CareProviderRepository.cs
│       ├── SchedulingRepository.cs
│       ├── SessionBookingRepository.cs
│       └── CommonRepository.cs
├── Helpers/                  # Business logic helpers
│   ├── SecurityHelper.cs          # Encryption/decryption
│   ├── VideoSDKHelper.cs          # Video SDK integration
│   ├── FCMNotificationHelper.cs   # Push notifications
│   └── XmlHelper.cs               # XML utilities
├── ActionFilters/            # Request validation
│   ├── ValidateSecureHashFilter.cs   # Hash validation
│   ├── AntiXssValidationFilter.cs    # XSS prevention
│   ├── ModelBinderToDecryptValue.cs  # ID decryption
│   └── SwaggerActionFilter.cs        # Swagger auth filter
├── Extensions/
│   └── DataRowExtensions.cs       # DataRow to object mapping
├── appsettings.json          # Configuration
├── Program.cs                # Application startup
└── PsyterSharedAPI.csproj    # Project file

Key Features

1. Multi-Tenant Authentication

  • Organizations receive a unique ApplicationToken (API Key)
  • OAuth 2.0 token endpoint (/api/auth/token)
  • JWT tokens valid for 24 hours
  • Token contains OrganizationId and SharedAPIKey claims

2. User Management

  • User Registration: Register organization users with encrypted data
  • Assessment Questionnaires: Mental health screening questions
  • User Validation: Ensure users belong to requesting organization

3. Care Provider Discovery

  • Advanced Filtering: By gender, language, specialty, experience, etc.
  • Real-time Availability: Schedule integration with hourly/slot-based availability
  • Profile Data: Provider credentials, bio, ratings, languages
  • Catalogue Data: Filter options (specialties, languages, experience levels)

4. Session Booking

  • Book Sessions: Create appointments with automatic slot validation
  • Cancel Bookings: Cancellation with refund handling
  • Video Meeting Creation: Auto-generate VideoSDK meeting rooms
  • Notifications: FCM push notifications to providers
  • Charity Organization Support: Free/subsidized sessions for partner orgs

5. Security Features

  • Encrypted IDs: All sensitive IDs encrypted in transit
  • Hash Validation: Request integrity verification using HMAC-SHA256
  • Anti-XSS: Input validation against XSS attacks
  • Encrypted Connection Strings: Database credentials encrypted in config
  • Custom Model Binding: Automatic ID decryption

Getting Started

Prerequisites

  • .NET 8.0 SDK or later
  • SQL Server (two databases: PsyterDatabase, SchedulingDatabase)
  • Firebase project (for push notifications)
  • VideoSDK account (for video meetings)
  • IIS or Azure App Service (for deployment)

Installation

  1. Clone the repository:

    git clone <repository-url>
    cd Tahoon_API/PsyterSharedAPI
    

  2. Restore NuGet packages:

    dotnet restore
    

  3. Configure appsettings.json:

Update the following sections:

{
  "ConnectionStrings": {
    "PsyterDatabase": "<encrypted-connection-string>",
    "SchedulingDatabase": "<encrypted-connection-string>"
  },
  "Jwt": {
    "Key": "your-secret-key",
    "Issuer": "psyter.com",
    "Audience": "psyter_client"
  },
  "SecuritySettings": {
    "AESKey": "<base64-aes-key>",
    "AESIV": "<base64-aes-iv>",
    "PassPhrase": "<encryption-passphrase>",
    "Salt": "<salt-value>",
    "Vector": "<vector-value>"
  }
}
  1. Add Firebase credentials:

Place firebase-adminsdk-live.json in the project root.

  1. Build the project:

    dotnet build --configuration Release
    

  2. Run the application:

    dotnet run
    

Or in production:

dotnet publish -c Release

Database Setup

The API requires two SQL Server databases:

  1. PsyterDatabase - Main application database
    - User accounts and profiles
    - Care provider information
    - Booking orders and payments
    - Organization data

  2. SchedulingDatabase - Scheduling system
    - Provider availability
    - Hourly schedules
    - Slot bookings
    - Booking status tracking

Note: Stored procedures are required. Contact the development team for database schema and stored procedure scripts.


Configuration

Connection Strings

Connection strings are encrypted in appsettings.json. To encrypt a connection string:

  1. Use the SecurityHelper.EncryptString() method
  2. Encrypt these components separately:
    - Data Source
    - Initial Catalog
    - User Id
    - Password

Example plaintext format before encryption:

Data Source=server.database.windows.net;Initial Catalog=PsyterDB;User Id=admin;Password=pass123;

Security Settings

{
  "SecuritySettings": {
    "AESKey": "base64-encoded-32-byte-key",
    "AESIV": "base64-encoded-16-byte-iv",
    "PassPhrase": "UUID-style-passphrase",
    "Salt": "16-character-salt",
    "Vector": "16-character-vector",
    "EncryptionPassword": "Password*1"
  }
}

JWT Configuration

{
  "Jwt": {
    "Key": "unique-secret-key-min-32-chars",
    "Issuer": "psyter.com",
    "Audience": "psyter_client"
  }
}

API Endpoints

Authentication

POST /api/auth/token

Get an OAuth 2.0 bearer token for API access.

Request (form-data):

grant_type=password
access_key=<organization-api-key>

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 86400
}


User Management

POST /api/user/register

Register a new user under the organization.

Headers:
- Authorization: Bearer <token>

Request:

{
  "referenceId": "ORG-USER-12345",
  "name": "John Doe",
  "dob": "1990-05-15",
  "genderType": 1,
  "secureHash": "<hmac-sha256-hash>"
}

Response:

{
  "status": 1,
  "message": "Success",
  "reason": 2,
  "data": {
    "userLoginInfoId": "<encrypted-user-id>"
  }
}

GET /api/user/getassessmentquestions

Retrieve mental health screening questions.

Response:

{
  "status": 1,
  "data": {
    "screeningQuestions": [...]
  }
}

POST /api/user/submituserassessmentquestions

Submit user assessment answers.


Care Provider Discovery

POST /api/careprovider/getcareproviderslistwithschedule

Search care providers with optional filtering and availability.

Request:

{
  "userId": "<encrypted-user-id>",
  "scheduleDate": "2025-11-15",
  "gmtTimeDiffrenceHours": 3,
  "applyFilter": true,
  "filterCriteriaObject": {
    "genderType": 0,
    "languageIds": [1, 2],
    "specialtyIds": [3],
    "experienceLevel": 2
  }
}

Response:

{
  "status": 1,
  "data": {
    "careProvidersList": [
      {
        "userLoginInfoId": 123,
        "fullName": "Dr. Sarah Ahmed",
        "genderType": 0,
        "availableScheduleHoursList": [...],
        "availableSlotsList": [...]
      }
    ]
  }
}

POST /api/careprovider/getcareproviderschedule

Get detailed schedule for a specific provider.

POST /api/careprovider/getcareprovidersprofiledata

Get full profile information for a care provider.

GET /api/careprovider/getcataloguedataforfilters

Get filter options (specialties, languages, etc.).


Session Booking

POST /api/sessionbooking/booksession

Book a therapy session.

Request:

{
  "userId": "<encrypted-user-id>",
  "careProviderId": "<encrypted-provider-id>",
  "slotDate": "2025-11-15",
  "slotStartTime": "10:00:00",
  "slotEndTime": "11:00:00",
  "applicationMultiSlotId": "<encrypted-service-id>",
  "catCommunicationTypeId": 1,
  "isBookingFromMobile": false,
  "bookingPlatformId": 3,
  "secureHash": "<hmac-sha256-hash>"
}

Response:

{
  "status": 1,
  "message": "Success",
  "data": {
    "meetingId": "abcd-1234-efgh-5678",
    "bookingId": "<encrypted-booking-id>"
  }
}

POST /api/sessionbooking/cancelbooking

Cancel a booked session.

Request:

{
  "bookingId": "<encrypted-booking-id>",
  "userId": "<encrypted-user-id>",
  "careProviderId": "<encrypted-provider-id>",
  "secureHash": "<hmac-sha256-hash>"
}


Security Implementation

Secure Hash Validation

For endpoints marked with [ValidateSecureHash], requests must include a secureHash field.

Hash Calculation:
1. Concatenate all properties marked with [IncludeInHash] attribute
2. Sort alphabetically by property name
3. Generate HMAC-SHA256 hash using SharedAPIKey from JWT token

Example (C# client):

public string GenerateSecureHash(object request, string sharedApiKey)
{
    var hashValues = GetIncludedHashValues(request);
    var data = string.Join("", hashValues.OrderBy(kv => kv.Key).Select(kv => kv.Value));

    using var hmac = new HMACSHA256(Convert.FromBase64String(sharedApiKey));
    var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
    return Convert.ToBase64String(hash);
}

ID Encryption

All sensitive IDs (user, provider, booking) are encrypted using AES-256:

Format: Base64URL(AES256-CBC(ID))

Decryption (automatic via model binding):
- Properties marked with [Encrypted] attribute
- Automatically decrypted to {PropertyName}_Decrypted field


Deployment

Azure DevOps Pipeline

The project includes an azure-pipelines.yml for CI/CD:

  1. Trigger: Push to master branch
  2. Build: .NET 8.0 build
  3. Publish: Creates deployment package
  4. Deploy: Extracts to IIS application pool psyter_tuhoon

Deployment Path: D:\ROOT\Development\Psyter\Master\TuhoonAPIs

IIS Configuration

  1. Create Application Pool: psyter_tuhoon
  2. Set .NET CLR Version: No Managed Code
  3. Set Application Path: /Psyter/Master/TuhoonAPIs
  4. Configure HTTPS bindings

Environment Configuration

  • Development: Uses appsettings.Development.json
  • Production: Uses appsettings.json

AppBasePath setting controls Swagger endpoint URL in production.


Error Handling

Response Format

All API responses follow this structure:

{
  "status": 0,           // 0 = error, 1 = success
  "message": "Description",
  "reason": 18,          // Enumeration.ResponseReason value
  "data": null
}

Common Error Codes

Reason Code Description
EmptyParameter 1 Missing required fields
UserNotFound 18 Invalid user ID
NotAllowed 16 Action not permitted
RecordAlreadyExist 4 Duplicate booking
CharityOrganizationBalanceOut 50 Insufficient balance

Testing

Swagger UI

Available at: https://<base-url>/swagger

Note: Swagger is enabled in both Development and Production (for integration testing).

Authentication in Swagger

  1. Click “Authorize” button
  2. Enter token: Bearer <your-jwt-token>
  3. All protected endpoints will include the token

Sample Workflow

  1. Get Token:

    POST /api/auth/token
    grant_type=password&access_key=your-api-key
    

  2. Register User:

    POST /api/user/register
    Authorization: Bearer <token>
    

  3. Search Providers:

    POST /api/careprovider/getcareproviderslistwithschedule
    

  4. Book Session:

    POST /api/sessionbooking/booksession
    


Integration Guide

Client Implementation Checklist

  • Obtain ApplicationToken from Psyter team
  • Implement token refresh (24-hour expiry)
  • Implement SecureHash generation
  • Handle encrypted ID formats
  • Store user mappings (ReferenceId ↔ Psyter UserLoginInfoId)
  • Implement error handling for all response reasons
  • Test booking workflow end-to-end
  • Implement FCM notification handling (optional)

Best Practices

  1. Token Management:
    - Cache JWT tokens (valid 24 hours)
    - Implement automatic refresh before expiry

  2. ID Handling:
    - Store encrypted IDs returned from API
    - Never decrypt IDs client-side (treat as opaque)

  3. Error Handling:
    - Check status field (0/1) in all responses
    - Use reason enum for specific error handling
    - Display user-friendly messages from message field

  4. User Registration:
    - Use unique referenceId for your users
    - Store mapping between your user ID and Psyter encrypted ID

  5. Booking Flow:
    - Always validate slot availability before booking
    - Handle RecordAlreadyExist (slot taken) gracefully
    - Store meetingId for video session access


Monitoring & Logging

Application Insights

(To be configured)

Log Locations

  • Development: Console output
  • Production: Windows Event Log / File system

Key Metrics to Monitor

  • Token generation success rate
  • Booking success/failure ratio
  • API response times
  • Database connection pool health
  • VideoSDK meeting creation success rate

Troubleshooting

Common Issues

1. 401 Unauthorized

  • Cause: Invalid or expired JWT token
  • Solution: Regenerate token using /api/auth/token

2. SecureHash Validation Failed

  • Cause: Incorrect hash calculation
  • Solution: Verify SharedAPIKey in JWT claims, ensure correct property ordering

3. Slot Not Available

  • Cause: Another user booked the slot
  • Solution: Refresh schedule and select another time

4. CharityOrganizationBalanceOut

  • Cause: Organization quota exhausted
  • Solution: Contact Psyter to increase quota

5. Connection String Decryption Error

  • Cause: Invalid encryption keys in SecuritySettings
  • Solution: Verify PassPhrase, Salt, Vector match encryption values

Dependencies

NuGet Packages

<PackageReference Include="Google.Apis.FirebaseCloudMessaging.v1" Version="1.70.0.3813" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.18" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.13.0" />

External Services

  • Firebase Cloud Messaging: Push notifications
  • VideoSDK.live: Video conferencing infrastructure
  • SQL Server: Data persistence


Support

For integration support:
- Email: dev@psyter.com
- Documentation: https://docs.psyter.com
- Issue Tracking: Internal JIRA


Changelog

Version 1.0.0 (Current)

  • .NET 8.0 migration
  • JWT authentication
  • OAuth 2.0 token endpoint
  • Multi-tenant support
  • VideoSDK integration
  • FCM notifications
  • Encrypted ID support
  • SecureHash validation

License

Proprietary - Psyter Platform