OpenProject#
OpenProject is registered for bounded, read-only work-package sync from one OpenProject Cloud instance. Each TeamBoost organization stores one API-token credential with an explicit project-id allowlist. Sync produces a reviewable TeamBoost import session; it does not create or change OpenProject work packages or TeamBoost tasks.
| Capability | Method | Status |
|---|---|---|
SYNC |
Pull selected projects and their work packages through API v3 | Built |
USER_IMPORT |
Bring task-linked actors into the proposed user mapping | Built as part of API sync |
CSV_IMPORT |
Upload an OpenProject work-package export | Not built |
WEBHOOK |
Receive signed OpenProject work-package events | Not built |
The endpoints below live under /api/v1/providers/openproject/.... They are the
generic provider endpoints and require an organization-scoped user token; see
Authentication.
Discovery#
GET /api/v1/providers/openproject
{
"status": "success",
"data": {
"provider": "openproject",
"capabilities": ["SYNC", "USER_IMPORT"]
}
}
Cloud setup and credential verification#
Create a dedicated OpenProject API token whose user can view work packages in every selected project. Store one strict, versioned credential envelope per TeamBoost organization:
PUT /api/v1/providers/openproject/credentials?organization_id=<id>
POST /api/v1/providers/openproject/credentials/verify?organization_id=<id>
The write-only outer request contains a JSON-serialized secret:
{
"secret": "{\"version\":1,\"baseUrl\":\"https://YOUR_TENANT.openproject.com\",\"apiToken\":\"YOUR_API_TOKEN\",\"projectIds\":[17,23]}"
}
The inner envelope accepts exactly version, baseUrl, apiToken, and
projectIds:
versionmust be1.baseUrlmust be the HTTPS root of one*.openproject.comCloud tenant. Arbitrary/self-hosted origins, IP addresses, credentials in the URL, ports, redirects, paths, query strings, and fragments are rejected.apiTokenmust be one non-empty token without whitespace or control characters.projectIdsmust be a non-empty, unique list of positive numeric OpenProject project ids. At most 100 ids are accepted.
Verification makes bounded, read-only GET probes for installation metadata,
the authenticated API root, each selected project, and one work-package page.
Malformed or provider-rejected credentials return invalid_api_key;
insufficient project permission returns insufficient_permissions; rejected
instance/project inputs return bad_request; transient, DNS, retry-budget, or
response-contract failures return service_unavailable.
Stored credentials are encrypted at rest, scoped to one TeamBoost organization,
replaceable through the same PUT, and never returned by the API. Status and
deletion use the generic GET and DELETE credential routes.
Importing work packages#
POST /api/v1/providers/openproject/imports/sync?organization_id=<id>
The adapter uses fixed-path API v3 GET requests. It reads installation
metadata, the authenticated root, selected projects, the complete status/type/
priority reference collections, selected work packages, and unique linked user
actors. Work packages are ordered by numeric id, fetched in pages of 50, and
limited to 500 per session. Duplicate, repeated, incomplete, inconsistent, or
over-limit pagination fails rather than persisting a partial import.
The client resolves the allowlisted Cloud hostname before every attempt, refuses
private/link-local/loopback results, never follows redirects, and uses at most
three attempts for network, 429, and 5xx failures with a bounded total wait.
The API token is sent only as a Bearer token and is never logged or returned.
Each successful work package retains an aligned, snake-cased source record plus a normalized task and proposed TeamBoost draft. Malformed rows are isolated as row errors without shifting task/source alignment.
User mapping#
USER_IMPORT rides work-package sync; there is no standalone user-import route.
The adapter fetches each unique linked Author, Assignee, or Responsible user once
per session. OpenProject numeric user id is the stable account key. Visible
e-mail and display name are matching hints; hidden e-mail is valid.
OpenProject can assign work to groups and placeholder users. Those principals remain sanitized provider context and do not become false TeamBoost users:
- a mapped real-user Assignee becomes proposed
ownerId; - a present but unmapped real-user Assignee creates a blocking projection error;
- an unassigned, group-assigned, or placeholder-assigned task keeps
ownerIdunset, with non-user principals called out in mapping notes; - a mapped Author becomes
creatorId; an absent or unmapped Author leaves it unset with a note; and - Responsible remains provider context and never becomes
requestedById.
Projection field coverage#
| OpenProject source | TeamBoost draft | Behavior |
|---|---|---|
Namespaced work-package id / displayId |
provider id / identifier | Stable instance-scoped identity; invalid identity blocks projection |
subject |
title |
Fewer than two usable characters blocks projection |
| Milestone structural flag | type |
Milestones → RELEASE |
| Type name | type |
Bug/Defect, Feature/User Story, Documentation, Review, Refactor, Performance, and Security map directly; custom values → OTHER plus note |
| Status and structural closed flag | status |
Canceled → CANCELED; closed → COMPLETED; blocked/hold → BLOCKED; active → IN_PROGRESS; open/backlog/custom fallback → NOT_STARTED, with notes for conservative reduction |
| Priority | priority |
Urgent/High/Medium/Low map directly; custom values → UNKNOWN plus note |
| Category | labels |
Non-empty category title becomes a label |
| Project name | projectTitle |
Preserved as the provider project name |
| Actor mappings | creatorId, ownerId |
Resolved through the session mapping as described above |
| Import lifecycle | scheduleStage |
Defaults to PENDING |
| Date-only scheduling, duration, progress, version, hierarchy, relation availability, custom fields, provider timestamps, and stable actor ids | descriptionJson.openproject |
Curated context only; no unsupported TeamBoost scheduling, release, or dependency value is invented |
The projected provider context excludes actor e-mail/name fields, credentials,
raw description variants, and HTML. The normalized plain-text description is
used as description.
Not built yet#
- OpenProject self-hosted or arbitrary instance origins.
- CSV import.
- OAuth application installation and token refresh.
- Standalone/full-directory user import.
- Webhook ingress, signature verification, replay protection, or event processing.
- Incremental sync state or work-package write-back.
- Mapping date-only fields, duration, progress, versions, hierarchy, or relations into TeamBoost scheduling, releases, or dependencies.