Utviklere
Bygg med Planitude
Et REST API, signerte webhooks og en MCP-server: hold systemene dine synkronisert med planen, reager på hver endring og la en AI-assistent jobbe med prosjektene dine.
Kode, feltnavn og den tekniske referansen er på engelsk, som i de fleste API-dokumentasjoner.
- Synkroniser oppgaver med systemene dineOpprett prosjekter og oppgaver fra et CRM, et ERP eller et skript, finn dem igjen med din egen id via
externalId, og la planleggingsmotoren beregne datoene. - Reager på hver endringMotta en signert HTTPS-forespørsel når en oppgave opprettes, fullføres eller flyttes, enten endringen kommer fra appen, API-et, en import eller en AI-assistent.
- Koble til en AI-assistentChatGPT, Claude, Gemini, Cursor og VS Code leser planene dine og foreslår endringer via MCP-serveren, med dine tillatelser og ikke mer.
Basis-URL: https://planitude.app
Forespørsler og svar er JSON over HTTPS. Varigheter og forsinkelser oppgis i arbeidsminutter (en arbeidsdag på 8 timer er 480), tidspunkter er ISO 8601 i UTC, datoer uten klokkeslett er YYYY-MM-DD.
curl https://planitude.app/api/auth/me \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/auth/me", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/auth/me",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"user": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"email": "[email protected]",
"name": "Anna Rossi",
"avatarUrl": null,
"locale": "en",
"emailVerified": true
}
}Hurtigstart
Fra null til din første webhook i tre steg. Alt du trenger er en terminal.
Opprett en API-nøkkel
Åpne Profil → API-nøkler, velg Les og skriv og kopier nøkkelen: den begynner med
gnt_og vises bare én gang. Lagre den i en miljøvariabel.Gjør ditt første kall
List opp prosjektene du kan se. Nøkkelen handler som deg: de samme prosjektene, de samme rollene.
Motta en webhook
Abonner et offentlig HTTPS-endepunkt på hendelsene du trenger, send deretter en testhendelse med en gang og verifiser signaturen.
export PLANITUDE_API_KEY="gnt_…"curl https://planitude.app/api/projects \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"projects": [
{
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"workspaceName": "Acme Construction",
"role": "owner",
"taskCount": 12,
"finishAt": "2026-10-07T15:00:00.000Z"
}
]
}curl -X POST https://planitude.app/api/webhooks \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8"
}'const res = await fetch("https://planitude.app/api/webhooks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com/hooks/planitude",
events: ["task.created", "task.completed"],
projectId: "40be00e0-7e34-4f7a-864b-5cc986f575b8",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"url": "https://example.com/hooks/planitude",
"events": ["task.created", "task.completed"],
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
},
)
res.raise_for_status()
print(res.json()){
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "webhook.ping",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"message": "Planitude webhook test",
"webhook": {
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"name": "Warehouse sync",
"events": [
"task.created",
"task.completed"
]
}
}
}Autentisering
Autentiser hver forespørsel med en personlig API-nøkkel i Authorization-headeren, som et bærertoken. Nøkler er personlige: de handler som deg, med rollen din i hvert prosjekt, aldri mer. Du kan begrense en nøkkel til ett arbeidsområde, gi den en utløpsdato og trekke den tilbake når som helst; hvert kall logges ved siden av nøkkelen.
Scopes
| Omfang | Tillater |
|---|---|
| readplanitude:read | Les prosjekter, oppgaver, avhengigheter, medlemmer, kommentarer, grunnlinjer og webhooks. |
| writeplanitude:write | Alt i lesetilgang, pluss opprette og endre prosjekter, oppgaver, avhengigheter, kommentarer, grunnlinjer og webhooks. |
Nøkler og OAuth-apper kan ikke slette prosjekter eller oppgaver: sletting skjer bare i nettappen, der en person bekrefter det. Et skript som peker på feil id kan ikke tømme en plan.
OAuth 2.1 for tredjepartsapper
Apper som handler på vegne av andre bruker OAuth 2.1: autorisasjonskode med PKCE (S256), refresh-tokens som roteres ved hver bruk, dynamisk klientregistrering (RFC 7591). Be om ressursen https://planitude.app/api og scopet planitude:read eller planitude:write.
Endepunktene er publisert i standard discovery-dokumenter, så OAuth-biblioteker konfigurerer seg selv.
https://planitude.app/.well-known/oauth-authorization-serverhttps://planitude.app/.well-known/oauth-protected-resource
God praksis
- Oppbevar nøkler i miljøvariabler eller en hemmelighetsbehandler, aldri i kode eller i et repositorium. Nøkler begynner med
gnt_, så hemmelighetsskannere kan oppdage dem. - Bruk en skrivebeskyttet nøkkel når du bare leser, og én nøkkel per integrasjon: du kan tilbakekalle én uten å stoppe de andre.
- Gi nøkler som brukes av skript en utløpsdato, og roter dem.
- Kall API-et fra serveren din, ikke fra en nettleser: en nøkkel i frontend-kode er en offentlig nøkkel.
curl https://planitude.app/api/projects \
-H "Authorization: Bearer $PLANITUDE_API_KEY"{
"issuer": "https://planitude.app",
"authorization_endpoint": "https://planitude.app/oauth/authorize",
"token_endpoint": "https://planitude.app/api/oauth/token",
"registration_endpoint": "https://planitude.app/api/oauth/register",
"revocation_endpoint": "https://planitude.app/api/oauth/revoke",
"scopes_supported": [
"planitude:read",
"planitude:write"
],
"grant_types_supported": [
"authorization_code",
"refresh_token"
],
"code_challenge_methods_supported": [
"S256"
]
}Feil
Planitude bruker standard HTTP-statuskoder. Feil har alltid samme JSON-form: en stabil error-kode å forgrene på og, når det er nyttig, details med årsaken eller feltene som må rettes.
| Status | Betydning |
|---|---|
| 400invalid_request | Forespørselen er ugyldig: details.fields lister hvert felt og problemet. |
| 401unauthorized | Nøkkelen mangler, er ugyldig, tilbakekalt eller utløpt. |
| 403forbidden | Nøkkelen eller rollen din tillater det ikke (details.reason), for eksempel en skriving med skrivebeskyttet nøkkel, eller en sletting. |
| 404not_found | Ikke funnet, eller ikke synlig for deg. |
| 409dependency_cycle | Konflikt med planen, for eksempel en avhengighet som ville lukke en syklus (dependency_cycle). |
| 429rate_limited | For mange forespørsler: vent antall sekunder oppgitt i Retry-After. |
| 500server_error | Noe gikk galt hos oss: prøv på nytt med eksponentiell backoff. |
Error
| Felt | Type | Beskrivelse |
|---|---|---|
| error påkrevd | string | Stable error code: invalid_request, unauthorized, forbidden, not_found, conflict, dependency_cycle, limit_exceeded, rate_limited, server_error, ... |
| details | object |
{
"error": "invalid_request",
"details": {
"fields": [
{
"path": "name",
"message": "Invalid input: expected string, received undefined"
},
{
"path": "durationMin",
"message": "Too small: expected number to be >=0"
}
]
}
}{
"error": "forbidden",
"details": {
"reason": "destructive"
}
}{
"error": "dependency_cycle",
"details": {
"cycles": [
{
"path": "Foundations -> Walls -> Foundations",
"taskIds": [
"4dbd104a-00cd-4035-8955-255f52ea586a",
"a22fd799-c4dc-4869-a466-0dd6e96f71ce"
],
"taskNames": [
"Foundations",
"Walls"
]
}
]
}
}Hastighetsgrenser
Grensene gjelder per nøkkel, i et glidende vindu på ett minutt: 240 leseforespørsler og 60 skriveforespørsler. Over grensen får du 429 rate_limited med en Retry-After-header, i sekunder.
Vent på Retry-After før du prøver på nytt, spre store jobber over tid og samle mange endringer i ett endringssett: opptil 1 000 endringer i én forespørsel og én omberegning.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json
{
"error": "rate_limited",
"details": {
"retryAfterSec": 12
}
}Paginering og søk
Oppgavelister er paginert med en markør. Send limit (1–500, standard 100) og, for neste side, nextCursor fra forrige svar som cursor. Når nextCursor er null, er det ingen flere sider.
Filtrer med externalId (eksakt treff på din egen id), q (navnet inneholder), updatedSince og completed; sorter med sort=-number (nyeste først) eller -updatedAt. Kortere lister, som prosjekter, medlemmer og avhengigheter, kommer hele i ett svar.
curl "https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks?limit=500" \
-H "Authorization: Bearer $PLANITUDE_API_KEY"
# next page: pass the nextCursor of the previous response
curl "https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks?limit=500&cursor=$NEXT_CURSOR" \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const tasks = [];
let cursor = null;
do {
const url = new URL("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks");
url.searchParams.set("limit", "500");
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}` },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const page = await res.json();
tasks.push(...page.tasks);
cursor = page.nextCursor;
} while (cursor);
console.log(tasks.length);import os
import requests
tasks, cursor = [], None
while True:
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
params={"limit": 500, **({"cursor": cursor} if cursor else {})},
)
res.raise_for_status()
page = res.json()
tasks += page["tasks"]
cursor = page["nextCursor"]
if not cursor:
break
print(len(tasks))Versjonering
API-et og webhook-nyttelastene er versjonert med dato. Gjeldende versjon er 2026-10-01: den står i apiVersion-feltet i hver hendelse og i info.version i OpenAPI-dokumentet.
Innenfor en versjon legger vi bare til: nye endepunkter, nye valgfrie felt, nye hendelsestyper. Felt fjernes eller endrer aldri type uten ny versjon, så ignorer feltene du ikke kjenner.
curl https://planitude.app/api/webhooks/eventsconst res = await fetch("https://planitude.app/api/webhooks/events");
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import requests
res = requests.get("https://planitude.app/api/webhooks/events")
res.raise_for_status()
print(res.json()){
"apiVersion": "2026-10-01",
"events": [
"project.created",
"project.updated",
"project.deleted",
"task.created",
"task.updated",
"task.deleted",
"task.completed",
"task.dates_changed",
"dependency.created",
"dependency.deleted",
"baseline.saved",
"member.invited",
"member.joined",
"comment.created"
]
}API-referanse
Account
Who is calling, and their workspaces.
User
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| string (email) | ||
| name | stringkan være null | |
| avatarUrl | stringkan være null | |
| locale | string | |
| emailVerified | boolean |
{
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"email": "[email protected]",
"name": "Anna Rossi",
"avatarUrl": null,
"locale": "en",
"emailVerified": true
}Workspace
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| name | string | |
| role | string | Én av: |
{
"id": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"name": "Acme Construction",
"role": "owner"
}Current user (connection test)
GET/api/auth/me
Nøkkel med lesetilgang
Returnerer
200 OK The user
| Felt | Type | Beskrivelse |
|---|---|---|
| user | User |
curl https://planitude.app/api/auth/me \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/auth/me", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/auth/me",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"user": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"email": "[email protected]",
"name": "Anna Rossi",
"avatarUrl": null,
"locale": "en",
"emailVerified": true
}
}Workspaces of the user, with role
GET/api/workspaces
Nøkkel med lesetilgang
Returnerer
200 OK Workspaces
| Felt | Type | Beskrivelse |
|---|---|---|
| workspaces | array of Workspace |
curl https://planitude.app/api/workspaces \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/workspaces", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/workspaces",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"workspaces": [
{
"id": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"name": "Acme Construction",
"role": "owner"
}
]
}API-referanse
Projects
Projects, templates and baselines.
Project
A project as returned by the write endpoints and project listings.
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| workspaceId | string (uuid) | |
| key | string | Project key, e.g. CRON (task keys are CRON-12). |
| keyLocked | boolean | |
| name | string | |
| description | stringkan være null | |
| startDate | string (date) | |
| calendarId | string (uuid)kan være null | |
| currency | string | |
| scheduleFrom | string | Én av: |
| deadline | string (date)kan være null | |
| color | stringkan være null | |
| settings | object | |
| archivedAt | string (date-time)kan være null | |
| createdBy | string (uuid)kan være null | |
| createdAt | string (date-time) | |
| updatedAt | string (date-time) |
{
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z"
}Template
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string | builtin:<slug> or the id of a template saved by you. |
| kind | string | Én av: |
| name | string | |
| description | stringkan være null | |
| taskCount | integer | |
| durationDays | integer | Working days from start to finish. |
{
"id": "builtin:website-launch",
"kind": "builtin",
"name": "Website launch",
"description": "From discovery to go-live: design, content, development, testing and launch.",
"taskCount": 12,
"durationDays": 43
}Baseline
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| name | string | |
| index | integerkan være null | Numbered MS Project baseline (1-10); null for the main baseline and the ones you name. |
| capturedAt | string (date-time) | |
| capturedBy | string (uuid)kan være null | |
| taskCount | integer |
{
"id": "b5d68d05-0640-48f9-8eeb-ed7804f4a116",
"name": "Plan v1",
"index": null,
"capturedAt": "2026-10-01T08:30:12.418Z",
"capturedBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"taskCount": 12
}List projects
GET/api/projects
Nøkkel med lesetilgang
All projects visible to the user (not paginated). ?archived=1 includes archived ones.
Spørringsparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| archived | string | Én av: |
Returnerer
200 OK Projects
| Felt | Type | Beskrivelse |
|---|---|---|
| projects | array of Project |
curl https://planitude.app/api/projects \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"projects": [
{
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"workspaceName": "Acme Construction",
"role": "owner",
"taskCount": 12,
"finishAt": "2026-10-07T15:00:00.000Z"
}
]
}Create a project
POST/api/projects
Nøkkel med skrivetilgang
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| name påkrevd | string | |
| workspaceId | string (uuid) | Defaults to your personal workspace. |
| key | string | 2-5 letters/digits, starts with a letter. Derived from the name if omitted. |
| description | stringkan være null | |
| startDate | string (date) | |
| deadline | string (date)kan være null | |
| currency | string | |
| scheduleFrom | string | Én av: |
| color | stringkan være null |
Returnerer
201 Created Created
| Felt | Type | Beskrivelse |
|---|---|---|
| project | Project |
curl -X POST https://planitude.app/api/projects \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Warehouse expansion","startDate":"2026-10-05","currency":"EUR"}'const res = await fetch("https://planitude.app/api/projects", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Warehouse expansion",
startDate: "2026-10-05",
currency: "EUR",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/projects",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"name": "Warehouse expansion",
"startDate": "2026-10-05",
"currency": "EUR",
},
)
res.raise_for_status()
print(res.json()){
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z"
}
}Create a project from a template
POST/api/projects/from-template
Nøkkel med skrivetilgang
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| templateId påkrevd | string | Id from GET /api/templates. |
| startDate påkrevd | string (date) | |
| name | string | |
| key | string | |
| locale | string | Language of the template texts (en, it, es, fr, de, pt, nl, pl, ja, zh, sv, da, no, fi, cs, ro, uk, tr, ar, he, hi, id, vi, ko). |
| tz | string | IANA time zone of the project calendar. |
| workspaceId | string (uuid) |
Returnerer
201 Created Created
| Felt | Type | Beskrivelse |
|---|---|---|
| project | Project | |
| taskCount | integer | |
| conflicts | array of Conflict |
curl -X POST https://planitude.app/api/projects/from-template \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "builtin:website-launch",
"startDate": "2026-10-05",
"name": "Website relaunch",
"locale": "en"
}'const res = await fetch("https://planitude.app/api/projects/from-template", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
templateId: "builtin:website-launch",
startDate: "2026-10-05",
name: "Website relaunch",
locale: "en",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/projects/from-template",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"templateId": "builtin:website-launch",
"startDate": "2026-10-05",
"name": "Website relaunch",
"locale": "en",
},
)
res.raise_for_status()
print(res.json()){
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z"
},
"taskCount": 12,
"conflicts": []
}List project templates
GET/api/templates
Nøkkel med lesetilgang
Spørringsparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| locale | string |
Returnerer
200 OK Templates
| Felt | Type | Beskrivelse |
|---|---|---|
| templates | array of Template |
curl https://planitude.app/api/templates \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/templates", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/templates",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"templates": [
{
"id": "builtin:website-launch",
"kind": "builtin",
"name": "Website launch",
"description": "From discovery to go-live: design, content, development, testing and launch.",
"taskCount": 12,
"durationDays": 43
}
]
}Full project (tasks tree, dependencies, resources, members, baselines)
GET/api/projects/{projectId}
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Returnerer
200 OK Project
| Felt | Type | Beskrivelse |
|---|---|---|
| project | Project | |
| tasks | array of Task | |
| dependencies | array of Dependency |
curl https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8 \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z"
},
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"sortKey": "i",
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null
}
],
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
]
}Update a project
PATCH/api/projects/{projectId}
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| name | string | |
| description | stringkan være null | |
| startDate | string (date) | |
| deadline | string (date)kan være null | |
| currency | string | |
| scheduleFrom | string | Én av: |
| color | stringkan være null | |
| archived | boolean |
Returnerer
200 OK Updated
| Felt | Type | Beskrivelse |
|---|---|---|
| project | Project | |
| conflicts | array of Conflict | |
| rescheduled | boolean | The schedule was recalculated (start date, calendar or direction changed). |
curl -X PATCH https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8 \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"deadline":"2026-12-18"}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
deadline: "2026-12-18",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.patch(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"deadline": "2026-12-18",
},
)
res.raise_for_status()
print(res.json()){
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"keyLocked": false,
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"calendarId": null,
"currency": "EUR",
"scheduleFrom": "forward",
"deadline": null,
"color": null,
"settings": {},
"archivedAt": null,
"createdBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z"
},
"conflicts": [],
"rescheduled": false
}List baselines
GET/api/projects/{projectId}/baseline
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Returnerer
200 OK Baselines
| Felt | Type | Beskrivelse |
|---|---|---|
| baselines | array of Baseline |
curl https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/baseline \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/baseline", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/baseline",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"baselines": [
{
"id": "b5d68d05-0640-48f9-8eeb-ed7804f4a116",
"name": "Plan v1",
"index": null,
"capturedAt": "2026-10-01T08:30:12.418Z",
"capturedBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"taskCount": 12
}
]
}Save a baseline
POST/api/projects/{projectId}/baseline
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| name | string |
Returnerer
201 Created Saved
| Felt | Type | Beskrivelse |
|---|---|---|
| baseline | Baseline |
curl -X POST https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/baseline \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Plan v1"}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/baseline", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Plan v1",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/baseline",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"name": "Plan v1",
},
)
res.raise_for_status()
print(res.json()){
"baseline": {
"id": "b5d68d05-0640-48f9-8eeb-ed7804f4a116",
"name": "Plan v1",
"index": null,
"capturedAt": "2026-10-01T08:30:12.418Z",
"capturedBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"taskCount": 12
}
}API-referanse
Tasks
Tasks, search by external id, comments.
Task
Task representation of GET /tasks and webhook payloads: the stored task (without sortKey) plus project, assignees and link.
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| number | integer | Sequential number in the project, never reused. |
| key | string | Human key, e.g. CRON-12. |
| parentId | string (uuid)kan være null | |
| name | string | |
| type | string | Én av: |
| durationMin | integer | Duration in working minutes (8h day = 480). |
| workMin | integer | |
| progressPct | number | |
| constraintKind | string | Én av: |
| constraintDate | string (date-time)kan være null | |
| deadline | string (date-time)kan være null | |
| calendarId | string (uuid)kan være null | |
| costFixed | number | |
| notes | stringkan være null | |
| color | stringkan være null | |
| wbs | stringkan være null | |
| externalId | stringkan være null | Your identifier for this task in another system. Searchable with GET /tasks?externalId=. |
| startAt | string (date-time)kan være null | Computed start. |
| finishAt | string (date-time)kan være null | Computed finish. |
| isCritical | boolean | On the critical path. |
| totalFloatMin | integerkan være null | Total float (slack) in working minutes. |
| earlyStartAt | string (date-time)kan være null | |
| lateFinishAt | string (date-time)kan være null | |
| actualStartAt | string (date-time)kan være null | |
| actualFinishAt | string (date-time)kan være null | |
| actualDurationMin | integerkan være null | |
| remainingDurationMin | integerkan være null | |
| manuallyScheduled | boolean | |
| levelingDelayMin | integer | |
| taskType | string | Én av: |
| effortDriven | boolean | |
| durationOptimisticMin | integerkan være null | |
| durationPessimisticMin | integerkan være null | |
| projectId | string (uuid) | |
| completed | boolean | progressPct = 100. |
| assignees | array of Assignee | |
| url | string (uri) | Page of the task in the web app. |
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}WriteResult
Attributter
| Felt | Type | Beskrivelse | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tasks | array of Task | Created/updated tasks plus the ones the recalculation moved. | |||||||||||||||
| deletedTaskIds | array of string | ||||||||||||||||
| dependencies | array of Dependency | ||||||||||||||||
| deletedDependencyIds | array of string | ||||||||||||||||
| conflicts | array of Conflict | ||||||||||||||||
| projectStartAt | string (date-time) | ||||||||||||||||
| projectFinishAt | string (date-time) | ||||||||||||||||
| stats | object | Vis feltene til stats
|
{
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"sortKey": "i",
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null
}
],
"deletedTaskIds": [],
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
],
"deletedDependencyIds": [],
"conflicts": [],
"projectStartAt": "2026-10-05T06:00:00.000Z",
"projectFinishAt": "2026-10-07T15:00:00.000Z",
"stats": {
"taskCount": 12,
"recomputedCount": 3,
"savedCount": 2,
"durationMs": 39
}
}Comment
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| taskId | string (uuid) | |
| userId | string (uuid) | |
| authorName | string | |
| authorAvatarUrl | stringkan være null | |
| body | string | |
| mentions | array of string | |
| createdAt | string (date-time) | |
| editedAt | string (date-time)kan være null |
{
"id": "0fc2dec5-a409-47c9-9c6e-0663e8f8bcf3",
"taskId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"authorName": "Anna Rossi",
"authorAvatarUrl": null,
"body": "Concrete delivered, we can start the walls.",
"mentions": [],
"createdAt": "2026-10-01T08:30:12.418Z",
"editedAt": null
}List or search tasks (paginated)
GET/api/projects/{projectId}/tasks
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Spørringsparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| limit | integer | 1-500. Standard: |
| cursor | string | nextCursor of the previous page. |
| sort | string | -number = newest first (polling triggers). -updatedAt returns the first page only.Én av: Standard: |
| externalId | string | Exact match on externalId. |
| q | string | Name contains (case-insensitive). |
| updatedSince | string (date-time) | |
| completed | string | Én av: |
Returnerer
200 OK A page of tasks
| Felt | Type | Beskrivelse |
|---|---|---|
| tasks | array of Task | |
| nextCursor | stringkan være null |
curl "https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks?externalId=crm-4711" \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks?externalId=crm-4711", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
params={
"externalId": "crm-4711",
},
)
res.raise_for_status()
print(res.json()){
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}
],
"nextCursor": null
}Create a task, or apply a change set
POST/api/projects/{projectId}/tasks
Nøkkel med skrivetilgang
Send a TaskCreate to create one task (201), or a ChangeSet to apply several changes in one transaction (200). Dates are recalculated by the scheduling engine.
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Forespørselsinnhold
TaskCreate
| Felt | Type | Beskrivelse |
|---|---|---|
| name påkrevd | string | |
| parentId | string (uuid)kan være null | Parent (summary) task; null = top level. |
| afterTaskId | string (uuid)kan være null | Insert after this sibling. |
| beforeTaskId | string (uuid)kan være null | Insert before this sibling. |
| type | string | Én av: |
| durationMin | integer | Duration in working minutes (8h day = 480). |
| workMin | integer | |
| progressPct | number | |
| constraintKind | string | Én av: |
| constraintDate | string (date-time)kan være null | |
| deadline | string (date-time)kan være null | |
| calendarId | string (uuid)kan være null | |
| costFixed | number | |
| notes | stringkan være null | |
| color | stringkan være null | |
| wbs | stringkan være null | |
| externalId | stringkan være null | Your identifier for this task in another system. Searchable with GET /tasks?externalId=. |
eller ChangeSet
| Felt | Type | Beskrivelse |
|---|---|---|
| createTasks | array of TaskCreate | |
| updateTasks | array of any | |
| createDependencies | array of DependencyCreate | |
| deleteDependencyIds | array of string | |
| fullReschedule | boolean |
Returnerer
201 Created Task created
| Felt | Type | Beskrivelse | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tasks | array of Task | Created/updated tasks plus the ones the recalculation moved. | |||||||||||||||
| deletedTaskIds | array of string | ||||||||||||||||
| dependencies | array of Dependency | ||||||||||||||||
| deletedDependencyIds | array of string | ||||||||||||||||
| conflicts | array of Conflict | ||||||||||||||||
| projectStartAt | string (date-time) | ||||||||||||||||
| projectFinishAt | string (date-time) | ||||||||||||||||
| stats | object | Vis feltene til stats
|
curl -X POST https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Foundations","durationMin":1440,"externalId":"crm-4711"}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Foundations",
durationMin: 1440,
externalId: "crm-4711",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"name": "Foundations",
"durationMin": 1440,
"externalId": "crm-4711",
},
)
res.raise_for_status()
print(res.json()){
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"sortKey": "i",
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null
}
],
"deletedTaskIds": [],
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
],
"deletedDependencyIds": [],
"conflicts": [],
"projectStartAt": "2026-10-05T06:00:00.000Z",
"projectFinishAt": "2026-10-07T15:00:00.000Z",
"stats": {
"taskCount": 12,
"recomputedCount": 3,
"savedCount": 2,
"durationMs": 39
}
}Get a task
GET/api/projects/{projectId}/tasks/{taskId}
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
| taskId påkrevd | string (uuid) | Task id. |
Returnerer
200 OK The task
| Felt | Type | Beskrivelse |
|---|---|---|
| task | Task |
curl https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}
}Update a task
PATCH/api/projects/{projectId}/tasks/{taskId}
Nøkkel med skrivetilgang
Only the fields you send change; null clears a field.
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
| taskId påkrevd | string (uuid) | Task id. |
Forespørselsinnhold
| Felt | Type | Beskrivelse | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| name | string | |||||||||||||
| type | string | Én av: | ||||||||||||
| durationMin | integer | Duration in working minutes (8h day = 480). | ||||||||||||
| workMin | integer | |||||||||||||
| progressPct | number | |||||||||||||
| constraintKind | string | Én av: | ||||||||||||
| constraintDate | string (date-time)kan være null | |||||||||||||
| deadline | string (date-time)kan være null | |||||||||||||
| calendarId | string (uuid)kan være null | |||||||||||||
| costFixed | number | |||||||||||||
| notes | stringkan være null | |||||||||||||
| color | stringkan være null | |||||||||||||
| wbs | stringkan være null | |||||||||||||
| externalId | stringkan være null | Your identifier for this task in another system. Searchable with GET /tasks?externalId=. | ||||||||||||
| placement | object | Vis feltene til placement
|
Returnerer
200 OK Updated
| Felt | Type | Beskrivelse | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tasks | array of Task | Created/updated tasks plus the ones the recalculation moved. | |||||||||||||||
| deletedTaskIds | array of string | ||||||||||||||||
| dependencies | array of Dependency | ||||||||||||||||
| deletedDependencyIds | array of string | ||||||||||||||||
| conflicts | array of Conflict | ||||||||||||||||
| projectStartAt | string (date-time) | ||||||||||||||||
| projectFinishAt | string (date-time) | ||||||||||||||||
| stats | object | Vis feltene til stats
|
curl -X PATCH https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"progressPct":100}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
progressPct: 100,
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.patch(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"progressPct": 100,
},
)
res.raise_for_status()
print(res.json()){
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"sortKey": "i",
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null
}
],
"deletedTaskIds": [],
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
],
"deletedDependencyIds": [],
"conflicts": [],
"projectStartAt": "2026-10-05T06:00:00.000Z",
"projectFinishAt": "2026-10-07T15:00:00.000Z",
"stats": {
"taskCount": 12,
"recomputedCount": 3,
"savedCount": 2,
"durationMs": 39
}
}Comments of a task
GET/api/projects/{projectId}/tasks/{taskId}/comments
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
| taskId påkrevd | string (uuid) | Task id. |
Returnerer
200 OK Comments
| Felt | Type | Beskrivelse |
|---|---|---|
| comments | array of Comment |
curl https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/comments \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/comments", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/comments",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"comments": [
{
"id": "0fc2dec5-a409-47c9-9c6e-0663e8f8bcf3",
"taskId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"authorName": "Anna Rossi",
"authorAvatarUrl": null,
"body": "Concrete delivered, we can start the walls.",
"mentions": [],
"createdAt": "2026-10-01T08:30:12.418Z",
"editedAt": null
}
]
}Comment on a task
POST/api/projects/{projectId}/tasks/{taskId}/comments
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
| taskId påkrevd | string (uuid) | Task id. |
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| body påkrevd | string | Plain text. |
| mentions | array of string | User ids to notify. |
Returnerer
201 Created Created
| Felt | Type | Beskrivelse |
|---|---|---|
| comment | Comment |
curl -X POST https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/comments \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"body":"Concrete delivered, we can start the walls."}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/comments", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
body: "Concrete delivered, we can start the walls.",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/comments",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"body": "Concrete delivered, we can start the walls.",
},
)
res.raise_for_status()
print(res.json()){
"comment": {
"id": "0fc2dec5-a409-47c9-9c6e-0663e8f8bcf3",
"taskId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"authorName": "Anna Rossi",
"authorAvatarUrl": null,
"body": "Concrete delivered, we can start the walls.",
"mentions": [],
"createdAt": "2026-10-01T08:30:12.418Z",
"editedAt": null
}
}API-referanse
Dependencies
Links between tasks (FS, SS, FF, SF, with lag).
Dependency
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| predecessorId | string (uuid) | |
| successorId | string (uuid) | |
| type | string | Én av: |
| lagMin | integer | Working minutes; negative = lead. |
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}List dependencies
GET/api/projects/{projectId}/dependencies
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Returnerer
200 OK Dependencies
| Felt | Type | Beskrivelse |
|---|---|---|
| dependencies | array of Dependency |
curl https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
]
}Create (or update) a dependency
POST/api/projects/{projectId}/dependencies
Nøkkel med skrivetilgang
A dependency that would close a cycle is refused with 409 dependency_cycle.
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Forespørselsinnhold
DependencyCreate
| Felt | Type | Beskrivelse |
|---|---|---|
| predecessorId påkrevd | string (uuid) | |
| successorId påkrevd | string (uuid) | |
| type | string | Én av: Standard: |
| lagMin | integer | Standard: |
eller dependencies
| Felt | Type | Beskrivelse |
|---|---|---|
| dependencies påkrevd | array of DependencyCreate |
Returnerer
201 Created Created
| Felt | Type | Beskrivelse | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tasks | array of Task | Created/updated tasks plus the ones the recalculation moved. | |||||||||||||||
| deletedTaskIds | array of string | ||||||||||||||||
| dependencies | array of Dependency | ||||||||||||||||
| deletedDependencyIds | array of string | ||||||||||||||||
| conflicts | array of Conflict | ||||||||||||||||
| projectStartAt | string (date-time) | ||||||||||||||||
| projectFinishAt | string (date-time) | ||||||||||||||||
| stats | object | Vis feltene til stats
|
curl -X POST https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
predecessorId: "4dbd104a-00cd-4035-8955-255f52ea586a",
successorId: "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
type: "FS",
lagMin: 0,
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0,
},
)
res.raise_for_status()
print(res.json()){
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"sortKey": "i",
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null
}
],
"deletedTaskIds": [],
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
],
"deletedDependencyIds": [],
"conflicts": [],
"projectStartAt": "2026-10-05T06:00:00.000Z",
"projectFinishAt": "2026-10-07T15:00:00.000Z",
"stats": {
"taskCount": 12,
"recomputedCount": 3,
"savedCount": 2,
"durationMs": 39
}
}Remove a dependency
DEL/api/projects/{projectId}/dependencies/{dependencyId}
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
| dependencyId påkrevd | string (uuid) |
Returnerer
200 OK Removed
| Felt | Type | Beskrivelse | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tasks | array of Task | Created/updated tasks plus the ones the recalculation moved. | |||||||||||||||
| deletedTaskIds | array of string | ||||||||||||||||
| dependencies | array of Dependency | ||||||||||||||||
| deletedDependencyIds | array of string | ||||||||||||||||
| conflicts | array of Conflict | ||||||||||||||||
| projectStartAt | string (date-time) | ||||||||||||||||
| projectFinishAt | string (date-time) | ||||||||||||||||
| stats | object | Vis feltene til stats
|
curl -X DELETE https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies/9ba5faf8-923d-4ecc-86f0-f245c5d179db \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies/9ba5faf8-923d-4ecc-86f0-f245c5d179db", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(res.status); // 204import os
import requests
res = requests.delete(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/dependencies/9ba5faf8-923d-4ecc-86f0-f245c5d179db",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.status_code) # 204{
"tasks": [
{
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"sortKey": "i",
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null
}
],
"deletedTaskIds": [],
"dependencies": [
{
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
],
"deletedDependencyIds": [],
"conflicts": [],
"projectStartAt": "2026-10-05T06:00:00.000Z",
"projectFinishAt": "2026-10-07T15:00:00.000Z",
"stats": {
"taskCount": 12,
"recomputedCount": 3,
"savedCount": 2,
"durationMs": 39
}
}API-referanse
People
Project members and task assignees.
Member
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| userId | string (uuid) | |
| name | string | |
| string | ||
| role | string | Effective role on the project. Én av: |
| directRole | stringkan være null | Role granted on the project itself (null = only through the workspace). Én av: |
| inherited | boolean | Access comes from the workspace. |
| resourceId | string (uuid)kan være null | Resource used when the person is assigned to tasks. |
| addedAt | string (date-time) | |
| avatarUrl | stringkan være null |
{
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"email": "[email protected]",
"role": "owner",
"directRole": null,
"inherited": false,
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"addedAt": "2026-10-01T08:30:12.418Z",
"avatarUrl": null
}Assignee
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| resourceId | string (uuid) | |
| userId | string (uuid)kan være null | |
| name | string | |
| unitsPct | integer |
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}Replace the people assigned to a task
PUT/api/projects/{projectId}/tasks/{taskId}/assignees
Nøkkel med skrivetilgang
userIds must be members of the project (GET /members). An empty list removes everyone. Optional resourceIds replaces the people imported from a file (resources without an account) assigned to the task; omit it to leave them as they are.
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
| taskId påkrevd | string (uuid) | Task id. |
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| userIds påkrevd | array of string | |
| resourceIds | array of string |
Returnerer
200 OK Assignees saved
| Felt | Type | Beskrivelse | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| taskId | string (uuid) | |||||||||||||||||||||||||||||||||||||
| assignments | array of object | Vis feltene til assignments
| ||||||||||||||||||||||||||||||||||||
| resources | array of object | Vis feltene til resources
| ||||||||||||||||||||||||||||||||||||
| needsReschedule | boolean | |||||||||||||||||||||||||||||||||||||
| conflicts | array of Conflict |
curl -X PUT https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/assignees \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"userIds":["b1666432-132a-4ea9-b1ae-76ea69e226c5"]}'const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/assignees", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
userIds: ["b1666432-132a-4ea9-b1ae-76ea69e226c5"],
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.put(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/tasks/4dbd104a-00cd-4035-8955-255f52ea586a/assignees",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"userIds": ["b1666432-132a-4ea9-b1ae-76ea69e226c5"],
},
)
res.raise_for_status()
print(res.json()){
"taskId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"assignments": [
{
"id": "e62ac96b-e68e-40d3-842e-335e27dfd099",
"taskId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"unitsPct": 100,
"workMin": 0
}
],
"resources": [
{
"id": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"kind": "builtin",
"email": "[email protected]",
"costPerHour": 0,
"costPerUse": 0,
"capacityPct": 0,
"calendarId": null,
"color": null,
"avatarUrl": null
}
],
"needsReschedule": false,
"conflicts": []
}People with access to the project (assignable)
GET/api/projects/{projectId}/members
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| projectId påkrevd | string (uuid) | Project id. |
Returnerer
200 OK Members
| Felt | Type | Beskrivelse |
|---|---|---|
| members | array of Member | |
| role | string |
curl https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/members \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/members", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8/members",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"members": [
{
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"email": "[email protected]",
"role": "owner",
"directRole": null,
"inherited": false,
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"addedAt": "2026-10-01T08:30:12.418Z",
"avatarUrl": null
}
],
"role": "owner"
}API-referanse
Webhooks
Outgoing webhook subscriptions (REST hooks: subscribe/unsubscribe).
- GET/api/webhooks
- POST/api/webhooks
- GET/api/webhooks/events
- GET/api/webhooks/{webhookId}
- PATCH/api/webhooks/{webhookId}
- DELETE/api/webhooks/{webhookId}
- GET/api/webhooks/{webhookId}/deliveries
- GET/api/webhooks/{webhookId}/deliveries/{deliveryId}
- POST/api/webhooks/{webhookId}/deliveries/{deliveryId}/redeliver
- POST/api/webhooks/{webhookId}/test
- POST/api/webhooks/{webhookId}/rotate-secret
Webhook
Attributter
| Felt | Type | Beskrivelse | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| id | string (uuid) | ||||||||||
| workspaceId | string (uuid) | ||||||||||
| workspaceName | string | ||||||||||
| projectId | string (uuid)kan være null | null = every project of the workspace. | |||||||||
| projectName | stringkan være null | ||||||||||
| name | string | ||||||||||
| url | string (uri) | ||||||||||
| events | array of string | Én av: | |||||||||
| secretPrefix | string | First characters of the signing secret (not secret). | |||||||||
| active | boolean | ||||||||||
| disabledReason | stringkan være null | Én av: | |||||||||
| disabledAt | string (date-time)kan være null | ||||||||||
| consecutiveFailures | integer | ||||||||||
| viaApi | boolean | Created with the API (REST hook) rather than from the profile. | |||||||||
| createdBy | objectkan være null | Vis feltene til createdBy
| |||||||||
| createdAt | string (date-time) | ||||||||||
| updatedAt | string (date-time) | ||||||||||
| lastDeliveryAt | string (date-time)kan være null | ||||||||||
| lastSuccessAt | string (date-time)kan være null |
{
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
}Delivery
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| eventId | string (uuid) | |
| eventType | string | |
| status | string | Én av: |
| attempts | integer | |
| nextAttemptAt | string (date-time)kan være null | |
| lastAttemptAt | string (date-time)kan være null | |
| responseStatus | integerkan være null | |
| responseExcerpt | stringkan være null | |
| error | stringkan være null | |
| durationMs | integerkan være null | |
| manual | boolean | |
| createdAt | string (date-time) |
{
"id": "4b207161-80f9-40bb-bc3f-d8f70315be00",
"eventId": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"eventType": "task.completed",
"status": "success",
"attempts": 1,
"nextAttemptAt": null,
"lastAttemptAt": "2026-10-01T08:30:12.418Z",
"responseStatus": 200,
"responseExcerpt": "{\"ok\":true}",
"error": null,
"durationMs": 39,
"manual": false,
"createdAt": "2026-10-01T08:30:12.418Z"
}Event
Attributter
| Felt | Type | Beskrivelse | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| id påkrevd | string (uuid) | Event id, also in the Planitude-Event-Id header: use it to deduplicate. | |||||||||
| type påkrevd | string | Én av: | |||||||||
| apiVersion påkrevd | string | Én av: | |||||||||
| createdAt påkrevd | string (date-time) | ||||||||||
| workspaceId påkrevd | string (uuid) | ||||||||||
| projectId | string (uuid)kan være null | ||||||||||
| actor | objectkan være null | Who made the change (null for system changes).Vis feltene til actor
| |||||||||
| data påkrevd | object |
{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "project.created",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {}
}Project (event payload)
Compact project representation used in webhook payloads.
Attributter
| Felt | Type | Beskrivelse |
|---|---|---|
| id | string (uuid) | |
| workspaceId | string (uuid) | |
| key | string | |
| name | string | |
| description | stringkan være null | |
| startDate | string (date) | |
| deadline | string (date)kan være null | |
| currency | string | |
| scheduleFrom | string | Én av: |
| color | stringkan være null | |
| archived | boolean | |
| createdAt | string (date-time) | |
| updatedAt | string (date-time) | |
| url | string (uri) |
{
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"deadline": null,
"currency": "EUR",
"scheduleFrom": "forward",
"color": null,
"archived": false,
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"url": "https://planitude.app/app/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8"
}List webhook subscriptions
GET/api/webhooks
Nøkkel med lesetilgang
Spørringsparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| workspaceId | string (uuid) | |
| projectId | string (uuid) |
Returnerer
200 OK Subscriptions
| Felt | Type | Beskrivelse |
|---|---|---|
| webhooks | array of Webhook |
curl https://planitude.app/api/webhooks \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/webhooks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"webhooks": [
{
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
}
]
}Subscribe (REST hook)
POST/api/webhooks
Nøkkel med skrivetilgang
Creates a subscription. The response contains the signing secret: it is shown only once. Aliases accepted for automation platforms: targetUrl for url, event for a single event.
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| url påkrevd | string (uri) | HTTPS endpoint that receives the events. Public addresses only. |
| events påkrevd | array of string | * = all events.Én av: |
| name | string | |
| projectId | string (uuid) | Limit to one project (editor role needed). Omit for the whole workspace (owner/admin). |
| workspaceId | string (uuid) |
Returnerer
201 Created Created
| Felt | Type | Beskrivelse |
|---|---|---|
| webhook | Webhook | |
| secret | string | whsec_... |
curl -X POST https://planitude.app/api/webhooks \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8"
}'const res = await fetch("https://planitude.app/api/webhooks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com/hooks/planitude",
events: ["task.created", "task.completed"],
projectId: "40be00e0-7e34-4f7a-864b-5cc986f575b8",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"url": "https://example.com/hooks/planitude",
"events": ["task.created", "task.completed"],
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
},
)
res.raise_for_status()
print(res.json()){
"webhook": {
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
},
"secret": "whsec_3dvU0T1oaYlW4kH6m2Vb8nqXcR9eZpLsYw1QhGk"
}Event catalog (public)
GET/api/webhooks/events
Offentlig, ingen nøkkel
Returnerer
200 OK Events
| Felt | Type | Beskrivelse |
|---|---|---|
| apiVersion | string | |
| events | array of string |
curl https://planitude.app/api/webhooks/eventsconst res = await fetch("https://planitude.app/api/webhooks/events");
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import requests
res = requests.get("https://planitude.app/api/webhooks/events")
res.raise_for_status()
print(res.json()){
"apiVersion": "2026-10-01",
"events": [
"project.created",
"project.updated",
"project.deleted",
"task.created",
"task.updated",
"task.deleted",
"task.completed",
"task.dates_changed",
"dependency.created",
"dependency.deleted",
"baseline.saved",
"member.invited",
"member.joined",
"comment.created"
]
}Get a subscription
GET/api/webhooks/{webhookId}
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
Returnerer
200 OK Subscription
| Felt | Type | Beskrivelse |
|---|---|---|
| webhook | Webhook |
curl https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88 \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"webhook": {
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
}
}Update, pause or resume a subscription
PATCH/api/webhooks/{webhookId}
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
Forespørselsinnhold
| Felt | Type | Beskrivelse |
|---|---|---|
| name | string | |
| url | string (uri) | |
| events | array of string | |
| active | boolean | false = pause; true = resume (also resets the failure counter). |
Returnerer
200 OK Updated
| Felt | Type | Beskrivelse |
|---|---|---|
| webhook | Webhook |
curl -X PATCH https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88 \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"active":false}'const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
active: false,
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.patch(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"active": False,
},
)
res.raise_for_status()
print(res.json()){
"webhook": {
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
}
}Unsubscribe (REST hook)
DEL/api/webhooks/{webhookId}
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
Returnerer
204 No Content Deleted
curl -X DELETE https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88 \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(res.status); // 204import os
import requests
res = requests.delete(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.status_code) # 204Delivery log (newest first, kept 30 days)
GET/api/webhooks/{webhookId}/deliveries
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
Spørringsparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| limit | integer | 1-100. Standard: |
| before | string (date-time) | nextCursor of the previous page. |
Returnerer
200 OK Deliveries
| Felt | Type | Beskrivelse |
|---|---|---|
| deliveries | array of Delivery | |
| nextCursor | stringkan være null |
curl https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"deliveries": [
{
"id": "4b207161-80f9-40bb-bc3f-d8f70315be00",
"eventId": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"eventType": "task.completed",
"status": "success",
"attempts": 1,
"nextAttemptAt": null,
"lastAttemptAt": "2026-10-01T08:30:12.418Z",
"responseStatus": 200,
"responseExcerpt": "{\"ok\":true}",
"error": null,
"durationMs": 39,
"manual": false,
"createdAt": "2026-10-01T08:30:12.418Z"
}
],
"nextCursor": null
}Body sent with a delivery
GET/api/webhooks/{webhookId}/deliveries/{deliveryId}
Nøkkel med lesetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
| deliveryId påkrevd | string (uuid) |
Returnerer
200 OK Payload
| Felt | Type | Beskrivelse |
|---|---|---|
| payload | Event |
curl https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries/4b207161-80f9-40bb-bc3f-d8f70315be00 \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries/4b207161-80f9-40bb-bc3f-d8f70315be00", {
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.get(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries/4b207161-80f9-40bb-bc3f-d8f70315be00",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"payload": {
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "project.created",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {}
}
}Send the same event again
POST/api/webhooks/{webhookId}/deliveries/{deliveryId}/redeliver
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
| deliveryId påkrevd | string (uuid) |
Returnerer
202 Accepted Queued
| Felt | Type | Beskrivelse |
|---|---|---|
| delivery | Delivery |
curl -X POST https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries/4b207161-80f9-40bb-bc3f-d8f70315be00/redeliver \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries/4b207161-80f9-40bb-bc3f-d8f70315be00/redeliver", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/deliveries/4b207161-80f9-40bb-bc3f-d8f70315be00/redeliver",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"delivery": {
"id": "4b207161-80f9-40bb-bc3f-d8f70315be00",
"eventId": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"eventType": "task.completed",
"status": "success",
"attempts": 1,
"nextAttemptAt": null,
"lastAttemptAt": "2026-10-01T08:30:12.418Z",
"responseStatus": 200,
"responseExcerpt": "{\"ok\":true}",
"error": null,
"durationMs": 39,
"manual": false,
"createdAt": "2026-10-01T08:30:12.418Z"
}
}Send a webhook.ping test event
POST/api/webhooks/{webhookId}/test
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
Returnerer
202 Accepted Queued
| Felt | Type | Beskrivelse |
|---|---|---|
| delivery | Delivery |
curl -X POST https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/test \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/test", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/test",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"delivery": {
"id": "4b207161-80f9-40bb-bc3f-d8f70315be00",
"eventId": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"eventType": "task.completed",
"status": "success",
"attempts": 1,
"nextAttemptAt": null,
"lastAttemptAt": "2026-10-01T08:30:12.418Z",
"responseStatus": 200,
"responseExcerpt": "{\"ok\":true}",
"error": null,
"durationMs": 39,
"manual": false,
"createdAt": "2026-10-01T08:30:12.418Z"
}
}Generate a new signing secret
POST/api/webhooks/{webhookId}/rotate-secret
Nøkkel med skrivetilgang
Baneparametere
| Felt | Type | Beskrivelse |
|---|---|---|
| webhookId påkrevd | string (uuid) | Webhook id. |
Returnerer
200 OK New secret (shown once)
| Felt | Type | Beskrivelse |
|---|---|---|
| webhook | Webhook | |
| secret | string |
curl -X POST https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/rotate-secret \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/rotate-secret", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/rotate-secret",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"webhook": {
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
},
"secret": "whsec_3dvU0T1oaYlW4kH6m2Vb8nqXcR9eZpLsYw1QhGk"
}Webhooks
Webhooks
Webhooks sender en HTTPS-POST med JSON-innhold til endepunktet ditt så snart noe endres, enten endringen kommer fra nettappen, API-et, MCP-serveren eller en import. En webhook dekker ett prosjekt, eller alle prosjektene i et arbeidsområde (eiere og administratorer).
Opprett dem i Profil → Webhooks eller med API-et, som REST-hooks: abonner med POST /api/webhooks, avslutt abonnementet med DELETE. Signeringshemmeligheten vises bare én gang.
Hver forespørsel har disse headerne:
| Header | Beskrivelse |
|---|---|
| Planitude-Signature | t=<unix seconds>,v1=<hex HMAC-SHA256>: see Verify signatures. |
| Planitude-Event | Event type, e.g. task.completed. |
| Planitude-Event-Id | Event id, the same in every retry: use it to deduplicate. |
| Planitude-Delivery | Id of this delivery (changes with a manual resend). |
| User-Agent | Planitude-Webhooks/1.0 (+https://planitude.app/developers) |
| Content-Type | application/json |
curl -X POST https://planitude.app/api/webhooks \
-H "Authorization: Bearer $PLANITUDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8"
}'const res = await fetch("https://planitude.app/api/webhooks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com/hooks/planitude",
events: ["task.created", "task.completed"],
projectId: "40be00e0-7e34-4f7a-864b-5cc986f575b8",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
json={
"url": "https://example.com/hooks/planitude",
"events": ["task.created", "task.completed"],
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
},
)
res.raise_for_status()
print(res.json()){
"webhook": {
"id": "1747ee7f-a395-4d3c-94b0-54b513d71d88",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"workspaceName": "Acme Construction",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"projectName": "Warehouse expansion",
"name": "Warehouse sync",
"url": "https://example.com/hooks/planitude",
"events": [
"task.created",
"task.completed"
],
"secretPrefix": "whsec_Fdwl",
"active": true,
"disabledReason": null,
"disabledAt": null,
"consecutiveFailures": 0,
"viaApi": true,
"createdBy": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"lastDeliveryAt": "2026-10-01T08:30:12.418Z",
"lastSuccessAt": "2026-10-01T08:30:12.418Z"
},
"secret": "whsec_3dvU0T1oaYlW4kH6m2Vb8nqXcR9eZpLsYw1QhGk"
}Hendelsestyper
Abonner på enkeltstående hendelser, eller på * for alle. Alle hendelser har samme konvolutt; data endres med typen.
| Hendelse | Beskrivelse |
|---|---|
| project.created | A project was created (blank, from a template, duplicated or imported from MS Project). |
| project.updated | Project fields changed (name, dates, deadline, archive...), or a saved version was restored. |
| project.deleted | A project was deleted. |
| task.created | A task was created. |
| task.updated | Task fields or assignees changed. changes lists only the fields that changed. |
| task.deleted | A task was deleted (one event per task of a deleted branch). |
| task.completed | Task progress reached 100%. |
| task.dates_changed | Start or finish moved, because of an edit (cause: edit) or because the schedule was recalculated (cause: reschedule). |
| dependency.created | A dependency was created or changed. |
| dependency.deleted | A dependency was removed. |
| baseline.saved | A baseline was saved. |
| member.invited | An invite link was created for the project. |
| member.joined | A person joined the project. |
| comment.created | A comment was added to a task. |
{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "project.created",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"deadline": null,
"currency": "EUR",
"scheduleFrom": "forward",
"color": null,
"archived": false,
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"url": "https://planitude.app/app/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8"
},
"source": "blank"
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "project.updated",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"deadline": null,
"currency": "EUR",
"scheduleFrom": "forward",
"color": null,
"archived": false,
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"url": "https://planitude.app/app/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8"
},
"changes": {
"deadline": {
"from": null,
"to": "2026-12-18"
}
},
"reason": "version_restored"
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "project.deleted",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"project": {
"id": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"key": "WHX",
"name": "Warehouse expansion",
"description": null,
"startDate": "2026-10-05",
"deadline": null,
"currency": "EUR",
"scheduleFrom": "forward",
"color": null,
"archived": false,
"createdAt": "2026-10-01T08:30:12.418Z",
"updatedAt": "2026-10-01T08:30:12.418Z",
"url": "https://planitude.app/app/projects/40be00e0-7e34-4f7a-864b-5cc986f575b8"
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "task.created",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "task.updated",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
},
"changes": {
"progressPct": {
"from": 40,
"to": 60
}
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "task.deleted",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "task.completed",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 100,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": true,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "task.dates_changed",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
},
"cause": "reschedule",
"changes": {
"startAt": {
"from": "2026-10-02T06:00:00.000Z",
"to": "2026-10-05T06:00:00.000Z"
},
"finishAt": {
"from": "2026-10-06T15:00:00.000Z",
"to": "2026-10-07T15:00:00.000Z"
}
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "dependency.created",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"dependency": {
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "dependency.deleted",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"dependency": {
"id": "9ba5faf8-923d-4ecc-86f0-f245c5d179db",
"predecessorId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"successorId": "a22fd799-c4dc-4869-a466-0dd6e96f71ce",
"type": "FS",
"lagMin": 0
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "baseline.saved",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"baseline": {
"id": "b5d68d05-0640-48f9-8eeb-ed7804f4a116",
"name": "Plan v1",
"index": null,
"capturedAt": "2026-10-01T08:30:12.418Z",
"capturedBy": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"taskCount": 12
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "member.invited",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"invite": {
"id": "5d0b7c11-8e2a-4f63-a1d4-93c7e2b6f804",
"role": "editor",
"expiresAt": "2026-10-31T08:30:12.418Z",
"maxUses": null
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "member.joined",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"member": {
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"role": "editor"
}
}
}{
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"type": "comment.created",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-01T08:30:12.418Z",
"workspaceId": "824650d2-d0b3-4cac-8df8-5743ae9ff65a",
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"actor": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"data": {
"comment": {
"id": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"taskId": "4dbd104a-00cd-4035-8955-255f52ea586a",
"body": "Concrete delivered, we can start the walls.",
"author": {
"id": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi"
},
"createdAt": "2026-10-01T08:30:12.418Z"
},
"task": {
"id": "4dbd104a-00cd-4035-8955-255f52ea586a",
"number": 1,
"key": "WHX-1",
"parentId": null,
"name": "Foundations",
"type": "task",
"durationMin": 1440,
"workMin": 0,
"progressPct": 0,
"constraintKind": "asap",
"constraintDate": null,
"deadline": null,
"calendarId": null,
"costFixed": 0,
"notes": null,
"color": null,
"wbs": null,
"externalId": "crm-4711",
"startAt": "2026-10-05T06:00:00.000Z",
"finishAt": "2026-10-07T15:00:00.000Z",
"isCritical": true,
"totalFloatMin": 0,
"earlyStartAt": "2026-10-05T06:00:00.000Z",
"lateFinishAt": "2026-10-07T15:00:00.000Z",
"actualStartAt": null,
"actualFinishAt": null,
"actualDurationMin": null,
"remainingDurationMin": null,
"manuallyScheduled": false,
"levelingDelayMin": 0,
"taskType": "fixed_units",
"effortDriven": false,
"durationOptimisticMin": null,
"durationPessimisticMin": null,
"projectId": "40be00e0-7e34-4f7a-864b-5cc986f575b8",
"completed": false,
"assignees": [
{
"resourceId": "0c6a8f52-3d7e-4b19-9a4e-6f1d2c8b7e30",
"userId": "b1666432-132a-4ea9-b1ae-76ea69e226c5",
"name": "Anna Rossi",
"unitsPct": 100
}
],
"url": "https://planitude.app/app/t/WHX-1"
}
}
}Verifiser signaturer
Hver forespørsel er signert med HMAC-SHA256 og webhookens hemmelighet. Planitude-Signature-headeren inneholder et tidsstempel t og signaturen v1, beregnet på t, et punktum og rå body.
- Bruk rå body, før noen JSON-parsing: en re-serialisert body har en annen signatur.
- Beregn HMAC og sammenlign i konstant tid.
- Avvis forespørsler med tidsstempel mer enn 5 minutter fra klokken din: en fanget forespørsel kan ikke spilles av på nytt.
- Roter hemmeligheten når du vil: den gamle slutter å virke umiddelbart.
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body as a string, before JSON.parse
export function verifyPlanitude(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; // replay
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
const given = Buffer.from(parts.v1 ?? "", "hex");
return given.length === expected.length && timingSafeEqual(given, expected);
}
// Express: app.post("/hooks/planitude", express.raw({ type: "application/json" }), (req, res) => {
// if (!verifyPlanitude(req.body.toString("utf8"), req.get("Planitude-Signature"), process.env.PLANITUDE_WEBHOOK_SECRET)) return res.sendStatus(400);
// res.sendStatus(200); // then process the event in a queue
// });import hashlib
import hmac
import time
def verify_planitude(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t = int(parts.get("t", "0"))
if abs(time.time() - t) > tolerance:
return False # replay
expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))
# Flask: verify_planitude(request.get_data(), request.headers["Planitude-Signature"], os.environ["PLANITUDE_WEBHOOK_SECRET"])Nye forsøk og levering
Svar med en hvilken som helst 2xx innen 10 sekunder og gjør selve jobben etterpå, i en kø. Omdirigeringer følges ikke. Ved feil og tidsavbrudd prøver Planitude opptil 6 ganger totalt: umiddelbart, deretter etter 1 min, 5 min, 30 min, 2 h, 12 h.
Leveringen er minst én gang og uten garantert rekkefølge. Lagre hendelses-id-en (Planitude-Event-Id, også id i body) og hopp over de du allerede har behandlet; sorter etter createdAt.
Når 5 hendelser på rad mislykkes på alle forsøk, deaktiveres webhooken og eieren får en e-post. Et 410 Gone-svar deaktiverer den umiddelbart. Slå den på igjen fra profilen, eller med PATCH og active: true.
Leveringsloggen (status, HTTP-kode, utdrag av svaret, nyttelast, manuell gjensending) lagres i 30 dager. Bare offentlige adresser godtas som mål.
Forsøk 1 umiddelbart
Forsøk 2 + 1 min
Forsøk 3 + 5 min
Forsøk 4 + 30 min
Forsøk 5 + 2 h
Forsøk 6 + 12 hTest endepunktet ditt
- Send en
webhook.ping-hendelse med testendepunktet, eller med Test-knappen i profilen. - For å motta hendelser på datamaskinen din, eksponer den lokale serveren med en tunnel (for eksempel ngrok eller Cloudflare Tunnel) og abonner på den offentlige HTTPS-adressen.
- Åpne leveringsloggen for å se status, HTTP-kode og svar, og send en levering på nytt når endepunktet er rettet.
curl -X POST https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/test \
-H "Authorization: Bearer $PLANITUDE_API_KEY"const res = await fetch("https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/test", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PLANITUDE_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());import os
import requests
res = requests.post(
"https://planitude.app/api/webhooks/1747ee7f-a395-4d3c-94b0-54b513d71d88/test",
headers={"Authorization": f"Bearer {os.environ['PLANITUDE_API_KEY']}"},
)
res.raise_for_status()
print(res.json()){
"delivery": {
"id": "4b207161-80f9-40bb-bc3f-d8f70315be00",
"eventId": "6f1c1d1e-2f4b-4d0a-9a77-2a3c5b1e9f10",
"eventType": "task.completed",
"status": "success",
"attempts": 1,
"nextAttemptAt": null,
"lastAttemptAt": "2026-10-01T08:30:12.418Z",
"responseStatus": 200,
"responseExcerpt": "{\"ok\":true}",
"error": null,
"durationMs": 39,
"manual": false,
"createdAt": "2026-10-01T08:30:12.418Z"
}
}AI og MCP
MCP-server
Planitude er en MCP-server (Model Context Protocol): AI-assistenter og kodeeditorer leser prosjekter, analyserer kritisk linje og arbeidsbelastning, og oppretter eller endrer oppgaver, med dine tillatelser. Nettapper kobler til med OAuth (du logger inn og gir tilgang); kommandolinjeverktøy og editorer bruker en API-nøkkel.
Server-URL
https://planitude.app/mcp
- ChatGPTOAuth
I ChatGPT åpner du Innstillinger › Sikkerhet og pålogging og slår på utviklermodus. Opprett en app med server-URL-en og OAuth-autentisering, logg deretter inn på Planitude og gi tilgang.
Offisiell dokumentasjon ↗ - ClaudeOAuth
Åpne Tilpass › Koblinger › Legg til egendefinert kobling, lim inn server-URL-en og velg Koble til: Planitude åpnes, du logger inn og gir tilgang. Det fungerer i claude.ai, Claude Desktop og mobilappen.
Offisiell dokumentasjon ↗ - GeminiOAuth
På gemini.google.com åpner du Innstillinger › Tilkoblede apper, velger Legg til en egendefinert app og limer inn server-URL-en; logg deretter inn på Planitude og gi tilgang.
Offisiell dokumentasjon ↗ - Claude CodeAPI-nøkkel
Kjør kommandoen med nøkkelen din i en miljøvariabel. Legg til
Offisiell dokumentasjon ↗--scope userfor å bruke den i alle prosjekter, og sjekk medclaude mcp list. - CodexAPI-nøkkel
Legg nøkkelen i
Offisiell dokumentasjon ↗PLANITUDE_API_KEYog legg blokken til i~/.codex/config.toml: den gjelder for CLI-en, appen og IDE-utvidelsen. - CursorAPI-nøkkel
Legg blokken til i
Offisiell dokumentasjon ↗~/.cursor/mcp.json(alle prosjekter) eller.cursor/mcp.json(ett prosjekt); Cursor leser nøkkelen fra miljøet. - Visual Studio CodeAPI-nøkkel
Legg
Offisiell dokumentasjon ↗.vscode/mcp.jsontil i arbeidsområdet: VS Code spør om nøkkelen én gang og lagrer den sikkert, utenfor filen. - Gemini CLIAPI-nøkkel
Kjør kommandoen med nøkkelen din i en miljøvariabel, eller legg blokken til i
Offisiell dokumentasjon ↗~/.gemini/settings.json.
Verktøy
Serveren tilbyr 29 verktøy, fra lesing og analyse til trygge endringer. Ingen av dem sletter prosjekter eller oppgaver.
read
planitude_list_projectsplanitude_portfolio_overviewplanitude_get_projectplanitude_critical_pathplanitude_delay_impactplanitude_monte_carloplanitude_workloadplanitude_list_baselinesplanitude_list_versionsplanitude_list_templatesplanitude_list_commentsplanitude_preview_import
write
planitude_create_projectplanitude_create_project_from_templateplanitude_create_project_from_planplanitude_import_fileplanitude_edit_projectplanitude_add_taskplanitude_update_taskplanitude_set_progressplanitude_indent_taskplanitude_outdent_taskplanitude_link_tasksplanitude_unlink_tasksplanitude_rescheduleplanitude_configure_simulationplanitude_add_commentplanitude_save_baselineplanitude_save_version
Server URL
https://planitude.app/mcpServer URL
https://planitude.app/mcpServer URL
https://planitude.app/mcpTerminal
claude mcp add --transport http planitude https://planitude.app/mcp \
--header "Authorization: Bearer $PLANITUDE_API_KEY"~/.codex/config.toml
[mcp_servers.planitude]
url = "https://planitude.app/mcp"
bearer_token_env_var = "PLANITUDE_API_KEY"~/.cursor/mcp.json
{
"mcpServers": {
"planitude": {
"url": "https://planitude.app/mcp",
"headers": {
"Authorization": "Bearer ${env:PLANITUDE_API_KEY}"
}
}
}
}.vscode/mcp.json
{
"servers": {
"planitude": {
"type": "http",
"url": "https://planitude.app/mcp",
"headers": {
"Authorization": "Bearer ${input:planitude-key}"
}
}
},
"inputs": [
{
"id": "planitude-key",
"type": "promptString",
"description": "Planitude API key",
"password": true
}
]
}Terminal
gemini mcp add --transport http \
--header "Authorization: Bearer $PLANITUDE_API_KEY" planitude https://planitude.app/mcp~/.gemini/settings.json
{
"mcpServers": {
"planitude": {
"httpUrl": "https://planitude.app/mcp",
"headers": {
"Authorization": "Bearer $PLANITUDE_API_KEY"
}
}
}
}Ferdige integrasjoner
Ingen kode nødvendig: disse integrasjonene bruker samme API og webhooks og settes opp med noen få klikk.
- JiraTilgjengeligToveis synkronisering av oppgaver, datoer og avhengigheter med Jira-saker.
- Azure DevOpsTilgjengeligToveis synkronisering med arbeidselementer i Azure DevOps Boards.
- SlackTilgjengeligProsjektoppdateringer, daglige sammendrag og en slash-kommando i kanalene dine.
- Microsoft TeamsTilgjengeligOppdateringer, sammendrag og en Planitude-fane i Microsoft Teams.
- Zapier, Make, n8nKommer snartUmiddelbare utløsere og handlinger på oppgaver og prosjekter for automatiseringer uten kode.
Endringslogg
Ny utviklerdokumentasjon, generert fra OpenAPI-dokumentet. OpenAPI-dokumentet beskriver nå hvert felt som returneres for medlemmer, kommentarer, grunnlinjer, maler og tildelte.
API-versjon 2026-10-01: signerte utgående webhooks, dokumentert offentlig REST API (OpenAPI 3.1), markørpaginering og søk etter externalId.
OAuth 2.1 for MCP-serveren og API-et: ChatGPT, Claude og Gemini kobler til uten å kopiere en nøkkel.
MCP-server og personlige API-nøkler med lese- eller lese- og skrivetilgang.