Quick Reference
const MEETERGO_API = 'https://api.meetergo.com/v4';
const API_KEY = process.env.MEETERGO_API_KEY;
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};
// Add user ID header for most requests
function withUser(userId) {
return { ...headers, 'x-meetergo-api-user-id': userId };
}
import os
import requests
MEETERGO_API = 'https://api.meetergo.com/v4'
API_KEY = os.environ['MEETERGO_API_KEY']
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
def with_user(user_id):
return {**headers, 'x-meetergo-api-user-id': user_id}
<?php
$MEETERGO_API = 'https://api.meetergo.com/v4';
$API_KEY = getenv('MEETERGO_API_KEY');
$headers = [
'Authorization: Bearer ' . $API_KEY,
'Content-Type: application/json'
];
function withUser($userId) {
global $headers;
return array_merge($headers, ['x-meetergo-api-user-id: ' . $userId]);
}
package main
import (
"net/http"
"os"
)
const meetergoAPI = "https://api.meetergo.com/v4"
var apiKey = os.Getenv("MEETERGO_API_KEY")
func newRequest(method, path string) *http.Request {
req, _ := http.NewRequest(method, meetergoAPI+path, nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
return req
}
Authentication
Verify API Key
async function verifyApiKey() {
const response = await fetch(`${MEETERGO_API}/user/me`, { headers });
if (!response.ok) {
throw new Error(`API key invalid: ${response.status}`);
}
return response.json();
}
// Usage
const user = await verifyApiKey();
console.log('Authenticated as:', user.email);
def verify_api_key():
response = requests.get(f'{MEETERGO_API}/user/me', headers=headers)
response.raise_for_status()
return response.json()
# Usage
user = verify_api_key()
print(f'Authenticated as: {user["email"]}')
function verifyApiKey() {
global $MEETERGO_API, $headers;
$ch = curl_init("$MEETERGO_API/user/me");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("API key invalid: $httpCode");
}
return json_decode($response, true);
}
Users
Create User
async function createUser({ email, firstName, lastName, timezone = 'Europe/Berlin' }) {
const response = await fetch(`${MEETERGO_API}/user`, {
method: 'POST',
headers,
body: JSON.stringify({
email,
givenName: firstName,
familyName: lastName,
timezone
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to create user: ${error.message}`);
}
return response.json();
}
// Usage
const user = await createUser({
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe'
});
console.log('Created user:', user.userId);
console.log('Booking URL:', user.bookingUrl);
def create_user(email, first_name, last_name, timezone='Europe/Berlin'):
response = requests.post(
f'{MEETERGO_API}/user',
headers=headers,
json={
'email': email,
'givenName': first_name,
'familyName': last_name,
'timezone': timezone
}
)
response.raise_for_status()
return response.json()
# Usage
user = create_user('john@example.com', 'John', 'Doe')
print(f'Created user: {user["userId"]}')
print(f'Booking URL: {user["bookingUrl"]}')
function createUser($email, $firstName, $lastName, $timezone = 'Europe/Berlin') {
global $MEETERGO_API, $headers;
$data = json_encode([
'email' => $email,
'givenName' => $firstName,
'familyName' => $lastName,
'timezone' => $timezone
]);
$ch = curl_init("$MEETERGO_API/user");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
Availability
Get Available Slots
async function getAvailableSlots(meetingTypeId, startDate, endDate, userId) {
const params = new URLSearchParams({
meetingTypeId,
start: startDate,
end: endDate
});
const response = await fetch(
`${MEETERGO_API}/booking-availability?${params}`,
{ headers: withUser(userId) }
);
const data = await response.json();
return data.dates?.flatMap(d => d.spots) || [];
}
// Usage
const slots = await getAvailableSlots(
'meeting-type-id',
'2024-01-15',
'2024-01-22',
'user-id'
);
slots.forEach(slot => {
console.log(`Available: ${new Date(slot.startTime).toLocaleString()}`);
});
def get_available_slots(meeting_type_id, start_date, end_date, user_id):
response = requests.get(
f'{MEETERGO_API}/booking-availability',
headers=with_user(user_id),
params={
'meetingTypeId': meeting_type_id,
'start': start_date,
'end': end_date
}
)
response.raise_for_status()
data = response.json()
dates = data.get('dates', [])
return [spot for d in dates for spot in d.get('spots', [])]
# Usage
from datetime import datetime, timedelta
today = datetime.now().strftime('%Y-%m-%d')
next_week = (datetime.now() + timedelta(days=7)).strftime('%Y-%m-%d')
slots = get_available_slots('meeting-type-id', today, next_week, 'user-id')
for slot in slots:
print(f'Available: {slot["startTime"]}')
function getAvailableSlots($meetingTypeId, $startDate, $endDate, $userId) {
global $MEETERGO_API;
$params = http_build_query([
'meetingTypeId' => $meetingTypeId,
'start' => $startDate,
'end' => $endDate
]);
$ch = curl_init("$MEETERGO_API/booking-availability?$params");
curl_setopt($ch, CURLOPT_HTTPHEADER, withUser($userId));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
$spots = [];
foreach ($data['dates'] ?? [] as $date) {
$spots = array_merge($spots, $date['spots'] ?? []);
}
return $spots;
}
Bookings
Create Booking
async function createBooking({
meetingTypeId,
start,
attendee,
userId
}) {
const response = await fetch(`${MEETERGO_API}/booking`, {
method: 'POST',
headers: withUser(userId),
body: JSON.stringify({
meetingTypeId,
start,
attendee: {
email: attendee.email,
fullname: attendee.name,
phone: attendee.phone
}
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Booking failed: ${error.message}`);
}
return response.json();
}
// Usage
const booking = await createBooking({
meetingTypeId: 'meeting-type-id',
start: '2024-01-16T10:00:00Z',
attendee: {
email: 'client@example.com',
name: 'Jane Client',
phone: '+1234567890'
},
userId: 'user-id'
});
console.log('Booking confirmed:', booking.id);
console.log('Meeting link:', booking.meetingLink);
def create_booking(meeting_type_id, start, attendee, user_id):
response = requests.post(
f'{MEETERGO_API}/booking',
headers=with_user(user_id),
json={
'meetingTypeId': meeting_type_id,
'start': start,
'attendee': {
'email': attendee['email'],
'fullname': attendee['name'],
'phone': attendee.get('phone')
}
}
)
response.raise_for_status()
return response.json()
# Usage
booking = create_booking(
meeting_type_id='meeting-type-id',
start='2024-01-16T10:00:00Z',
attendee={
'email': 'client@example.com',
'name': 'Jane Client',
'phone': '+1234567890'
},
user_id='user-id'
)
print(f'Booking confirmed: {booking["id"]}')
function createBooking($meetingTypeId, $start, $attendee, $userId) {
global $MEETERGO_API;
$data = json_encode([
'meetingTypeId' => $meetingTypeId,
'start' => $start,
'attendee' => [
'email' => $attendee['email'],
'fullname' => $attendee['name'],
'phone' => $attendee['phone'] ?? null
]
]);
$ch = curl_init("$MEETERGO_API/booking");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, withUser($userId));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
Cancel Booking
async function cancelBooking(appointmentId, userId, reason = null) {
const response = await fetch(`${MEETERGO_API}/appointment/${appointmentId}/cancel`, {
method: 'POST',
headers: { ...withUser(userId), 'Content-Type': 'application/json' },
body: reason ? JSON.stringify({ reason }) : undefined
});
if (!response.ok) {
throw new Error(`Cancel failed: ${response.status}`);
}
return true;
}
// Usage
await cancelBooking('appointment-id', 'user-id', 'Customer requested');
def cancel_booking(appointment_id, user_id, reason=None):
data = None
if reason:
data = {'reason': reason}
response = requests.post(
f'{MEETERGO_API}/appointment/{appointment_id}/cancel',
headers=with_user(user_id),
json=data
)
response.raise_for_status()
return True
# Usage
cancel_booking('appointment-id', 'user-id', 'Customer requested')
Webhooks
Webhook Handler (Express.js)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhooks/meetergo', async (req, res) => {
// Respond immediately
res.status(200).send('OK');
const payload = req.body;
try {
switch (payload.webhookType) {
case 'booking_created':
console.log('New booking:', payload.id);
// Add to CRM, send notifications, etc.
break;
case 'booking_cancelled':
console.log('Booking cancelled:', payload.id);
// Update records, process refunds, etc.
break;
case 'booking_rescheduled':
console.log('Booking rescheduled:', payload.rescheduledAppointment.id);
// Update calendar, notify team, etc.
break;
}
} catch (error) {
console.error('Webhook processing failed:', error);
}
});
app.listen(3000);
Webhook Handler (Python/Flask)
from flask import Flask, request, jsonify
import threading
app = Flask(__name__)
def process_webhook(payload):
webhook_type = payload.get('webhookType')
if webhook_type == 'booking_created':
print(f'New booking: {payload["id"]}')
elif webhook_type == 'booking_cancelled':
print(f'Booking cancelled: {payload["id"]}')
elif webhook_type == 'booking_rescheduled':
print(f'Booking rescheduled: {payload["rescheduledAppointment"]["id"]}')
@app.route('/webhooks/meetergo', methods=['POST'])
def webhook():
payload = request.json
# Process in background thread
thread = threading.Thread(target=process_webhook, args=(payload,))
thread.start()
return jsonify({'status': 'ok'}), 200
if __name__ == '__main__':
app.run(port=3000)
Complete Example: Booking Flow
Full example of checking availability and creating a booking:class MeetergoClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.meetergo.com/v4';
}
async request(method, path, userId = null, body = null) {
const headers = {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
};
if (userId) {
headers['x-meetergo-api-user-id'] = userId;
}
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers,
body: body ? JSON.stringify(body) : undefined
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.message || `HTTP ${response.status}`);
}
return response.json();
}
async getAvailability(meetingTypeId, startDate, endDate, userId) {
const params = new URLSearchParams({
meetingTypeId,
start: startDate,
end: endDate
});
return this.request('GET', `/booking-availability?${params}`, userId);
}
async createBooking(meetingTypeId, start, attendee, userId) {
return this.request('POST', '/booking', userId, {
meetingTypeId,
start,
attendee
});
}
}
// Usage
async function bookAppointment() {
const client = new MeetergoClient(process.env.MEETERGO_API_KEY);
const meetingTypeId = 'your-meeting-type-id';
const userId = 'your-user-id';
// 1. Get available slots
const today = new Date().toISOString().split('T')[0];
const nextWeek = new Date(Date.now() + 7 * 86400000).toISOString().split('T')[0];
const availability = await client.getAvailability(
meetingTypeId,
today,
nextWeek,
userId
);
const allSlots = availability.dates?.flatMap(d => d.spots) || [];
if (!allSlots.length) {
throw new Error('No available slots');
}
// 2. Book the first available slot
const slot = allSlots[0];
const booking = await client.createBooking(
meetingTypeId,
slot.startTime,
{
email: 'client@example.com',
fullname: 'Client Name',
phone: '+1234567890'
},
userId
);
console.log('Booked!', booking);
return booking;
}
bookAppointment().catch(console.error);
import os
import requests
from datetime import datetime, timedelta
class MeetergoClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://api.meetergo.com/v4'
def request(self, method, path, user_id=None, json=None, params=None):
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
if user_id:
headers['x-meetergo-api-user-id'] = user_id
response = requests.request(
method,
f'{self.base_url}{path}',
headers=headers,
json=json,
params=params
)
response.raise_for_status()
return response.json()
def get_availability(self, meeting_type_id, start_date, end_date, user_id):
return self.request('GET', '/booking-availability', user_id, params={
'meetingTypeId': meeting_type_id,
'start': start_date,
'end': end_date
})
def create_booking(self, meeting_type_id, start, attendee, user_id):
return self.request('POST', '/booking', user_id, json={
'meetingTypeId': meeting_type_id,
'start': start,
'attendee': attendee
})
def book_appointment():
client = MeetergoClient(os.environ['MEETERGO_API_KEY'])
meeting_type_id = 'your-meeting-type-id'
user_id = 'your-user-id'
# 1. Get available slots
today = datetime.now().strftime('%Y-%m-%d')
next_week = (datetime.now() + timedelta(days=7)).strftime('%Y-%m-%d')
availability = client.get_availability(
meeting_type_id,
today,
next_week,
user_id
)
dates = availability.get('dates', [])
all_slots = [spot for d in dates for spot in d.get('spots', [])]
if not all_slots:
raise Exception('No available slots')
# 2. Book the first available slot
slot = all_slots[0]
booking = client.create_booking(
meeting_type_id,
slot['startTime'],
{
'email': 'client@example.com',
'fullname': 'Client Name',
'phone': '+1234567890'
},
user_id
)
print('Booked!', booking)
return booking
if __name__ == '__main__':
book_appointment()
Next Steps
API Reference
Full API documentation
Troubleshooting
Common issues and solutions