REST API Access Guide

Last Updated: July 20, 2026

1. What's included

Every workspace can issue a one-time API access keyto call ResourcePlanner's built-in REST endpoints directly. The key authenticates requests to the same server-side routes that power the web application, so you always receive normalized JSON responses.

2. Generating the API access key

  1. Sign in and open Settings → API access for REST clients.
  2. Click Generate new key.
  3. Copy the one-time value that appears in the dialog. The plaintext key is never shown again.
  4. Store it securely (we recommend a secrets manager). You can revoke or regenerate the key at any time from the same screen.

Only one API access key can exist per workspace. Regenerating a key immediately invalidates the previous value.

3. Authentication

All API requests must include the key in the Authorization header using the Bearer scheme:

curl https://resourceplanner.io/api/resources \
  -H "Authorization: Bearer <YOUR_API_ACCESS_KEY>"
  • The key encodes your workspace ID, so every request is scoped to your workspace automatically.
  • Keys are currently unlimited; apply your own rate limiting if you expose the key to client-side apps.

4. Supported endpoints

The following endpoints accept bearer authentication. Payloads use camelCase fields, and responses always return the normalized ResourcePlanner shape.

| Method | Endpoint | Notes |
| ------ | -------- | ----- |
| GET | `/api/resources` | List all resources in the workspace. |
| POST | `/api/resources` | Create a new resource. |
| PUT | `/api/resources/{id}` | Update a resource (partial updates supported). |
| DELETE | `/api/resources/{id}` | Delete a resource and its assignments. |
| GET | `/api/projects` | List all projects. |
| POST | `/api/projects` | Create a project; accepts optional `projectSize` (hours), `projectRate`, and `resourceRates[]`. |
| PUT | `/api/projects/{id}` | Update a project; set `projectSize`, `projectRate`, or `resourceRates[]` (use `null` or an empty array to clear). |
| DELETE | `/api/projects/{id}` | Delete a project and its assignments. |
| GET | `/api/assignments` | Optional filters: `projectId`, `resourceId`, `dateFrom`, `dateTo`. |
| POST | `/api/assignments` | Create an assignment using camelCase payloads; optional task fields are supported. |
| PUT | `/api/assignments/{id}` | Update date range, hours, note, links, or task details. |
| DELETE | `/api/assignments/{id}` | Remove an assignment. |
| GET | `/api/time-entries` | Read time entries with optional period, person, and project filters. Time-entry writes are not available through API keys. |

Filtering assignments

GET /api/assignments accepts optional projectId, resourceId, dateFrom, and dateTo query parameters to refine the list. Provide just one date to fetch everything after or before that point, or pass both to limit results to a specific window. Aliases from and to work as shorthand. When no filters are provided, you receive every assignment in the workspace.

Reading time entries

GET /api/time-entries returns time entries across the workspace. All filters are optional, and API-key requests return the newest 100 matching entries by default.

curl --get https://resourceplanner.io/api/time-entries \
  -H "Authorization: Bearer <YOUR_API_ACCESS_KEY>" \
  --data-urlencode "from=2026-07-01T00:00:00.000Z" \
  --data-urlencode "to=2026-08-01T00:00:00.000Z" \
  --data-urlencode "resourceId=RESOURCE_ID" \
  --data-urlencode "sort=desc"
| Parameter | Notes |
| --------- | ----- |
| `from` | Optional ISO 8601 date-time. Includes entries still running or ending after this instant. |
| `to` | Optional ISO 8601 date-time. Includes entries starting before this instant. |
| `resourceId` | Optional resource ID. Repeat the parameter to select multiple people. |
| `projectId` | Optional project ID. Repeat it for multiple projects or use `unassigned` for entries without a project. |
| `limit` | Page size from 1 to 100. Defaults to 100 for API-key requests. |
| `offset` | Number of matching entries to skip; defaults to 0. |
| `sort` | `asc` or `desc` by start time. API-key requests default to `desc`. |
| `includeSummary` | Set to `true` to include total tracked seconds, clipped to any supplied period bounds. |

When both from and to are supplied, the interval is half-open: an entry overlaps the period when it starts before to and is still running or ends after from. Entries ending exactly at from and entries starting exactly at to are excluded.

The response uses the standard data array and includes serverNow plus pagination. When requested,summary.totalSeconds covers every matching entry, not only the current page.

| Field | Description |
| ----- | ----------- |
| `id`, `title` | Entry ID and description. |
| `startedAt`, `endedAt`, `isRunning` | ISO timestamps and current running state. `endedAt` is `null` for a running timer. |
| `resourceId`, `resource` | Person ID and expanded `{ id, name }` summary. |
| `projectId`, `project` | Optional project ID and expanded `{ id, title, color }` summary. |
| `taskId`, `task` | Optional task ID and expanded `{ id, title }` summary. |
| `createdAt`, `updatedAt` | Entry audit timestamps. |

Time tracking is read-only for API-key clients. Creating, updating, deleting, starting, or stopping entries remains available only to authenticated users through the ResourcePlanner application.

5. Creating data

Write endpoints accept the same payloads the web app uses internally. The examples below demonstrate how to create each entity with typical fields.

Create a resource

curl -X POST https://resourceplanner.io/api/resources \
  -H "Authorization: Bearer <YOUR_API_ACCESS_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Jordan Weaver",
        "email": "jordan.weaver@example.com",
        "invited": true,
        "membership": {
          "role": "manager",
          "memberSettings": { "visibility": "team" },
          "managerSettings": {
            "scope": "managed",
            "managesResources": ["RESOURCE_ID"],
            "canSeeFinancials": true
          }
        },
        "capacity": 37.5,
        "hourlyExpense": 45,
        "workDays": [1, 2, 3, 4, 5]
      }'

Supply access settings inside the nested membership object. Set invited=true to trigger an email invitation. The server sanitises the payload before persisting.

To add someone without inviting them yet, omit invited (or set it to false) and skip the membership block—the resource will be created without any access assigned.

Valid roles are member, manager, admin, and customer. The server applies safe defaults—for example, admins automatically gain full financial access.

  • memberSettings.visibility: self restricts the person to their own calendar; team lets them view teammates they are allowed to manage.
  • managerSettings.scope: use managed to constrain actions to the managesResources array, orall for workspace-wide control.
  • managerSettings.managesAllMembers: set true to grant access to every resource without listing IDs. When false, populate managesResourceswith resource IDs the manager oversees.
  • managerSettings.canSeeFinancials: trueexposes project rates (including overrides) and resource expenses; managers who lack this flag will have those fields removed from responses.
  • customerSettings.projectIds: array of project IDs the customer can view or edit.
  • customerSettings.canEditAssignments: allow customers to create or modify assignments within their project list.
  • status: optional lifecycle state—pending,active, inactive, or declined.

Responses include the normalised membership snapshot (role, status, settings) so you can confirm what was persisted.

Create a project

curl -X POST https://resourceplanner.io/api/projects \
  -H "Authorization: Bearer <YOUR_API_ACCESS_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
        "title": "Website Relaunch",
        "color": "#2563eb",
        "note": "Public roadmap initiative",
        "projectSize": 240,
        "projectRate": 125,
        "resourceRates": [
          { "resourceId": "RESOURCE_ID", "rate": 150 }
        ]
      }'

Include the optional projectSize field to capture the estimated total hours for the project. Send a non-negative number to set it or null to clear existing values.

When you need to manage billing, set projectRate for the default hourly amount and include a resourceRates array with objects like { "resourceId": "RES_ID", "rate": 150 }for overrides. Each resource can have only one override, and these values are only readable by users with financial permissions.

Create an assignment

curl -X POST https://resourceplanner.io/api/assignments \
  -H "Authorization: Bearer <YOUR_API_ACCESS_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
        "project": "PROJECT_ID",
        "resource": "RESOURCE_ID",
        "dateFrom": "2025-10-20",
        "dateTo": "2025-10-24",
        "hoursPerDay": 6,
        "note": "Internal workshop prep",
        "title": "Prepare workshop materials",
        "description": "<p>Collect slides, examples, and handouts.</p>"
      }'

Tasks are represented as optional metadata on assignments. There is no separate public /api/tasks endpoint. Send titleto create or update the assignment's linked task, and include description or comments when you need richer task detail. Leave title empty or omit it for a plain assignment.

| Field | Used on | Notes |
| ----- | ------- | ----- |
| `title` | request/response | Optional task title. A non-empty value creates or updates the linked task for the assignment. |
| `description` | request/response | Optional rich-text HTML task description. |
| `comments` | request/response | Optional task comments array; each comment should include at least `body`. |
| `taskId` | response only | ID of the linked task, or `null` when the assignment has no task. |
| `task` | response only | Expanded task object with `id`, `title`, `description`, and `comments`. |

6. Zapier integration

The ResourcePlanner Zapier app uses this same workspace API access key. In Zapier, connect the account by pasting the key generated in Settings → API access for REST clients. Zapier stores it as a secret and sends it as Authorization: Bearer <YOUR_API_ACCESS_KEY>.

The current Zapier integration is a REST client on top of the endpoints below:

| Zapier capability | REST endpoint used | Notes |
| ----------------- | ------------------ | ----- |
| New Project trigger | `GET /api/projects` | Polls projects and returns normalized project fields. |
| New Resource trigger | `GET /api/resources` | Polls resources and returns normalized resource fields. |
| New Assignment trigger | `GET /api/assignments` | Supports `projectId`, `resourceId`, `dateFrom`, and `dateTo` filters. |
| Find Project search | `GET /api/projects` | Matches ID, title, or note. |
| Find Resource search | `GET /api/resources` | Matches ID, name, email, or note. |
| Find Assignment search | `GET /api/assignments` | Matches project/resource/date filters plus assignment note or task text. |
| Create Project action | `POST /api/projects` | Uses the same payload as the REST create endpoint. |
| Create Resource action | `POST /api/resources` | Uses the same payload as the REST create endpoint. |
| Create Assignment action | `POST /api/assignments` | Can include optional task title and description. |

Assignment trigger and search results include task output fields when an assignment has a linked task. The Create Assignment action exposes optional Task Title and Task Description inputs, which map to the REST title and description fields.