Last Updated: October 18, 2025
This document explains how third‑party developers can integrate an external data source with the application. You configure your own API base URL, and the app's server proxies requests to your API.

id, name, email, capacity (decimal), and work_days (array of integers 1–7).id, title, optional note, color (any hex color, but we recommend avoiding gray, red and green as these are colors we use for statuses).id, project_id, resource_id, date_from, date_to, hours_per_day, optional note.The server proxies requests to your configured apiBaseUrl. Endpoints should be relative to your API root and return JSON. You should have the following endpoints, so the app works correctly:
On GET, return all resources, projects, assignments, plus any embedded memberships in a single payload.
{
"resources": [
{
"id": 1,
"name": "Alice",
"email": "alice@example.com", // optional
"capacity": 37.5,
"work_days": [1, 2, 3, 4, 5]
}
],
"projects": [
{
"id": 42,
"title": "Migration Project",
"note": "Phase 1 rollout", // optional
"color": '#D71DF4', // optional
"enum_status_id": 1
}
],
"assignments": [
{
"id": 7,
"project_id": 42,
"resource_id": 1,
"date_from": "2025-09-01",
"date_to": "2025-09-10",
"hours_per_day": 8,
"note": "Polishing UI", // optional
}
]
}| Method | Endpoint | Description |
|---|---|---|
| POST | /resources | Create a resource; return the created record with embedded membership. Pass invited=true when you want the app to email an invitation; omit the membership block entirely to add a resource without inviting them yet. Supply access details inside the nested membership object:The response includes the persisted membership snapshot: Membership field reference
You can omit the |
| PUT | /resources/{id} | Update a resource; supply the changed fields only. Provide the membership object when adjusting roles, visibility, or customer permissions. |
| DELETE | /resources/{id} | Delete a resource and its assignments; return status 200. We try to delete all assignments of this resource on external API, but we don't block the operation if it fails. |
| Method | Endpoint | Description |
|---|---|---|
| POST | /projects | Create a project; return the created record. For example: |
| PUT | /projects/{id} | Update a project; return the updated record. For example: |
| DELETE | /projects/{id} | Delete a project (and its assignments); return status 200. We try to delete all assignments of this project on external API, but we don't block the operation if it fails. |
| Method | Endpoint | Description |
|---|---|---|
| POST | /assignments | Create an assignment; return the created record. For example: |
| PUT | /assignments/{id} | Update an assignment; return the updated record. For example: |
| DELETE | /assignments/{id} | Delete an assignment; return status 200. |
Protect your API with authentication. The planner's server signs outbound requests with Authorization: Bearer <KEY>.
Since requests originate from our server to yours, typical browser CORS restrictions do not apply. Ensure your API allows requests from our deployment environment (standard server‑to‑server access).
YYYY-MM-DD). The client parses them to Dates.hours_per_day is converted to a float. Prefer dot as decimal separator.work_days is an array of integers 1–7 (Mon–Sun).Every outbound call from Resource Planner to your API contains the workspace API key in the Authorization header. When testing directly, use the same key:
curl -X POST https://yourapp.com/api/resources \
-H "Authorization: Bearer <API_ACCESS_KEY>" \
-H "Content-Type: application/json" \
-d '{
"name": "Charlie Manager",
"email": "charlie@example.com",
"membership": {
"role": "manager",
"memberSettings": { "visibility": "team" },
"managerSettings": {
"scope": "managed",
"managesResources": ["RESOURCE_ID"],
"canSeeFinancials": true
}
}
}'The body above uses the nested membership object; the backend normalises it to the canonical membership shape before persisting.
GET /loadData and normalises the response.POST /projects;POST /resources;POST /assignments; with respective resource_id and project_id.PUT/DELETE the relevant entity. We do optimistic updates on client, but we show error messages on failure, so user can reload the page.