TABLE OF CONTENTS
- Generic REST API Connector — Implementation Guide
- Contents
- 1. Introduction
- 2. Quick start
- 3. Glossary
- 4. Core concepts
- 5. Conventions
- 6. Authentication
- 7. Pagination
- 8. Status codes & error handling
- 9. Request & response envelopes
- 10. Endpoints
- 11. Data models
- 12. Enumerations
- 13. Dates & time
- 14. Performance & data volume
- 15. Testing your connector
- 16. Troubleshooting
- 17. Certification checklist
- 18. Registering your API in SchedEx
- Frequently asked questions
- Appendix A — A minimal end-to-end example
Generic REST API Connector — Implementation Guide
Build an API that SchedEx can connect to. Implement the endpoints and data shapes in this guide and SchedEx read schedule data from your system and write it back — with no custom integration on either side.
Audience: developers implementing the API on the external (host) system. You build: a set of HTTP endpoints. SchedEx provides: a connector that calls them.
Contents
- 1. Introduction
- 2. Quick start
- 3. Glossary
- 4. Core concepts
- 5. Conventions
- 6. Authentication
- 7. Pagination
- 8. Status codes & error handling
- 9. Request & response envelopes
- 10. Endpoints
- 11. Data models — Schedule (summary) · Schedule (detail) · Schedule (write) · Activity · Activity Link · Resource · Resource Availability · Resource Assignment · Calendar · Calendar Operation · Custom Host Field · Test Response
- 12. Enumerations — ActivityType · SuccessorType · ResourceUsageType · CalendarOperationType · DayOfWeek · Revision Type · PlanningObjectType · TypeCode
- 13. Dates & time
- 14. Performance & data volume
- 15. Testing your connector
- 16. Troubleshooting
- 17. Certification checklist
- 18. Registering your API in SchedEx
- Frequently asked questions
- Appendix A — A minimal end-to-end example
1. Introduction
The Generic REST API Connector is a standard contract for exchanging schedule data between SchedEx and any external scheduling system. By implementing this contract you let SchedEx synchronize projects, activities, dependencies, resources, resource assignments and calendars with your system.
SchedEx calls your API in three ways:
| Direction | HTTP verbs | What SchedEx does |
|---|---|---|
| Read from you | GET | Pulls planning objects out of your system. |
| Write to you | PUT (update), POST (create) | Pushes planning objects into your system. |
| Delete from you | DELETE | Conflict handling only — never during a normal transfer. |
2. Quick start
What you'll build
A small set of REST endpoints (one group per object type) that speak JSON and follow the conventions in this guide.
Minimum to be functional
At a minimum, implement these read endpoints so SchedEx can pull a schedule:
- Test — health/auth check.
- Get All Schedules — list selectable schedules.
- Get single Schedule — one schedule's detail.
- Get Activities, Get Resources, Get Calendars.
Add Activity Links and Resource Assignments to exchange dependencies and resourcing, and the POST/PUT endpoints when you want SchedEx to write back into your system. (See the full required-vs-optional matrix.)
How SchedEx talks to your connector
SchedEx Data Exchange
│ (HTTP + JSON, authenticated)
▼
Your API (Generic REST API)
├── Schedules (projects)
├── Calendars
├── Resources
└── Activities
├── Activity links (dependencies)
└── Resource assignmentsThe order SchedEx calls your endpoints
Reading a schedule into SchedEx
1. Test → confirm the API is up and authenticated
2. Get All Schedules → user picks a schedule
3. Get single Schedule → fetch its detail
4. Get Calendars
5. Get Resources
6. Get Activities
7. Get Resource Assignments
8. Get Activity LinksWriting a schedule back to your system (calendars and resources first, so activities can reference them):
1. Update Schedule
2. Create/Update Resources
3. Create/Update Calendars
4. Create/Update Activities
5. Create/Update Activity Links
6. Create/Update Resource AssignmentsHow your system fits — you build a translation layer
You are not redesigning your scheduling system. You add a thin API in front of it that maps your data to the shapes in this guide:
SchedEx
│
▼
Your Compliant API
│
▼
Adapter / translation layer ← you build this
│
▼
Your existing scheduling database / engineTypical implementation effort
Pick the scope that matches your goal:
| Scope | Implement | Gives you |
|---|---|---|
| Simple (read-only) connector | Test, Get All Schedules, Get single Schedule, and GET for Activities, Resources, Calendars | SchedEx can import schedules from your system. |
| Advanced connector | The above plus Activity Links, Resource Assignments, Custom Fields, and the POST/PUT (and optional DELETE) write-back endpoints | Full two-way synchronisation. |
Expected outcome
After implementation, a SchedEx admin can register your API as a connector, run a connectivity test, select a schedule, and transfer its data. See Testing your connector.
⚠️ Common implementation requirements
These are the rules most frequently missed during connector development. If something doesn't work, check these first:
- All
idand*Idvalues are JSON strings ("id": "491", never491).- References use the target object's
id—calendarId,resourceId,activityId,predecessorId,successorIdall point to an existing object'sid.POST(create) returns the newly createdidso SchedEx can track the object.- List write responses echo each request's
rowIdunchanged, one entry per row.- Pagination is deterministic — sort by internal
idand return an accuratetotalPages.- Dates are ISO-8601 in UTC.
- Transfers can re-run — match objects by
id(and bycodeif theidchanged), and upsert; don't assume every transfer is the first.
3. Glossary
| Term | Meaning |
|---|---|
| Schedule (project) | A plan: the top-level container for activities, resources and calendars. |
| Activity | A task in the schedule (work, milestone, summary, etc.). |
| Activity link | A dependency between two activities (predecessor → successor). |
| Resource | Something assigned to do work (people, equipment, material). |
| Resource assignment | A resource allocated to a specific activity. |
| Calendar | Working-time definition (working days/hours, holidays) an activity or assignment follows. |
| Custom field | Extra, user-defined data on a schedule or activity, defined by a Custom Host Field. |
| User field set | A named group of custom fields; lets some custom fields apply only to certain schedules. |
| Revision | A version/scope of a schedule (Live, Baseline, Current). Optional. |
| Planning object | Any of the above exchangeable entities. |
4. Core concepts
The data hierarchy
Schedule
├─ Calendars
├─ Resources ── Resource availabilities
└─ Activities
├─ Activity links (dependency to another activity)
└─ Resource assignments (a resource working on this activity)id and code — the two identifiers
Every planning object has two identifiers:
| Field | Purpose | Rules |
|---|---|---|
id | Stable system identifier (usually your primary key). SchedEx uses it to track and update objects, and as the target of all references (calendarId, resourceId, …). | Always a string. Unique within an object type and schedule. Convert integer/GUID keys to strings. |
code | Human-readable identifier shown to users and used to match objects across systems. | A string, unique within the schedule. If your object's name is unique, use it as the code; otherwise use any unique value. If you have no separate code, set code = id. |
Why two fields? id is the system identifier SchedEx uses internally to track and update a record; it should never change. code is the business identifier humans recognize and that SchedEx uses to match the same object across systems and in the UI. Keeping them separate lets the displayed code change without breaking the internal links — if you genuinely have only one identifier, set code = id.
Schedule & revision context
Object endpoints are scoped to a schedule, optionally to a revision:
| Query parameter | Required | Notes |
|---|---|---|
scheduleId | Yes (object endpoints) | Which schedule's objects to return. The parameter name is configurable in the connector. |
revisionType | No | Sent only when revisions are used. Ignore it if you have no revision concept. See Revision Type. |
Not sent to non-schedule endpoints (Test, Get All Schedules, Get Custom Fields).
Custom fields & user field sets
Custom fields are extra key/value data defined by Custom Host Fields. Each is either global (userFieldSetId = null, applies to all schedules) or schedule-specific (userFieldSetId matches the schedule's userFieldSetId). SchedEx scopes custom fields to a schedule by matching userFieldSetId — keep these values consistent between a schedule and its fields.
5. Conventions
- All
id/*Idvalues are JSON strings —"id": "491", not491. - JSON bodies;
Content-Type: application/json. - Dates are ISO-8601 — see Dates & time.
- Unknown fields are ignored — you may return extra fields; SchedEx reads only the documented ones.
- Property names match case-insensitively; use the exact
camelCasenames shown. - Relative paths — register each endpoint relative to a Base URL; don't return absolute URLs.
- Shared behaviour (auth, pagination, envelopes, errors) is defined once below and applies to every endpoint.
Versioning & forward compatibility
- Current ICAC version: 1.0. Report your own API version via the Test Response
apiVersionfield. - Future revisions of this contract will be backward-compatible: they may add new optional fields, never remove or repurpose existing ones.
- Ignore unknown fields you receive, and don't fail if a field you expect is absent — this is what keeps your connector working across versions.
6. Authentication
Choose one scheme when the connector is configured. Every request (including Test) must enforce it.
| Authentication type | Supported | How SchedEx sends it |
|---|---|---|
| Service token — Bearer scheme | Yes | Authorization: Bearer <token> |
| Service token — custom scheme (e.g. ApiKey) | Yes | Authorization: <scheme> <token> (scheme configurable) |
| Azure AD (Microsoft Entra ID) | Yes | Authorization: Bearer <access-token> obtained from your tenant |
| Custom headers | Yes | Any additional static headers configured on the connector |
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Il8...
Authorization: ApiKey 5mC343sssa42...7. Pagination
All list (GET) endpoints are paginated. SchedEx sends:
| Parameter | Type | Meaning |
|---|---|---|
pageNumber | integer | 1-based page index. |
pageSize | integer | Items per page. |
GET /api/activity?scheduleId=SCH-001&pageNumber=3&pageSize=20 → items 41–60.
Return:
{
"data": [ /* objects for this page */ ],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 50,
"totalPages": 5
}Rules
- Sort consistently (by internal
id) so pages neither overlap nor skip. totalPagesmust be accurate — SchedEx keeps requesting pages untilpageNumber > totalPagesor a page returns zero items.- Empty results are valid: return
200with an emptydataarray. - To skip paging entirely, return just
{ "data": [ … ] }with all items.
8. Status codes & error handling
| Situation | Status |
|---|---|
| Success (read or write, including empty results and partial-batch failures) | 200 |
| Authentication failed / missing | 401 |
| Authenticated but not permitted | 403 |
| Endpoint or resource not found (incl. unknown schedule on Get single Schedule) | 404 |
| Calendar create/update failed | 400 |
| Unexpected server error | 500 |
Error bodies are surfaced to the user, so return a clear message. Examples:
401 Unauthorized
{
"message": "Invalid or expired token."
}404 Not Found
{
"message": "Schedule 'SCH-999' was not found."
}400 Bad Request
{
"message": "Calendar 'C-1' rejected: finish date precedes start date."
}500 Internal Server Error
{
"message": "Unexpected error while reading activities. Reference: 8f3a."
}Even when a batch write partly fails, return
200and report each item's outcome in the body (next section) — don't fail the whole request.
9. Request & response envelopes
Write request — single object (Update Schedule, Create/Update Calendar)
{
"scheduleId": "SCH-001",
"revisionType": 1,
"...": "…object fields…"
}Write request — list of objects (activities, links, resources, assignments)
Each item carries a distinct rowId so SchedEx can match the response:
[
{
"scheduleId": "SCH-001",
"revisionType": 1,
"rowId": 1,
"id": "123",
"code": "A100"
},
{
"scheduleId": "SCH-001",
"revisionType": 1,
"rowId": 2,
"id": "124",
"code": "A101"
}
]Write response — single object
{
"id": "ACT-101",
"isSuccessful": true,
"message": "Created successfully"
}Write response — list (one entry per rowId, even if all failed)
[
{
"rowId": 1,
"id": "ACT-101",
"isSuccessful": true,
"message": "Created"
},
{
"rowId": 2,
"id": "ACT-102",
"isSuccessful": false,
"message": "Validation failed: …"
}
]| Field | Type | Meaning |
|---|---|---|
rowId | integer | The rowId from the matching request item (list responses only). |
id | string | The object's id. On POST (create), return the new id so SchedEx can track it. |
isSuccessful | bool | Whether this item succeeded. |
message | string (optional) | Detail, especially on failure. |
Delete request — list
[
{
"id": "ACT-101",
"rowId": 1,
"scheduleId": "SCH-001",
"revisionType": 1
}
]Respond with the same list envelope (one entry per rowId).
10. Endpoints
Required = needed for SchedEx to work. Optional = implement only if you support that capability. DELETE is conflict-handling only.
| Object | GET | POST | PUT | DELETE |
|---|---|---|---|---|
| Test | Required | — | — | — |
| All Schedules | Required | — | — | — |
| Custom Fields | Optional | — | — | — |
| Schedule | Required | — | Required | — |
| Calendar | Required | Required | Required | — |
| Resource | Required | Required | Required | — |
| Activity | Required | Required | Required | Optional |
| Activity Link | Required | Required | Required | Optional |
| Resource Assignment | Required | Required | Required | Optional |
Read-only systems: if you only want SchedEx to import data from your system, implement the
GETendpoints only.POST,PUTandDELETEare required only when you want SchedEx to write back into your system. "Required" above means required for that capability — not that every connector must implement every verb.
Each endpoint below lists its purpose, what SchedEx sends, what you return, and rules.
Test — GET
- Purpose: lets SchedEx confirm your API is reachable and the credentials are valid (used when an admin tests the connector).
- Sends: nothing (but enforce auth).
- Returns: a Test Response.
- Rules: healthy = success status and
isSuccessnotfalse.
Get All Schedules — GET
- Purpose: lists the schedules a user can choose to synchronise.
- Sends: pagination only.
- Returns: paginated Schedule (summary).
Get Custom Fields — GET (optional)
- Purpose: tells SchedEx which custom fields exist and what object types they apply to.
- Sends: pagination only.
- Returns: paginated Custom Host Field.
Get single Schedule — GET
- Purpose: retrieves one schedule's full detail once a user selects it.
- Sends:
scheduleId(+ optionalrevisionType). No pagination. - Returns:Schedule (detail). Return
404if not found.
Update Schedule — PUT
- Purpose: writes schedule-level changes back to your system.
- Sends:Schedule (write) (single-object envelope).
- Returns: single-object write response.
Activities — GET / POST / PUT / DELETE
- Purpose: exchange the tasks of a schedule.
- GET → paginated Activity (sends
scheduleId). POST/PUT → list envelope; return list response (return new ids onPOST). DELETE(optional) → conflict handling. - Rules: identify each activity by
id. If an item hasupdateOnlyActivityCode: true, update only thecode.
Activity Links — GET / POST / PUT / DELETE
- Purpose: exchange dependencies between activities.
- GET → paginated Activity Link. POST/PUT → list. DELETE(optional).
- Rules:
predecessorIdandsuccessorIdmust reference activityids in the same schedule; both are required.
Resources — GET / POST / PUT
- Purpose: exchange the resources available to a schedule.
- GET → paginated Resource. POST/PUT → list.
Resource Assignments — GET / POST / PUT / DELETE
- Purpose: exchange which resource works on which activity.
- GET → paginated Resource Assignment. POST/PUT → list. DELETE(optional).
- Rules:
resourceIdandactivityIdmust reference existing objects.
Calendars — GET / POST / PUT
- Purpose: exchange working-time definitions.
- GET → paginated Calendar (with operations). POST/PUT → a single calendar (single-object envelope). Return
400on failure.
11. Data models
(nullable) = may be
nullor omitted. Allid/*Idfields are strings.
Schedule
Exposed in three shapes — the three operations need different fields.
Schedule (summary)
Returned by Get All Schedules.
| Property | Type | Description |
|---|---|---|
id | string | Unique schedule identifier. |
name | string | Schedule name (shown as the title in SchedEx). |
description | string | Schedule description. |
startDate | DateTime (nullable) | Start date. |
finishDate | DateTime (nullable) | Finish date. |
userFieldSetId | int (nullable) | Custom-field set; null if none. |
lastUpdatedDate | DateTime (nullable) | When last updated. |
{
"id": "SCH-001",
"name": "Offshore Platform A",
"description": "EPC schedule for platform A",
"startDate": "2025-01-01T00:00:00",
"finishDate": "2026-12-31T00:00:00",
"userFieldSetId": 2,
"lastUpdatedDate": "2025-06-01T09:30:00"
}Schedule (detail)
Returned by Get single Schedule. Uses code as the identifier; carries custom fields.
| Property | Type | Description |
|---|---|---|
id | string | Unique schedule identifier. |
code | string | Human-readable identifier (schedule name if unique, else any unique value). |
description | string | Schedule description. |
startDate | DateTime (nullable) | Start date. |
finishDate | DateTime (nullable) | Finish date. |
currentProgress | double | Overall completion % (0–100). |
cutoffDate | DateTime (nullable) | Data date / cut-off date. |
userFieldSetId | int (nullable) | Custom-field set; null if none. |
customFields | object | Custom field values keyed by field name (keys unique). |
{
"id": "SCH-001",
"code": "P-1001",
"description": "EPC schedule for platform A",
"startDate": "2025-01-01T00:00:00",
"finishDate": "2026-12-31T00:00:00",
"currentProgress": 12.5,
"cutoffDate": "2025-06-01T00:00:00",
"userFieldSetId": 2,
"customFields": {
"Phase": "FEED",
"Discipline": "Structural"
}
}Schedule (write)
Sent by Update Schedule — the detail shape plus the envelope. userFieldSetId is read-only and is not sent on write.
| Property | Type | Description |
|---|---|---|
scheduleId | string | Schedule being updated (envelope). |
revisionType | integer | See Revision Type. |
id, code, description, startDate, finishDate, currentProgress, cutoffDate, customFields | — | As in Schedule (detail). |
{
"scheduleId": "SCH-001",
"revisionType": 1,
"id": "SCH-001",
"code": "P-1001",
"description": "EPC schedule for platform A",
"startDate": "2025-01-01T00:00:00",
"finishDate": "2026-12-31T00:00:00",
"currentProgress": 12.5,
"cutoffDate": "2025-06-01T00:00:00",
"customFields": {
"Phase": "FEED",
"Discipline": "Structural"
}
}Activity
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
code | string | Activity code. |
activityType | integer | See ActivityType. |
description | string | Description. |
calendarId | string (nullable) | Calendar this activity follows (a calendar id). |
finishAsEarlyAsPossible, startAsEarlyAsPossible, startAsLateAsPossible | bool | Scheduling constraints. |
mustStartOn, mustFinishOn, startNoEarlierThan, startNoLaterThan, finishNoLaterThan, finishOnOrAfter | DateTime (nullable) | Constraint dates. |
actualStart, actualFinish | DateTime (nullable) | Actual dates. |
earlyStart, earlyFinish, lateStart, lateFinish | DateTime (nullable) | Scheduled dates. |
actualWorkHours | double | Actual work hours completed. |
plannedWorkHours, remainingWorkHours | double (nullable) | Work hours. |
durationHours, remainingDurationHours | double (nullable) | Duration. |
freeFloatHours, totalFloatHours | double (nullable) | Float. |
currentProgress, plannedProgress | double | Progress %. |
isAlwaysOnSchedule | bool | Always on schedule. |
isCancelled | bool (nullable) | Cancelled. |
cancelledDate, frontLineDate | DateTime (nullable) | Related dates. |
customFields | object | Custom field values (keys unique). |
{
"id": "2650",
"code": "A100",
"activityType": 4,
"description": "Start Milestone",
"calendarId": "1674",
"mustStartOn": "2019-03-01T00:00:00",
"earlyStart": "2019-03-01T00:00:00",
"earlyFinish": "2019-03-01T00:00:00",
"plannedWorkHours": 500.0,
"remainingWorkHours": 500.0,
"currentProgress": 0.0,
"plannedProgress": 100.0,
"isAlwaysOnSchedule": false,
"isCancelled": false,
"durationHours": 0.0
}Activity Link
A dependency: predecessor → successor.
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
code | string | Link code. |
type | integer | Dependency type — SuccessorType. |
predecessorId | string | id of the predecessor activity. |
successorId | string | id of the successor activity. |
lagHours | double (nullable) | Lag in hours. |
calendarId | string (nullable) | Calendar for the lag. |
{
"id": "826",
"predecessorId": "1150",
"successorId": "1153",
"type": 2,
"lagHours": 48.0,
"calendarId": "490"
}Resource
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
code | string | Resource code. |
description | string | Description. |
resourceAvailabilities | array of Resource Availability | Availability windows. |
Resource Availability
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
code | string | Code. |
description | string | Description. |
startDateTime | DateTime (nullable) | Window start. |
finishDateTime | DateTime (nullable) | Window end. |
availableQuantity | double (nullable) | Quantity available. |
availableRate | double (nullable) | Rate available. |
{
"id": "331",
"code": "2|3",
"description": "RD-0010",
"resourceAvailabilities": [
{
"id": "331-1",
"startDateTime": "2019-03-01T00:00:00",
"finishDateTime": "2019-04-01T00:00:00",
"availableQuantity": 2,
"availableRate": 0.01
}
]
}
availableQuantity/availableRate/startDateTime/finishDateTimelive inside the nestedresourceAvailabilitiesitems — not on the resource itself.
Resource Assignment
Connects a resource to an activity.
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
code | string | Assignment code. |
resourceId | string | id of the assigned resource. |
activityId | string | id of the activity. |
calendarId | string (nullable) | Calendar for the assignment. |
resourceUsageType | integer | See ResourceUsageType. |
plannedHours, actualHours, durationHours | double (nullable) | Hours. |
currentProgress | double (nullable) | Progress %. |
earlyStart, earlyFinish | DateTime (nullable) | Scheduled dates. |
lagHours | double (nullable) | Lag hours. |
{
"id": "3796",
"code": "2|884|1452",
"resourceId": "331",
"activityId": "1150",
"calendarId": "1",
"resourceUsageType": 1,
"plannedHours": 500.0,
"actualHours": 0.0,
"currentProgress": 0.0,
"earlyStart": "2019-03-01T00:00:00",
"earlyFinish": "2019-04-01T00:00:00",
"lagHours": 2
}Calendar
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
code | string | Calendar code. |
description | string | Description. |
hoursPerDay | double | Standard working hours per day. |
start | DateTime | Calendar start date. |
finish | DateTime | Calendar end date. |
calendarOperations | array of Calendar Operation | Working-time rules. |
Calendar Operation
| Property | Type | Description |
|---|---|---|
type | integer | See CalendarOperationType. |
weeklyRepeatingPeriods | array | Recurring weekly working times. |
connectedPeriods | array | One-off date ranges (e.g. holidays). |
- Weekly repeating period:
dayOfWeek(integer, DayOfWeek),startTime(DateTime),finishTime(DateTime). The time-of-day in start/finish defines that day's working hours. - Connected period:
startDateTime(DateTime),finishDateTime(DateTime).
{
"id": "491",
"code": "3|176",
"description": "5 day, 8 hour",
"hoursPerDay": 8.0,
"start": "2016-01-01T00:00:00",
"finish": "2022-12-31T00:00:00",
"calendarOperations": [
{
"type": 1,
"weeklyRepeatingPeriods": [
{
"dayOfWeek": 1,
"startTime": "2025-05-22T00:00:00",
"finishTime": "2025-05-22T08:00:00"
}
],
"connectedPeriods": []
},
{
"type": 0,
"weeklyRepeatingPeriods": [],
"connectedPeriods": [
{
"startDateTime": "2019-03-15T00:00:00",
"finishDateTime": "2019-03-16T00:00:00"
}
]
}
]
}Custom Host Field
A custom field definition (from Get Custom Fields).
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier. |
name | string | Field name (the custom-field key). |
planningObjectType | integer | Object type it applies to — PlanningObjectType. |
dataType | integer | Field data type — TypeCode. |
userFieldSetId | int (nullable) | Field set; null = global; a value = applies to schedules whose userFieldSetId matches. |
alias | string (nullable) | Optional alias. |
metadata | string (nullable) | Any extra info you want SchedEx to keep. |
{
"id": "R-710D3D4E-80C2-47EE-8756-27B879C3E2A3",
"name": "Ilap_Term_1",
"planningObjectType": 2,
"dataType": 14,
"userFieldSetId": 2,
"alias": "",
"metadata": ""
}Test Response
| Property | Type | Description |
|---|---|---|
message | string | Status message. |
isSuccess | bool (nullable) | Healthy or not. If omitted, a success status is treated as healthy. |
apiVersion | string | API version, e.g. 1.0.0.0. |
{
"message": "Success",
"isSuccess": true,
"apiVersion": "1.0.0.0"
}12. Enumerations
Send the integer value.
ActivityType
| Value | Name |
|---|---|
| 0 | NotSet |
| 3 | RegularActivity |
| 4 | MilestoneStart |
| 5 | MilestoneFinish |
| 6 | Hammock |
| 7 | TaskDependent |
| 8 | ResourceDependent |
| 9 | LevelOfEffort |
| 10 | WbsSummary |
SuccessorType
| Value | Name |
|---|---|
| 0 | StartToStart |
| 1 | StartToFinish |
| 2 | FinishToStart |
| 3 | FinishToFinish |
ResourceUsageType
| Value | Name |
|---|---|
| 0 | NotSet |
| 1 | Equipment |
| 2 | StaffTime |
| 3 | Material |
CalendarOperationType
| Value | Name | Meaning |
|---|---|---|
| 0 | RemoveWorkingTime | Remove working time (e.g. holidays). |
| 1 | AddWorkingTime | Add working time (e.g. working days, overtime). |
DayOfWeek
| Value | Day |
|---|---|
| 0 | Sunday |
| 1 | Monday |
| 2 | Tuesday |
| 3 | Wednesday |
| 4 | Thursday |
| 5 | Friday |
| 6 | Saturday |
Revision Type
| Value | Name |
|---|---|
| 0 | Live |
| 1 | OriginalBaseline |
| 2 | Baseline |
| 3 | Current |
PlanningObjectType
| Value | Name |
|---|---|
| 1 | Schedule |
| 2 | Activity |
| 4 | Successor |
| 8 | ResourceUsage |
| 16 | Resource |
| 32 | Profile |
| 64 | Calendar |
| 128 | Structure |
TypeCode
| Value | Type |
|---|---|
| 3 | Boolean |
| 9 | Int32 |
| 13 | Single |
| 14 | Double |
| 16 | DateTime |
| 18 | String |
13. Dates & time
- Format: ISO-8601, e.g.
"2025-01-01T00:00:00". - Time zone:UTC is strongly recommended for all implementations. The examples carry no offset and SchedEx reads timestamps as given, so returning local time leads to synchronisation problems across vendors and daylight-saving shifts. Use UTC consistently on both reads and writes.
- Time-of-day matters for calendar working periods (
startTime/finishTimedefine daily hours). - Nullable dates: omit the field or send
nullwhen there is no value.
14. Performance & data volume
- Large schedules (10k+ activities) are normal — page your list endpoints and keep
totalPagescorrect. - Read batch size and Write batch size are configured on the connector (commonly
1000). SchedEx reads using the page size and writes in batches of that size, so handle array requests/responses efficiently. - Avoid timeouts: stream/paginate rather than loading everything into memory; keep per-request work bounded by the batch size.
- Consistent ordering (by internal
id) is essential for correct pagination across large data.
15. Testing your connector
- Deploy your API and make it reachable from the SchedEx execution component.
- Register the connector in SchedEx with your Base URL, paths and auth (see Section 18).
- Test connectivity — SchedEx calls your Test endpoint; confirm it returns success with
isSuccess: true. - List schedules — confirm Get All Schedules returns your schedules.
- Read a schedule — select one and verify activities, resources, calendars, links and assignments come through.
- Write back — run a transfer into your system and confirm the
POST/PUTpayloads create/update the right objects (check that relationship ids resolve). - Validate the data on both sides matches.
16. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Objects silently missing after a read | Numeric ids, or wrong field names | Return ids as strings; match the exact field names in this guide. |
| Pagination loops or drops items | Inaccurate totalPages, or unstable sort | Compute totalPages correctly; sort by internal id. |
| Dependencies don't appear | Missing/incorrect predecessorId/successorId | Both must reference existing activity ids in the schedule. |
| Resource assignment "orphaned" | Missing resourceId or activityId | Both must reference existing objects. |
| Activity has no/wrong calendar | calendarId doesn't match a calendar id | Reference an existing calendar id. |
| Resource availability ignored | Availability fields placed flat on the resource | Nest them under resourceAvailabilities. |
| Connectivity test fails | Auth not enforced on Test, or wrong scheme/token | Apply auth to every endpoint incl. Test; verify scheme/token. |
| Custom fields not applied to a schedule | userFieldSetId mismatch | Make field and schedule userFieldSetId consistent (null = global). |
| Duplicate-key errors | Non-unique id or code | Ensure uniqueness within object type and schedule. |
| Dates rejected/shifted | Non-ISO format or inconsistent zone | Use ISO-8601; one consistent zone. |
17. Certification checklist
Your connector is ready when all of these pass.
Endpoints
- Test
- Get All Schedules
- Get single Schedule
- Activities (GET, POST, PUT)
- Resources (GET, POST, PUT)
- Calendars (GET, POST, PUT)
- Activity Links (GET, POST, PUT)
- Resource Assignments (GET, POST, PUT)
- Custom Fields (if supported)
- Delete endpoints (if conflict handling needed)
Correctness
- All
id/*Idare strings;id&codeunique per schedule. - All references resolve (
calendarId,resourceId,activityId,predecessorId,successorId). - Lists paginated, sorted by
id, accuratetotalPages. - Writes return one result per
rowId;POSTreturns new ids. customFieldskeys unique;userFieldSetIdscoping consistent.- Dates ISO-8601; consistent time zone.
- Auth enforced everywhere incl. Test; health reported via
isSuccess. - Errors return clear messages with appropriate status codes.
End to end
- Connectivity test succeeds.
- A schedule reads in completely.
- A schedule writes back completely.
- Read/write data validated on both sides.
18. Registering your API in SchedEx
Pre-requisite: an SchedEx user with the Setup Admin role.
A SchedEx Setup Admin registers your API (Setup → Connectors → New) with:
| Field | Required | What it is |
|---|---|---|
| Title | Yes | Display name (unique in SchedEx). |
| Host System | Yes | Select Compliant API. |
| Execution Component | Yes | Where the transfer runs (Desktop or Autonomous component). |
| Authentication Type | Yes | Service Token or OAuth2/Azure AD. |
| Base URL | Yes | Root URL of your API (e.g. https://example.com/api/v1), no trailing slash. |
| Test Path | Yes | Relative path of your Test endpoint. |
| Get All Schedules Path | Yes | Relative path returning schedule summaries. |
| Get Custom Fields Path | No | Relative path for custom field definitions (if supported). |
| Schedule Id Query Parameter | Yes | The query-parameter name your API expects for the schedule id (default scheduleId). |
| Schedule Path | Yes | Single-schedule GET/PUT. |
| Calendar Path | Yes | Calendar GET/POST/PUT. |
| Resource Path | Yes | Resource GET/POST/PUT. |
| Activity Path | Yes | Activity GET/POST/PUT/DELETE. |
| Activity Link Path | Yes | Activity-link GET/POST/PUT/DELETE. |
| Resource Assignment Path | Yes | Resource-assignment GET/POST/PUT/DELETE. |
| Read Batch Size | No | Page size when reading (tune for large schedules). |
| Write Batch Size | Yes | Items per write request (prevents timeouts). |
All paths are relative to the Base URL: Base URL https://example.com/api/v1 + Test Path health → https://example.com/api/v1/health.
Reference implementation & example paths
SchedEx ships a working reference implementation (in a solution called "Analytics"): its GET endpoints return real data filtered by schedule id and revision type, while its POST/PUT/DELETE endpoints return a dummy response — so you can point a connector at it to see the contract in action. Its endpoint paths also make a good naming example:
| Endpoint | Example relative path |
|---|---|
| Test | api/v3/export/Status |
| All Schedules | api/v3/export/Persist/Schedules |
| Custom Fields | api/v3/export/Persist/HostFields |
| Schedule | api/v3/export/singleSchedule |
| Activity | api/v3/export/Activities |
| Activity Link | api/v3/export/ActivityLinks |
| Resource | api/v3/export/Resources |
| Resource Assignment | api/v3/export/ResourceAssignments |
| Calendar | api/v3/export/Calendars |
Sample connector values: Authentication Service Token, Schedule Id Query Parameter reportscheduleid, Read Batch Size 1000, Write Batch Size 1000.
Frequently asked questions
Can I use integers for IDs? No — all id and *Id values must be JSON strings. Convert integer or GUID keys to strings.
Can I omit pagination? Yes. Return the full set as { "data": [ … ] } without the paging fields. For large schedules, paginating is recommended.
Do I need to support revisions? No. If you have no Live/Baseline/Current concept, ignore the revisionType parameter.
Can I build a read-only integration? Yes. Implement the GET endpoints only; add POST/PUT/DELETE later if you want write-back.
Do I have to change my database? No. You build a thin translation layer in front of your existing system (see How your system fits).
What date format and time zone should I use? ISO-8601, in UTC — see Dates & time.
Which endpoints are mandatory? Test, Get All Schedules, Get single Schedule, and GET for Activities, Resources and Calendars. Everything else depends on the capabilities you want (see Endpoints).
What happens if a few items in a batch fail? Return 200 and report each item's outcome by rowId in the response body — don't fail the whole request.
Will new versions break my connector? No, if you ignore unknown fields and tolerate missing optional ones — see Versioning.
Appendix A — A minimal end-to-end example
A tiny schedule with one calendar, one resource, one activity, plus a dependency and an assignment — the shapes SchedEx expects from each endpoint.
GET {Test Path}
{
"message": "OK",
"isSuccess": true,
"apiVersion": "1.0.0.0"
}GET {Get All Schedules Path}?pageNumber=1&pageSize=10
{
"data": [
{
"id": "SCH-001",
"name": "Demo Project",
"description": "Sample",
"startDate": "2025-01-01T00:00:00",
"finishDate": "2025-12-31T00:00:00",
"userFieldSetId": null,
"lastUpdatedDate": "2025-06-01T09:30:00"
}
],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 1,
"totalPages": 1
}GET {Schedule Path}?scheduleId=SCH-001
{
"id": "SCH-001",
"code": "Demo Project",
"description": "Sample",
"startDate": "2025-01-01T00:00:00",
"finishDate": "2025-12-31T00:00:00",
"currentProgress": 0,
"cutoffDate": null,
"userFieldSetId": null,
"customFields": {}
}GET {Calendar Path}?scheduleId=SCH-001
{
"data": [
{
"id": "CAL-1",
"code": "Standard",
"description": "5x8",
"hoursPerDay": 8.0,
"start": "2025-01-01T00:00:00",
"finish": "2025-12-31T00:00:00",
"calendarOperations": [
{
"type": 1,
"weeklyRepeatingPeriods": [
{
"dayOfWeek": 1,
"startTime": "2025-01-01T08:00:00",
"finishTime": "2025-01-01T16:00:00"
}
],
"connectedPeriods": []
}
]
}
],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 1,
"totalPages": 1
}GET {Resource Path}?scheduleId=SCH-001
{
"data": [
{
"id": "RES-1",
"code": "Crane",
"description": "Mobile crane",
"resourceAvailabilities": []
}
],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 1,
"totalPages": 1
}GET {Activity Path}?scheduleId=SCH-001
{
"data": [
{
"id": "ACT-1",
"code": "A100",
"activityType": 3,
"description": "Pour foundation",
"calendarId": "CAL-1",
"currentProgress": 0,
"plannedProgress": 0,
"isAlwaysOnSchedule": false,
"durationHours": 40,
"customFields": {}
},
{
"id": "ACT-2",
"code": "A200",
"activityType": 3,
"description": "Build walls",
"calendarId": "CAL-1",
"currentProgress": 0,
"plannedProgress": 0,
"isAlwaysOnSchedule": false,
"durationHours": 80,
"customFields": {}
}
],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 2,
"totalPages": 1
}GET {Activity Link Path}?scheduleId=SCH-001
{
"data": [
{
"id": "LNK-1",
"code": "A100->A200",
"predecessorId": "ACT-1",
"successorId": "ACT-2",
"type": 2,
"lagHours": 0,
"calendarId": "CAL-1"
}
],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 1,
"totalPages": 1
}GET {Resource Assignment Path}?scheduleId=SCH-001
{
"data": [
{
"id": "RA-1",
"code": "Crane@A200",
"resourceId": "RES-1",
"activityId": "ACT-2",
"calendarId": "CAL-1",
"resourceUsageType": 1,
"plannedHours": 80,
"actualHours": 0,
"currentProgress": 0
}
],
"pageNumber": 1,
"pageSize": 10,
"totalItems": 1,
"totalPages": 1
}Writing back — POST {Activity Path} (request → response)
[
{
"scheduleId": "SCH-001",
"revisionType": 0,
"rowId": 1,
"code": "A300",
"activityType": 3,
"description": "Roofing",
"calendarId": "CAL-1"
}
][
{
"rowId": 1,
"id": "ACT-3",
"isSuccessful": true,
"message": "Created"
}
]
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article