The Klear Karma API provides comprehensive access to our digital wellness platform, enabling developers to build applications that connect users with holistic health practitioners. Our API follows RESTful principles and GraphQL standards, ensuring consistency, reliability, and ease of integration.
Production: https://api.klearkarma.com/v1
Staging: https://api-staging.klearkarma.com/v1
Development: https://api-dev.klearkarma.com/v1
GraphQL Endpoint: https://api.klearkarma.com/graphql
WebSocket: wss://ws.klearkarma.com
We use URL-based versioning to ensure backward compatibility:
Klear Karma uses OAuth 2.0 with PKCE (Proof Key for Code Exchange) for secure authentication.
Step 1: Authorization Request
GET https://auth.klearkarma.com/oauth/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=YOUR_REDIRECT_URI& scope=read:profile write:bookings& state=RANDOM_STATE& code_challenge=CODE_CHALLENGE& code_challenge_method=S256
Step 2: Token Exchange
POST https://auth.klearkarma.com/oauth/token Content-Type: application/json { "grant_type": "authorization_code", "client_id": "YOUR_CLIENT_ID", "code": "AUTHORIZATION_CODE", "redirect_uri": "YOUR_REDIRECT_URI", "code_verifier": "CODE_VERIFIER" }
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read:profile write:bookings"
}
Header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id"
}
Payload:
{
"sub": "user-id",
"iss": "https://auth.klearkarma.com",
"aud": "https://api.klearkarma.com",
"exp": 1640995200,
"iat": 1640991600,
"scope": "read:profile write:bookings",
"user_type": "patient",
"verified": true
}
For server-to-server communication, use API keys:
Authorization: Bearer YOUR_API_KEY
| Scope | Description |
|---|---|
read:profile | Read user profile information |
write:profile | Update user profile information |
read:bookings | Read user's booking information |
write:bookings | Create and modify bookings |
read:practitioners | Access practitioner directory |
write:practitioners | Update practitioner information (practitioners only) |
read:messages | Read messages and communications |
write:messages | Send messages and communications |
read:health_records | Access health records (with consent) |
write:health_records | Update health records |
admin:users | Administrative access to user management |
admin:platform | Full platform administrative access |
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json Accept: application/json User-Agent: YourApp/1.0.0 X-Request-ID: unique-request-id
Request Body (JSON):
{
"data": {
"attribute1": "value1",
"attribute2": "value2"
},
"meta": {
"client_version": "1.0.0",
"platform": "web"
}
}
Success Response:
{
"data": {
"id": "resource-id",
"type": "resource-type",
"attributes": {
"name": "Resource Name",
"created_at": "2024-01-01T00:00:00Z"
},
"relationships": {
"related_resource": {
"data": {
"id": "related-id",
"type": "related-type"
}
}
}
},
"meta": {
"request_id": "req-123",
"timestamp": "2024-01-01T00:00:00Z",
"version": "1.0.0"
}
}
Error Response:
{
"errors": [
{
"id": "error-id",
"status": "400",
"code": "VALIDATION_ERROR",
"title": "Validation Error",
"detail": "The email field is required",
"source": {
"pointer": "/data/attributes/email"
}
}
],
"meta": {
"request_id": "req-123",
"timestamp": "2024-01-01T00:00:00Z"
}
}
POST https://api.klearkarma.com/graphql
User Type
type User {
id: ID!
email: String!
firstName: String!
lastName: String!
dateOfBirth: Date
phoneNumber: String
address: Address
preferences: UserPreferences!
healthProfile: HealthProfile
bookings(first: Int, after: String): BookingConnection!
messages(first: Int, after: String): MessageConnection!
createdAt: DateTime!
updatedAt: DateTime!
}
type UserPreferences {
language: String!
timezone: String!
notifications: NotificationSettings!
privacy: PrivacySettings!
}
type HealthProfile {
conditions: [String!]!
allergies: [String!]!
medications: [String!]!
goals: [String!]!
emergencyContact: EmergencyContact
}
Practitioner Type
type Practitioner {
id: ID!
user: User!
specializations: [Specialization!]!
credentials: [Credential!]!
bio: String!
experience: Int!
languages: [String!]!
availability: Availability!
pricing: PricingInfo!
reviews(first: Int, after: String): ReviewConnection!
rating: Float!
totalSessions: Int!
responseTime: Int!
verified: Boolean!
createdAt: DateTime!
updatedAt: DateTime!
}
type Specialization {
id: ID!
name: String!
category: String!
description: String
}
type Credential {
id: ID!
type: String!
institution: String!
year: Int!
verified: Boolean!
}
Booking Type
type Booking {
id: ID!
user: User!
practitioner: Practitioner!
service: Service!
scheduledAt: DateTime!
duration: Int!
status: BookingStatus!
type: SessionType!
location: Location
notes: String
price: Money!
paymentStatus: PaymentStatus!
cancellationPolicy: CancellationPolicy!
createdAt: DateTime!
updatedAt: DateTime!
}
enum BookingStatus {
PENDING
CONFIRMED
IN_PROGRESS
COMPLETED
CANCELLED
NO_SHOW
}
enum SessionType {
VIDEO_CALL
PHONE_CALL
IN_PERSON
CHAT
}
Get User Profile
query GetUserProfile($userId: ID!) {
user(id: $userId) {
id
firstName
lastName
email
healthProfile {
conditions
goals
}
preferences {
language
timezone
}
}
}
Search Practitioners
query SearchPractitioners(
$specialization: String
$location: LocationInput
$availability: AvailabilityInput
$first: Int
$after: String
) {
practitioners(
filter: {
specialization: $specialization
location: $location
availability: $availability
}
first: $first
after: $after
) {
edges {
node {
id
user {
firstName
lastName
}
specializations {
name
category
}
rating
pricing {
basePrice
currency
}
availability {
nextAvailable
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Create Booking
mutation CreateBooking($input: CreateBookingInput!) {
createBooking(input: $input) {
booking {
id
scheduledAt
practitioner {
user {
firstName
lastName
}
}
service {
name
duration
}
price {
amount
currency
}
status
}
errors {
field
message
}
}
}
Real-time Booking Updates
subscription BookingUpdates($userId: ID!) {
bookingUpdates(userId: $userId) {
id
status
scheduledAt
practitioner {
user {
firstName
lastName
}
}
}
}
Live Chat Messages
subscription ChatMessages($conversationId: ID!) {
messageAdded(conversationId: $conversationId) {
id
content
sender {
id
firstName
}
timestamp
type
}
}
GET /users/{user_id}
Response:
{
"data": {
"id": "user_123",
"type": "user",
"attributes": {
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-01-01",
"phone_number": "+1234567890",
"verified": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
},
"relationships": {
"health_profile": {
"data": {
"id": "health_123",
"type": "health_profile"
}
}
}
}
}
PUT /users/{user_id} Content-Type: application/json { "data": { "type": "user", "attributes": { "first_name": "John", "last_name": "Smith", "phone_number": "+1234567890" } } }
GET /users/{user_id}/preferences
Response:
{
"data": {
"id": "pref_123",
"type": "user_preferences",
"attributes": {
"language": "en",
"timezone": "America/New_York",
"notifications": {
"email": true,
"sms": false,
"push": true
},
"privacy": {
"profile_visibility": "public",
"show_online_status": true
}
}
}
}
GET /practitioners?specialization=yoga&location=New+York&available_from=2024-01-01T09:00:00Z&limit=20&offset=0
Query Parameters:
specialization (string): Filter by specializationlocation (string): Geographic locationavailable_from (datetime): Earliest availabilityavailable_to (datetime): Latest availabilityrating_min (float): Minimum ratingprice_max (integer): Maximum price per sessionlanguage (string): Practitioner languagesession_type (string): video_call, phone_call, in_person, chatlimit (integer): Number of results (max 100)offset (integer): Pagination offsetResponse:
{
"data": [
{
"id": "prac_123",
"type": "practitioner",
"attributes": {
"first_name": "Jane",
"last_name": "Smith",
"bio": "Certified yoga instructor with 10 years of experience",
"specializations": ["Hatha Yoga", "Meditation"],
"rating": 4.8,
"total_sessions": 1250,
"response_time": 120,
"languages": ["English", "Spanish"],
"verified": true
},
"relationships": {
"availability": {
"data": {
"id": "avail_123",
"type": "availability"
}
}
}
}
],
"meta": {
"total_count": 150,
"page": 1,
"per_page": 20,
"total_pages": 8
}
}
GET /practitioners/{practitioner_id}
GET /practitioners/{practitioner_id}/availability?from=2024-01-01&to=2024-01-07
Response:
{
"data": {
"id": "avail_123",
"type": "availability",
"attributes": {
"timezone": "America/New_York",
"slots": [
{
"start_time": "2024-01-01T09:00:00Z",
"end_time": "2024-01-01T10:00:00Z",
"available": true,
"price": {
"amount": 75,
"currency": "USD"
}
}
]
}
}
}
POST /bookings Content-Type: application/json { "data": { "type": "booking", "attributes": { "practitioner_id": "prac_123", "service_id": "service_123", "scheduled_at": "2024-01-01T10:00:00Z", "duration": 60, "session_type": "video_call", "notes": "First session, interested in stress management" } } }
Response:
{
"data": {
"id": "booking_123",
"type": "booking",
"attributes": {
"scheduled_at": "2024-01-01T10:00:00Z",
"duration": 60,
"status": "pending",
"session_type": "video_call",
"price": {
"amount": 75,
"currency": "USD"
},
"payment_status": "pending",
"created_at": "2024-01-01T00:00:00Z"
},
"relationships": {
"practitioner": {
"data": {
"id": "prac_123",
"type": "practitioner"
}
}
}
}
}
GET /users/{user_id}/bookings?status=confirmed&from=2024-01-01&to=2024-12-31
PUT /bookings/{booking_id}
DELETE /bookings/{booking_id}
POST /payments/intents Content-Type: application/json { "data": { "type": "payment_intent", "attributes": { "booking_id": "booking_123", "amount": 7500, "currency": "USD", "payment_method_types": ["card", "apple_pay", "google_pay"] } } }
POST /payments/intents/{intent_id}/confirm
GET /users/{user_id}/payments
GET /users/{user_id}/conversations
POST /conversations/{conversation_id}/messages Content-Type: application/json { "data": { "type": "message", "attributes": { "content": "Hello, I'm looking forward to our session tomorrow.", "message_type": "text" } } }
POST /conversations/{conversation_id}/files Content-Type: multipart/form-data file=@document.pdf&message=Here's the health report we discussed
GET /users/{user_id}/health_profile
PUT /users/{user_id}/health_profile
POST /health_records/share Content-Type: application/json { "data": { "type": "health_record_share", "attributes": { "practitioner_id": "prac_123", "record_types": ["conditions", "medications"], "expires_at": "2024-12-31T23:59:59Z" } } }
const ws = new WebSocket('wss://ws.klearkarma.com');
// Authentication
ws.onopen = function() {
ws.send(JSON.stringify({
type: 'auth',
token: 'your_jwt_token'
}));
};
{
"type": "subscribe",
"channel": "bookings",
"user_id": "user_123"
}
{
"type": "message",
"conversation_id": "conv_123",
"content": "Hello!",
"message_type": "text"
}
{
"type": "typing",
"conversation_id": "conv_123",
"is_typing": true
}
{
"type": "webrtc_signal",
"booking_id": "booking_123",
"signal_type": "offer",
"signal_data": {
"sdp": "...",
"type": "offer"
}
}
Webhooks can be configured in the developer dashboard or via API:
POST /webhooks Content-Type: application/json { "data": { "type": "webhook", "attributes": { "url": "https://your-app.com/webhooks/klearkarma", "events": ["booking.created", "booking.confirmed", "payment.completed"], "secret": "your_webhook_secret" } } }
booking.created - New booking createdbooking.confirmed - Booking confirmed by practitionerbooking.cancelled - Booking cancelledbooking.completed - Session completedbooking.no_show - No-show recordedpayment.completed - Payment successfully processedpayment.failed - Payment failedpayment.refunded - Refund processeduser.created - New user registereduser.verified - User email/phone verifieduser.updated - User profile updated{
"id": "evt_123",
"type": "booking.created",
"created_at": "2024-01-01T00:00:00Z",
"data": {
"id": "booking_123",
"type": "booking",
"attributes": {
"scheduled_at": "2024-01-01T10:00:00Z",
"status": "pending",
"user_id": "user_123",
"practitioner_id": "prac_123"
}
}
}
Signature Verification:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
| Code | Description |
|---|---|
| 200 | OK - Request successful |
| 201 | Created - Resource created successfully |
| 204 | No Content - Request successful, no content returned |
| 400 | Bad Request - Invalid request format or parameters |
| 401 | Unauthorized - Authentication required or invalid |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource not found |
| 409 | Conflict - Resource conflict (e.g., duplicate booking) |
| 422 | Unprocessable Entity - Validation errors |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Server error |
| 502 | Bad Gateway - Upstream service error |
| 503 | Service Unavailable - Service temporarily unavailable |
{
"errors": [
{
"id": "error_123",
"status": "422",
"code": "VALIDATION_ERROR",
"title": "Validation Error",
"detail": "The email field must be a valid email address",
"source": {
"pointer": "/data/attributes/email",
"parameter": "email"
},
"meta": {
"field": "email",
"validation_rule": "email"
}
}
],
"meta": {
"request_id": "req_123",
"timestamp": "2024-01-01T00:00:00Z",
"documentation_url": "https://docs.klearkarma.com/errors/validation"
}
}
| Code | Description |
|---|---|
VALIDATION_ERROR | Request validation failed |
AUTHENTICATION_REQUIRED | Authentication token required |
INVALID_TOKEN | Authentication token invalid or expired |
INSUFFICIENT_PERMISSIONS | User lacks required permissions |
RESOURCE_NOT_FOUND | Requested resource not found |
RESOURCE_CONFLICT | Resource already exists or conflicts |
RATE_LIMIT_EXCEEDED | API rate limit exceeded |
PAYMENT_REQUIRED | Payment required to access resource |
SERVICE_UNAVAILABLE | Service temporarily unavailable |
BOOKING_CONFLICT | Booking time slot unavailable |
PRACTITIONER_UNAVAILABLE | Practitioner not available |
INVALID_BOOKING_STATUS | Invalid booking status transition |
All API responses include rate limiting headers:
X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1640995200 X-RateLimit-Window: 3600
| Tier | Requests per Hour | Burst Limit |
|---|---|---|
| Free | 1,000 | 100 |
| Basic | 10,000 | 500 |
| Pro | 100,000 | 2,000 |
| Enterprise | Custom | Custom |
Per-User Limits:
Per-IP Limits:
Endpoint-Specific Limits:
Installation:
npm install @klearkarma/sdk
Usage:
import { KlearKarmaClient } from '@klearkarma/sdk';
const client = new KlearKarmaClient({
apiKey: 'your_api_key',
environment: 'production' // or 'staging', 'development'
});
// Search practitioners
const practitioners = await client.practitioners.search({
specialization: 'yoga',
location: 'New York',
availableFrom: new Date()
});
// Create booking
const booking = await client.bookings.create({
practitionerId: 'prac_123',
scheduledAt: new Date('2024-01-01T10:00:00Z'),
duration: 60,
sessionType: 'video_call'
});
Installation:
pip install klearkarma-sdk
Usage:
from klearkarma import KlearKarmaClient
client = KlearKarmaClient(
api_key='your_api_key',
environment='production'
)
# Search practitioners
practitioners = client.practitioners.search(
specialization='yoga',
location='New York'
)
# Create booking
booking = client.bookings.create(
practitioner_id='prac_123',
scheduled_at='2024-01-01T10:00:00Z',
duration=60,
session_type='video_call'
)
import { useKlearKarma, usePractitioners, useBookings } from '@klearkarma/react';
function PractitionerSearch() {
const { data: practitioners, loading, error } = usePractitioners({
specialization: 'yoga',
location: 'New York'
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
{practitioners.map(practitioner => (
<PractitionerCard key={practitioner.id} practitioner={practitioner} />
))}
</div>
);
}
klearkarma-ruby (community maintained)klearkarma-php (community maintained)klearkarma-go (community maintained)klearkarma-java (community maintained)Base URL: https://api-sandbox.klearkarma.com/v1
Features:
Test Users:
{
"test_user_1": {
"email": "test.user@klearkarma.com",
"password": "TestPassword123!",
"user_id": "test_user_123"
},
"test_practitioner_1": {
"email": "test.practitioner@klearkarma.com",
"password": "TestPassword123!",
"practitioner_id": "test_prac_123"
}
}
Test Payment Methods:
{
"success_card": "4242424242424242",
"decline_card": "4000000000000002",
"insufficient_funds": "4000000000009995"
}
Postman Collection:
curl -o klearkarma-api.postman_collection.json \ https://docs.klearkarma.com/postman/collection.json
OpenAPI Specification:
curl -o klearkarma-openapi.yaml \ https://api.klearkarma.com/openapi.yaml
Webhook Testing:
# Install ngrok for local webhook testing
npm install -g ngrok
# Expose local server
ngrok http 3000
# Configure webhook URL
curl -X POST https://api-sandbox.klearkarma.com/v1/webhooks \
-H "Authorization: Bearer your_api_key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "webhook",
"attributes": {
"url": "https://your-ngrok-url.ngrok.io/webhooks",
"events": ["booking.created"]
}
}
}'
Added:
Changed:
Fixed:
Added:
Changed:
Fixed:
Initial Release:
klearkarma-apiThis documentation is updated regularly. For the latest information, visit https://docs.klearkarma.com
© 2024 Klear Karma. All rights reserved.