API Documentation
Complete guide to the Roster & Calendar API
Authentication
All API requests require authentication using an API key. Include your API key in the request header (recommended) or as a query parameter.
Header Method (Recommended)
const response = await fetch('https://rosterly.quickstopsolution.com/api/events?start=2026-01-01&end=2026-01-31', {
headers: {
'X-API-Key': 'your-api-key-here'
}
});
$ch = curl_init('https://rosterly.quickstopsolution.com/api/events?start=2026-01-01&end=2026-01-31');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Query Parameter Method
GET https://rosterly.quickstopsolution.com/api/events?start=2026-01-01&end=2026-01-31&api_key=your-api-key-here
Rate Limits
API requests are limited to 10 requests per minute per API key. Rate limit information is included in response headers:
X-RateLimit-Limit- Maximum requests allowedX-RateLimit-Remaining- Remaining requests in current windowX-RateLimit-Reset- When the rate limit resets
If you exceed the rate limit, you'll receive a 429 Too Many Requests response.
Caching
All GET requests are cached using ETag and Last-Modified headers. To validate your cache, include these headers in your request:
If-None-Match- ETag from previous responseIf-Modified-Since- Last-Modified date from previous response
If the data hasn't changed, you'll receive a 304 Not Modified response with no body,
saving bandwidth.
Date & Time
Event timestamps are stored in the database as UTC (YYYY-MM-DD HH:MM:SS
with no offset). API responses return those same UTC values in start_datetime and
end_datetime.
Sending dates (create / update)
When you POST or PUT an event, the server accepts ISO 8601 strings. How a value is interpreted depends on whether you include a timezone:
| Format | Example | Interpretation |
|---|---|---|
| With timezone offset | 2024-01-15T09:00:00+08:00, 2024-01-15T01:00:00Z |
Converted to UTC for storage |
| Without timezone (naive) | 2024-01-15 09:00:00, 2024-01-15T09:00:00 |
Treated as wall-clock time in the server APP_TIMEZONE (default:
Asia/Kuala_Lumpur, UTC+8) |
For example, 2024-01-15T09:00:00 without an offset means 9:00 AM Malaysia
time and is stored as 2024-01-15 01:00:00 UTC.
Recommended: always include an explicit offset (Z or
+08:00) so there is no ambiguity.
Events Endpoints
/api/events
List calendar events. Requires start and end date parameters.
Required Parameters:
start- Start date (YYYY-MM-DD or YYYY-MM-DD HH:MM:SS)end- End date (YYYY-MM-DD or YYYY-MM-DD HH:MM:SS)
Optional Parameters:
event_type_id- Filter by event typestaff_id- Filter events where this staff member is an attendee
const response = await fetch('https://rosterly.quickstopsolution.com/api/events?start=2026-01-01&end=2026-01-31&event_type_id=1&staff_id=5', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/events?start=2026-01-01&end=2026-01-31&event_type_id=1&staff_id=5`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/events?start=2026-01-01&end=2026-01-31&event_type_id=1&staff_id=5');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/events
Create a new calendar event. Descriptions support Markdown and the
API returns a sanitized description_html field for rendering.
Required Body Fields:
title- Event titlestart_datetime- Start date/time. ISO 8601 with offset recommended; naive values useAPP_TIMEZONE(see Date & Time)end_datetime- End date/time. Same format rules asstart_datetime
Optional Body Fields:
description- Markdown description source. Raw HTML is escaped; pasted<pre>blocks are normalized into code blocks.location- Event locationevent_type_id- Event type IDis_all_day- Boolean (true/false)attendees- Array of staff/user IDs
const response = await fetch('https://rosterly.quickstopsolution.com/api/events', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Team Meeting',
description: 'REPORTING FOR CASE/VISIT/MEETING BY STAFF
DATE/TIME: 20/05/2026 (21:00 - 22:00)
',
start_datetime: '2026-01-15 10:00:00',
end_datetime: '2026-01-15 11:00:00',
event_type_id: 1,
attendees: [1, 2, 3]
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/events`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Team Meeting',
description: 'REPORTING FOR CASE/VISIT/MEETING BY STAFF
DATE/TIME: 20/05/2026 (21:00 - 22:00)
',
start_datetime: '2026-01-15 10:00:00',
end_datetime: '2026-01-15 11:00:00',
event_type_id: 1,
attendees: [1, 2, 3]
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'title' => 'Team Meeting',
'description' => "REPORTING FOR CASE/VISIT/MEETING BY STAFF
DATE/TIME: 20/05/2026 (21:00 - 22:00)
",
'start_datetime' => '2026-01-15 10:00:00',
'end_datetime' => '2026-01-15 11:00:00',
'event_type_id' => 1,
'attendees' => [1, 2, 3]
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/events');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
/api/events/:id
Get a single event by ID.
const response = await fetch('https://rosterly.quickstopsolution.com/api/events/123', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/events/123`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/events/123');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/events/:id
Update an existing event. Only include fields you want to update.
const response = await fetch('https://rosterly.quickstopsolution.com/api/events/123', {
method: 'PUT',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Updated Team Meeting',
description: 'UPDATED HANDOVER
VENUE: Confirmed
STAFF: Assigned
'
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/events/123`, {
method: 'PUT',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Updated Team Meeting',
description: 'UPDATED HANDOVER
VENUE: Confirmed
STAFF: Assigned
'
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'title' => 'Updated Team Meeting',
'description' => "UPDATED HANDOVER
VENUE: Confirmed
STAFF: Assigned
"
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/events/123');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
/api/events/:id
Delete an event.
const response = await fetch('https://rosterly.quickstopsolution.com/api/events/123', {
method: 'DELETE',
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/events/123`, {
method: 'DELETE',
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/events/123');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
Public Holidays Endpoints
/api/public-holidays?year=YYYY
List all public holidays. You can optionally filter by
year.
Optional Parameters:
year- Filter holidays by year (e.g., 2026)
const response = await fetch('https://rosterly.quickstopsolution.com/api/public-holidays?year=2026', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/public-holidays?year=2026`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/public-holidays?year=2026');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/public-holidays/:id
Get a single public holiday by ID.
const response = await fetch('https://rosterly.quickstopsolution.com/api/public-holidays/10', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/public-holidays/10`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/public-holidays/10');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/public-holidays
Create a new public holiday.
Required Body Fields:
title- Holiday namestart_date- Start date (YYYY-MM-DD)end_date- End date (YYYY-MM-DD)
Optional Body Fields:
is_custom- Boolean (true/false), default false
const response = await fetch('https://rosterly.quickstopsolution.com/api/public-holidays', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Company Day',
start_date: '2026-11-15',
end_date: '2026-11-15',
is_custom: true
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/public-holidays`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Company Day',
start_date: '2026-11-15',
end_date: '2026-11-15',
is_custom: true
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'title' => 'Company Day',
'start_date' => '2026-11-15',
'end_date' => '2026-11-15',
'is_custom' => true
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/public-holidays');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
/api/public-holidays/:id
Update an existing public holiday. Send one or more updatable fields.
Updatable Body Fields:
title- Holiday namestart_date- Start date (YYYY-MM-DD)end_date- End date (YYYY-MM-DD)is_custom- Boolean (true/false)
const response = await fetch('https://rosterly.quickstopsolution.com/api/public-holidays/10', {
method: 'PUT',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Updated Company Day',
end_date: '2026-11-16'
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/public-holidays/10`, {
method: 'PUT',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Updated Company Day',
end_date: '2026-11-16'
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'title' => 'Updated Company Day',
'end_date' => '2026-11-16'
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/public-holidays/10');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
/api/public-holidays/:id
Delete a public holiday.
const response = await fetch('https://rosterly.quickstopsolution.com/api/public-holidays/10', {
method: 'DELETE',
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/public-holidays/10`, {
method: 'DELETE',
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/public-holidays/10');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
Rosters Endpoints
/api/rosters?start=YYYY-MM-DD&end=YYYY-MM-DD
List rosters. Requires start and end date parameters.
Required Parameters:
start- Start date (YYYY-MM-DD)end- End date (YYYY-MM-DD)
Optional Parameters:
roster_type_id- Filter by roster typestaff_id- Filter rosters where this staff member has entries
const response = await fetch('https://rosterly.quickstopsolution.com/api/rosters?start=2026-01-01&end=2026-12-31&roster_type_id=1&staff_id=5', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/rosters?start=2026-01-01&end=2026-12-31&roster_type_id=1&staff_id=5`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/rosters?start=2026-01-01&end=2026-12-31&roster_type_id=1&staff_id=5');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/rosters
Create a new roster.
Required Body Fields:
name- Roster nameroster_type_id- Roster type IDyear- Year (e.g., 2026)month- Month (1-12)
const response = await fetch('https://rosterly.quickstopsolution.com/api/rosters', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'January 2026 Roster',
roster_type_id: 1,
year: 2026,
month: 1,
notes: 'Monthly roster'
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/rosters`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'January 2026 Roster',
roster_type_id: 1,
year: 2026,
month: 1,
notes: 'Monthly roster'
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'name' => 'January 2026 Roster',
'roster_type_id' => 1,
'year' => 2026,
'month' => 1,
'notes' => 'Monthly roster'
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/rosters');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
/api/rosters/:id?staff_id=X
Get a roster with entries. If staff_id is provided,
returns shifts grouped by date for that staff member.
const response = await fetch('https://rosterly.quickstopsolution.com/api/rosters/123?staff_id=5', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/rosters/123?staff_id=5`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/rosters/123?staff_id=5');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/rosters/:id/entries
Add or update a roster entry.
Required Body Fields:
staff_id- Staff/user IDentry_date- Date (YYYY-MM-DD)
Optional Body Fields:
shift_id- Shift IDnotes- Notes
const response = await fetch('https://rosterly.quickstopsolution.com/api/rosters/123/entries', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
staff_id: 5,
entry_date: '2026-01-15',
shift_id: 1,
notes: 'Morning shift'
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/rosters/123/entries`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
staff_id: 5,
entry_date: '2026-01-15',
shift_id: 1,
notes: 'Morning shift'
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'staff_id' => 5,
'entry_date' => '2026-01-15',
'shift_id' => 1,
'notes' => 'Morning shift'
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/rosters/123/entries');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
Users Endpoints
/api/users
List all active users (staff members).
const response = await fetch('https://rosterly.quickstopsolution.com/api/users', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/users`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/users');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/users
Create a new user (staff member).
Required Body Fields:
username- Username (unique)email- Email address (unique)password- Password (will be hashed)full_name- Full name
Optional Body Fields:
designation- Job title/designationphone- Phone number
const response = await fetch('https://rosterly.quickstopsolution.com/api/users', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'johndoe',
email: 'john@example.com',
password: 'securepassword123',
full_name: 'John Doe',
designation: 'Developer',
phone: '+1234567890'
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/users`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'johndoe',
email: 'john@example.com',
password: 'securepassword123',
full_name: 'John Doe',
designation: 'Developer',
phone: '+1234567890'
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'username' => 'johndoe',
'email' => 'john@example.com',
'password' => 'securepassword123',
'full_name' => 'John Doe',
'designation' => 'Developer',
'phone' => '+1234567890'
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/users');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
Types Endpoints
/api/event-types
List all active event types. Creating and editing event types is only available in Settings to admins.
const response = await fetch('https://rosterly.quickstopsolution.com/api/event-types', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/event-types`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/event-types');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/event-types
Not available via the API. Admins create event types in Settings.
Required Body Fields:
name- Event type name (must be unique)
Optional Body Fields:
color- Hex color code (default: #0A9396)icon- Icon name
const response = await fetch('https://rosterly.quickstopsolution.com/api/event-types', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Workshop',
color: '#FF5733',
icon: 'calendar'
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/event-types`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Workshop',
color: '#FF5733',
icon: 'calendar'
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'name' => 'Workshop',
'color' => '#FF5733',
'icon' => 'calendar'
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/event-types');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
/api/event-types/:id
Not available via the API. Admins edit event types in Settings.
Optional Body Fields:
name- Event type namecolor- Hex color codeicon- Icon namedescription- Descriptionis_active- Boolean active state
const response = await fetch('https://rosterly.quickstopsolution.com/api/event-types/5', {
method: 'PUT',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Updated Workshop',
color: '#FF5733',
icon: 'calendar',
description: 'Updated event type description',
is_active: true
})
});
const data = await response.json();
/api/event-types/:id
Not available via the API. Admins delete event types in Settings.
const response = await fetch('https://rosterly.quickstopsolution.com/api/event-types/5', {
method: 'DELETE',
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
/api/roster-types
List all active roster types. Creating and editing roster types is only available in Settings to admins.
const response = await fetch('https://rosterly.quickstopsolution.com/api/roster-types', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/roster-types`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/roster-types');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
/api/roster-types
Not available via the API. Admins create roster types in Settings.
Required Body Fields:
name- Roster type name (must be unique)
Optional Body Fields:
color- Hex color code (default: #0A9396)description- Descriptionschedule_pattern- Schedule patterncustom_days- Custom days array
const response = await fetch('https://rosterly.quickstopsolution.com/api/roster-types', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Weekly Roster',
color: '#0A9396',
description: 'Weekly staff roster',
schedule_pattern: 'weekdays',
custom_days: ['mon', 'tue', 'wed', 'thu', 'fri']
})
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/roster-types`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Weekly Roster',
color: '#0A9396',
description: 'Weekly staff roster',
schedule_pattern: 'weekdays',
custom_days: ['mon', 'tue', 'wed', 'thu', 'fri']
})
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$data = [
'name' => 'Weekly Roster',
'color' => '#0A9396',
'description' => 'Weekly staff roster',
'schedule_pattern' => 'weekdays',
'custom_days' => ['mon', 'tue', 'wed', 'thu', 'fri']
];
$ch = curl_init('https://rosterly.quickstopsolution.com/api/roster-types');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-api-key-here',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
/api/roster-types/:id
Not available via the API. Admins edit roster types in Settings.
Optional Body Fields:
name- Roster type namecolor- Hex color codedescription- Descriptionschedule_pattern- Schedule patterncustom_days- Custom days arrayis_active- Boolean active state
const response = await fetch('https://rosterly.quickstopsolution.com/api/roster-types/3', {
method: 'PUT',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Updated Weekly Roster',
color: '#0A9396',
description: 'Updated weekly staff roster',
schedule_pattern: 'custom',
custom_days: ['mon', 'wed', 'fri'],
is_active: true
})
});
const data = await response.json();
/api/roster-types/:id
Not available via the API. Admins delete roster types in Settings.
const response = await fetch('https://rosterly.quickstopsolution.com/api/roster-types/3', {
method: 'DELETE',
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
/api/shifts
List all active shifts. Creating and editing staff shifts is only available in Settings to admins.
const response = await fetch('https://rosterly.quickstopsolution.com/api/shifts', {
headers: { 'X-API-Key': 'your-api-key-here' }
});
const data = await response.json();
// .env
// API_BASE_URL=https://rosterly.quickstopsolution.com/api
// API_KEY=your-api-key-here
const baseUrl = process.env.API_BASE_URL;
const apiKey = process.env.API_KEY;
async function main() {
const response = await fetch(`${baseUrl}/shifts`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
console.log('status', response.status);
console.log(data);
}
main().catch(console.error);
$ch = curl_init('https://rosterly.quickstopsolution.com/api/shifts');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: your-api-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
Permissions
API keys can have specific permissions to control access. Common permissions include:
events:read- Read calendar eventsevents:write- Create/update/delete eventsrosters:read- Read rostersrosters:write- Create/update rostersusers:read- Read usersusers:write- Create userstypes:read- Read typestypes:write- Create/update/delete types and public holidaysall- Full access to all endpoints
If an API key doesn't have the required permission, you'll receive a 403 Forbidden
response.