Calendar Integration Instructions for Division Agents

Copy and paste these instructions to Grade Level Up, Guided Aim, and other division AI agents

📋 COPY THIS ENTIRE SECTION TO DIVISION AGENT
═══════════════════════════════════════════════════════════════════════════
SPHEREUS CALENDAR & BOOKING API INTEGRATION
For Grade Level Up, Guided Aim, and Other Division Agents
═══════════════════════════════════════════════════════════════════════════

OVERVIEW:
---------
The SphereUs Network provides a unified calendar and booking system. Tutors, 
coaches, and service providers manage their availability on SphereUs.com. 
Your division can book appointments via API.

BASE URL: https://sphereus.com/functions/

AUTHENTICATION:
--------------
All API calls require the user's SphereUs auth token in the Authorization header:
Authorization: Bearer {user_token}

Use the existing SSO flow to get the user's token.


═══════════════════════════════════════════════════════════════════════════
API ENDPOINT 1: GET AVAILABLE SLOTS
═══════════════════════════════════════════════════════════════════════════

URL: POST https://sphereus.com/functions/getAvailableSlots

PURPOSE: Check when a provider (tutor/coach) is available on a specific date.

REQUEST BODY:
{
  "user_id": "provider_user_id",
  "service_listing_id": "optional_service_id", 
  "date": "2025-01-15"
}

RESPONSE:
{
  "date": "2025-01-15T00:00:00.000Z",
  "day_of_week": 3,
  "available_slots": [
    {
      "start": "2025-01-15T14:00:00.000Z",
      "end": "2025-01-15T15:00:00.000Z",
      "display": "2:00 PM"
    }
  ],
  "total_slots": 2
}

EXAMPLE CODE:
const response = await fetch('https://sphereus.com/functions/getAvailableSlots', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${userToken}`
  },
  body: JSON.stringify({
    user_id: providerId,
    date: '2025-01-15'
  })
});
const { available_slots } = await response.json();


═══════════════════════════════════════════════════════════════════════════
API ENDPOINT 2: CREATE BOOKING (WITH CONFLICT CHECK)
═══════════════════════════════════════════════════════════════════════════

URL: POST https://sphereus.com/functions/createBookingWithConflictCheck

PURPOSE: Book a time slot. Automatically checks for conflicts and creates 
engagement records for SU Coin tracking.

REQUEST BODY:
{
  "service_listing_id": "service_id",
  "provider_email": "tutor@example.com",
  "booking_date": "2025-01-15T14:00:00.000Z",
  "total_amount": 50,
  "payment_method": "su_coins",
  "notes": "Need help with algebra",
  "location": "Virtual - Zoom"
}

SUCCESS RESPONSE (200):
{
  "success": true,
  "booking": {
    "id": "booking_id",
    "service_listing_id": "...",
    "provider_email": "tutor@example.com",
    "customer_email": "student@example.com",
    "booking_date": "2025-01-15T14:00:00.000Z",
    "status": "pending",
    "payment_status": "pending",
    "total_amount": 50
  },
  "message": "Booking created successfully"
}

CONFLICT RESPONSE (409):
{
  "error": "Time slot conflict",
  "message": "This time slot is no longer available. Please choose another time."
}

EXAMPLE CODE:
const response = await fetch('https://sphereus.com/functions/createBookingWithConflictCheck', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${userToken}`
  },
  body: JSON.stringify({
    service_listing_id: serviceId,
    provider_email: 'tutor@example.com',
    booking_date: '2025-01-15T14:00:00.000Z',
    total_amount: 50,
    payment_method: 'su_coins',
    notes: 'Algebra help needed'
  })
});

if (response.status === 409) {
  alert('Time slot no longer available');
} else {
  const { booking } = await response.json();
  // Success - show confirmation
}


═══════════════════════════════════════════════════════════════════════════
API ENDPOINT 3: GET USER'S BOOKINGS
═══════════════════════════════════════════════════════════════════════════

URL: GET https://sphereus.com/functions/getUserBookings

PURPOSE: Retrieve all bookings for a user (as customer or provider) across 
all divisions.

QUERY PARAMETERS (Optional):
?user_email=user@example.com&include_past=true

If no params provided, uses authenticated user's data.

RESPONSE:
{
  "bookings": [
    {
      "id": "...",
      "service_name": "Algebra Tutoring",
      "service_category": "tutoring",
      "booking_date": "2025-01-15T14:00:00.000Z",
      "status": "confirmed",
      "role": "customer",
      "is_past": false,
      "provider_email": "tutor@example.com",
      "customer_email": "student@example.com"
    }
  ],
  "total": 5,
  "as_customer": 3,
  "as_provider": 2,
  "upcoming": 4,
  "past": 1
}

EXAMPLE CODE:
const response = await fetch('https://sphereus.com/functions/getUserBookings', {
  headers: {
    'Authorization': `Bearer ${userToken}`
  }
});
const { bookings, upcoming } = await response.json();


═══════════════════════════════════════════════════════════════════════════
API ENDPOINT 4: CHECK PROVIDER AVAILABILITY (OPTIONAL)
═══════════════════════════════════════════════════════════════════════════

URL: POST https://sphereus.com/functions/checkProviderAvailability

PURPOSE: Get provider's complete weekly schedule, exceptions, and bookings.

REQUEST BODY:
{
  "provider_email": "tutor@example.com",
  "start_date": "2025-01-01",
  "end_date": "2025-01-31"
}

RESPONSE:
{
  "provider_email": "tutor@example.com",
  "provider_name": "Jane Smith",
  "weekly_schedule": {
    "1": [{"start_time": "09:00", "end_time": "17:00"}],
    "2": [{"start_time": "09:00", "end_time": "17:00"}]
  },
  "exceptions": [
    {"date": "2025-01-20", "notes": "Holiday"}
  ],
  "upcoming_bookings": [...],
  "total_bookings": 5,
  "is_available": true
}


═══════════════════════════════════════════════════════════════════════════
TYPICAL INTEGRATION FLOW
═══════════════════════════════════════════════════════════════════════════

1. User selects a tutor/coach on your division site
   → Display provider profile from your local database

2. User picks a date
   → Call getAvailableSlots to show open time slots

3. User selects a time slot
   → Call createBookingWithConflictCheck

4. Handle response:
   → 200: Show success confirmation
   → 409: Show "slot unavailable" message and refresh slots

5. User views their bookings
   → Call getUserBookings to show upcoming sessions


═══════════════════════════════════════════════════════════════════════════
IMPORTANT NOTES
═══════════════════════════════════════════════════════════════════════════

✓ Authentication: All calls require user's SphereUs auth token
✓ Conflict Detection: API prevents double-booking automatically
✓ Engagement Tracking: Bookings create engagement records for SU Coins
✓ Cross-Division: All bookings visible across divisions
✓ Error Handling: Always handle 409 conflicts gracefully

QUESTIONS? Contact the SphereUs development team or refer to:
https://sphereus.com/calendarapiguide

═══════════════════════════════════════════════════════════════════════════
END OF INSTRUCTIONS
═══════════════════════════════════════════════════════════════════════════
1️⃣ Get Available Slots Code
// GET AVAILABLE SLOTS
const response = await fetch('https://sphereus.com/functions/getAvailableSlots', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${userToken}`
  },
  body: JSON.stringify({
    user_id: providerId,
    date: '2025-01-15'  // ISO date string
  })
});

const data = await response.json();
const availableSlots = data.available_slots;

// Display slots to user
availableSlots.forEach(slot => {
  console.log(slot.display); // "2:00 PM"
  console.log(slot.start);   // "2025-01-15T14:00:00.000Z"
});
2️⃣ Create Booking Code
// CREATE BOOKING WITH CONFLICT CHECK
const response = await fetch('https://sphereus.com/functions/createBookingWithConflictCheck', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${userToken}`
  },
  body: JSON.stringify({
    service_listing_id: serviceId,
    provider_email: 'tutor@example.com',
    booking_date: '2025-01-15T14:00:00.000Z',  // ISO datetime
    total_amount: 50,
    payment_method: 'su_coins',  // or 'stripe', 'cash'
    notes: 'Need help with algebra',
    location: 'Virtual - Zoom'
  })
});

if (response.status === 409) {
  // Conflict - slot no longer available
  alert('This time slot is no longer available. Please choose another time.');
  // Refresh available slots
} else if (response.ok) {
  const { booking } = await response.json();
  // Success! Show confirmation
  console.log('Booking created:', booking.id);
} else {
  // Other error
  const error = await response.json();
  alert('Error creating booking: ' + error.message);
}
3️⃣ Get User Bookings Code
// GET USER'S BOOKINGS
const response = await fetch('https://sphereus.com/functions/getUserBookings', {
  headers: {
    'Authorization': `Bearer ${userToken}`
  }
});

const data = await response.json();

console.log('Total bookings:', data.total);
console.log('As customer:', data.as_customer);
console.log('As provider:', data.as_provider);
console.log('Upcoming:', data.upcoming);

// Display bookings
data.bookings.forEach(booking => {
  console.log(booking.service_name);
  console.log(booking.booking_date);
  console.log(booking.role); // 'customer' or 'provider'
  console.log(booking.status);
});