How V1 and V2 Differ
This page explains what JS Vision changed, why the Scheduler API now exposes two paths, and how to know which one applies to your account.
The one-paragraph versionJS Vision changed how shifts are stored: a group shift with 3 users used to be 3 documents, now it's 1 base shift + 3 slots. To avoid breaking existing integrations, the API was split. V1 preserves the legacy "one object per user" shape and is always available. V2 exposes the new "one object per group" shape and is only available on Vision companies. Both run against the same data.
Why two versions exist
JS Vision changes how Connecteam stores shifts internally. A group shift with three users used to be three independent shift documents in the database. After Vision, it is one base shift + three lightweight slots — a single source of truth for the shared properties (title, time, location) and lightweight per-user pointers for the assignments.
That internal change has a visible API consequence: the "shape" of a group shift response can't be the same as before without breaking the legacy contract. To avoid silently breaking existing integrations when a company is migrated, the Scheduler API was split into two paths:
- V1 preserves the legacy shape: one shift object per user assignment, individual IDs per assignment. Integrations written before Vision keep working with zero code changes.
- V2 exposes the new shape: one shift object per base shift, with
assignedUserIdslisting every user on it. Recommended for new code.
Both versions are served by the same backend over the same data. The URL path you call controls the response shape and validation rules — your data is identical underneath.
URL path
The version is in the path, right after the feature prefix:
https://api.connecteam.com/scheduler/v1/schedulers/{schedulerId}/shifts
https://api.connecteam.com/scheduler/v2/schedulers/{schedulerId}/shifts
Everything else is identicalAuthentication (
X-API-KEYor OAuth 2.0), OAuth scopes (schedule.read,schedule.write,schedule.delete), path parameters, query parameters, and the request body schema are identical between V1 and V2. Only the version segment changes.
Am I migrated?
Send any request to the V2 path and inspect the result:
curl --request GET \
--url 'https://api.connecteam.com/scheduler/v2/schedulers/{schedulerId}/shifts?startTime=1736899200&endTime=1737504000' \
--header 'X-API-KEY: YOUR_API_KEY'The response tells you everything:
- ✅ A normal
200response (or404for a non-existent shift) → your company is on Vision. Both V1 and V2 are available. - 🚫 A
403with the body below → your company is not migrated yet.
{
"detail": "V2 endpoints require JS Vision migration. Contact support to migrate."
}
Non-migrated companies always get403Every V2 endpoint (
GET,POST,PUT,DELETE) returns403 Forbiddenfor non-Vision accounts. There is no opt-in flag in the API — contact Connecteam Support to be migrated.
TL;DR comparison
/scheduler/v1/... | /scheduler/v2/... | |
|---|---|---|
| Available on non-Vision companies | Yes | No — 403 |
| Group shift with 3 users in a response | 3 separate objects | 1 object, assignedUserIds: [a, b, c] |
| Shift ID format (Vision company) | Slot ID: 507f1f...:550e8400-... | Base ID: 507f1f77bcf86cd799439011 |
Multiple assignedUserIds on create / update | Rejected (max 1) | Allowed |
openSpots > 1 on create / update | Rejected | Allowed |
isEditForAllUsers: true | Rejected (400) | Allowed |
| Pagination unit | One row per user assignment | One row per base shift |
createdShifts / deletedShiftIds in PUT response | Always empty | Populated when users change |
When to choose V1 vs V2 on Vision
| Situation | Recommendation |
|---|---|
| Existing integration written before Vision | Stay on V1 — no code change required |
| New integration, single-user shifts only | Either works; V2 if you might add group shifts later |
| New integration with group shifts or multi-spot open shifts | V2 — multi-user assign and openSpots > 1 only work here |
| Need to edit a single user out of a group | V2 with isEditForAllUsers: false + assignedUserIds |
| Need to remove one user from a group without deleting it | V1 with that user's slot ID, OR V2 PUT with the remaining users |
| Need every shift property change to propagate to all group members by default | V2 — this is the default behavior on V2 |
You can use bothV1 and V2 are not mutually exclusive. Many integrations end up using V2 for new code while keeping V1 callers running unchanged. An ID returned by one path can be converted to the format the other expects — see Shift IDs and Response Shapes.
Updated about 19 hours ago
