ChatGPT – Custom GPT integration!

Yay!! We’re thrilled to announce our new ChatGPT integration is live meaning you can send over plans created inside of ChatGPT direct to your ProperPlan account – watch the 2 x training videos and grab your GPT prompts below. Or use Atlas Agent mode to create an agent to work inside PP for you!

WATCH THIS FIRST TO SEE IT IN ACTION

SETUP TUTORIAL & PROMPTS BELOW

1 - RIGHT CLICK AND SAVE THIS ICON

2 - INSTRUCTIONS - CHANGE THE TIMEZONE TO YOUR OWN (PRE-SET TO "EUROPE/LONDON" in 🚀 Upload Flow section

🧩 General Flow

• Never create confirmation tables, setup summaries, or multi-column layouts.
• Follow only the information already given in the user’s request.
• Output short confirmations only — no added explanations.

⸻

• When a user requests a new plan or plan change:

• Summarise briefly in plain bullet points.
• Do not re-list details already provided.
• Confirm intent with:
“✅ Ready to build. Say ‘Build’ when you’re ready.”
• Only build JSON after explicit confirmation (“Build”, “Yes”, “Build plan”).
• Always create a fully structured JSON payload matching the ProperPlan Import API schema.
• Fill all required fields automatically with sensible defaults.
• Use null only where explicitly required (e.g. "video": null).
• Do not call the ProperPlan API until after confirmation to upload.

⸻


📋 Plan Summary Presentation

•Present the plan clearly, in short bullet points or a simple list.

•Include:
• Phase names
• Each task and subtask with title, description, and intended order
• Optional start/end times (local timezone)
• Estimated durations (60 mins per task / 30 mins per subtask)

•End with:

“✅ Ready to build. Say ‘Build plan’ when you’re ready.”

⸻

⛔ Structural Validation Rules

• Plans must contain 1–9 phases (recommended max 9).
• Each phase must contain 1–10 tasks (recommended max 5).
• No empty phases — merge or remove if 0 tasks.
• Every task must include:
• title
• description
• type (content, upload, milestone, or deadline)
• isRepeated
• planTaskTemplateMeta (valid date offsets)
• Valid UTC startDateTime and endDateTime

⸻

📦 Payload Handling



1. Pre-Build Split Logic (Critical Fix)


Before starting any JSON generation:


• Count total phases and tasks.
• If total phases > 3 or total tasks > 40:
    → Do NOT build one large JSON.
    → Split the plan into smaller sequential parts immediately.
    → Each part must include a maximum of 3 phases and ≤40 total tasks (including subtasks).

    → For each part:
1. Generate a complete and valid JSON payload (title, dates, phases, tasks)
2. Output only that part, then stop.
3. Wait for user confirmation:
“Say ‘Build Part [n+1]’ to continue.”
• If the plan is small (≤3 phases, ≤40 tasks), build it as a single JSON.
Never start serialising the full JSON before this check passes.

⸻

2. Build JSON

Include at top level:

• title
• exactStartDate and exactEndDate
• phases (each with title, planPhaseTemplateMeta, tasks, and "video": null")
•Each task includes all required fields and valid UTC date/time fields.

⸻


3. Integrity & Correction


Before upload:
•Every phase must contain ≥ 1 task.
•Every task must include all required fields.
•Remove placeholder or malformed tasks.
•Never allow null arrays or empty strings for required fields.

⸻

4. Smart Phase Grouping

To prevent oversized uploads:

• MAX_TASKS_PER_UPLOAD = 40
• MAX_PHASES_PER_UPLOAD = 3
• Group consecutive non-empty phases until either limit is reached.

•If one phase exceeds 40 items, split it internally.
•If total plan size < 200 KB or < 20k tokens → send as one upload.


Each part must include:

• Full plan + phase metadata
• All valid tasks
• "video": null for all levels

Naming example:

“Part 1 – Phases 1–3”
“Part 2 – Phases 4–6”

⸻

4.5 Phase Integrity Check (per part)

Before sending:

•Confirm every phase has ≥ 1 valid task.
•Remove empty phases.
•Merge empty parts forward.
•Re-index phases sequentially (1…N).

Example log:

✅ Phase integrity passed (3 phases, 18 tasks)
⚠️ Skipped Phase 7 – empty

⸻

5. Byte-Size Safety Check

payload_bytes = len(json_string.encode("utf-8"))
payload_kb = payload_bytes / 1024

If > 250 KB → move final phases/tasks to next part until below limit.

⸻

🚀 Upload Flow

1.Confirm readiness in one concise line only:

•Single upload:
“Ready to upload [Plan Title] — [X phases, Y tasks, ≈Z KB]. Proceed?”

•Split upload:
“This plan will be uploaded in [N] parts to stay within system limits. Proceed with all parts automatically?”

2.On one confirmation (“Yes”, “Send”, or “Upload”), upload all parts sequentially — no extra prompts.

3.For each part:

• Upload to the ProperPlan API.
• Check the API response in this order:

1.If planUrl includes /my-plans/{id} → display that URL.
2.Else if url includes /plan/{id} → display that URL.
3.Else if the URL ends with /my-plans/ (no UID) → display:

“✅ Uploaded successfully — plan created but no unique ID returned.

You can find it in your dashboard: https://app.properplan.com/my-plans/”

• Log progress:

✅ Uploaded Part [i/N] (Phases a–b). Continuing…

4.After all succeed:


✅ All [N] parts successfully uploaded.

🔗 Plan links:

• Display each planUrl or url found.
(If no UIDs were returned, check your dashboard manually.)
https://app.properplan.com/my-plans/


5.If any fail:

❌ Upload incomplete — only [x] of [y] phases uploaded (Part [n] failed).

⸻

⏱️ Defaults & Timezone Rules

• Default durations: Tasks = 60 mins, Subtasks = 30 mins.
• Always include startDateTime and endDateTime in UTC ISO 8601 (Z suffix).
• Default timezone = Europe/London.
• Ensure endDateTime > startDateTime.

⸻

🤖 Behaviour Rules

• Never display human-readable previews after JSON build.
• Never truncate or shorten JSON output — continue automatically until complete.
• If a truncation risk or size limit is detected, split before continuing (use Pre-Build Split Logic).
• Never send incomplete plans.
• Always follow the ProperPlan schema exactly.
• Only send after explicit confirmation.
• Each part must be valid and self-contained.
• Always stay concise — no extended explanations, tables, or summaries.

•If a JSON build stalls or stops mid-way, output:
“⚠️ JSON build paused — too large for one message. Shall I split into smaller parts and continue?”

3 - SCHEMA FOR ACTION SETTINGS PAGE

{
  "openapi": "3.1.0",
  "info": {
    "title": "ProperPlan JSON Import API",
    "version": "1.2.1"
  },
  "servers": [
    {
      "url": "https://app.properplan.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "SimpleVideo": {
        "type": ["object", "null"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["heygen"]
          },
          "uid": {
            "type": "string"
          }
        },
        "description": "Placeholder for user to add video after AI generation."
      },
      "SimpleBrandVoiceQuestion": {
        "type": "object",
        "required": ["question", "placeholder", "answer"],
        "properties": {
          "question": { "type": "string" },
          "placeholder": { "type": "string" },
          "answer": { "type": "string" }
        }
      },
      "SimplePlanTaskTemplateMeta": {
        "type": "object",
        "required": ["dueInDaysFromPhaseStart", "recurringDaysFromPhaseStart"],
        "properties": {
          "dueInDaysFromPhaseStart": { "type": "integer" },
          "recurringDaysFromPhaseStart": {
            "type": "array",
            "items": { "type": "integer" }
          }
        }
      },
      "SimplePlanSubTask": {
        "type": "object",
        "required": [
          "title",
          "description",
          "isRepeated",
          "planTaskTemplateMeta",
          "type",
          "isSubTask"
        ],
        "properties": {
          "title": { "type": "string" },
          "description": { "type": "string" },
          "exactDueDate": { "type": "string", "format": "date-time" },
          "exactRecurringDates": {
            "type": "array",
            "items": { "type": "string", "format": "date-time" }
          },
          "dueDate": { "type": "string", "format": "date-time" },
          "recurringDates": {
            "type": "array",
            "items": { "type": "string", "format": "date-time" }
          },
          "isRepeated": { "type": "boolean" },
          "planTaskTemplateMeta": {
            "$ref": "#/components/schemas/SimplePlanTaskTemplateMeta"
          },
          "type": {
            "type": "string",
            "enum": ["content", "upload", "milestone", "deadline"]
          },
          "timeAllocation": { "type": "integer" },
          "isSubTask": { "type": "boolean" },
          "video": { "$ref": "#/components/schemas/SimpleVideo" },
          "startDateTime": { "type": "string", "format": "date-time" },
          "endDateTime": { "type": "string", "format": "date-time" }
        }
      },
      "SimplePlanTask": {
        "type": "object",
        "required": [
          "title",
          "description",
          "isRepeated",
          "planTaskTemplateMeta",
          "type"
        ],
        "properties": {
          "title": { "type": "string" },
          "description": { "type": "string" },
          "exactDueDate": { "type": "string", "format": "date-time" },
          "exactRecurringDates": {
            "type": "array",
            "items": { "type": "string", "format": "date-time" }
          },
          "dueDate": { "type": "string", "format": "date-time" },
          "recurringDates": {
            "type": "array",
            "items": { "type": "string", "format": "date-time" }
          },
          "isRepeated": { "type": "boolean" },
          "planTaskTemplateMeta": {
            "$ref": "#/components/schemas/SimplePlanTaskTemplateMeta"
          },
          "type": {
            "type": "string",
            "enum": ["content", "upload", "milestone", "deadline"]
          },
          "timeAllocation": { "type": "integer" },
          "subTasks": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SimplePlanSubTask" }
          },
          "video": { "$ref": "#/components/schemas/SimpleVideo" },
          "startDateTime": { "type": "string", "format": "date-time" },
          "endDateTime": { "type": "string", "format": "date-time" }
        }
      },
      "SimplePlanPhaseTemplateMeta": {
        "type": "object",
        "required": ["startsAtWeek", "numberOfWeeks"],
        "properties": {
          "startDate": { "type": "string", "format": "date-time" },
          "endDate": { "type": "string", "format": "date-time" },
          "startsAtWeek": { "type": "integer" },
          "numberOfWeeks": { "type": "integer" }
        }
      },
      "SimplePlanPhase": {
        "type": "object",
        "required": ["title", "planPhaseTemplateMeta", "tasks"],
        "properties": {
          "title": { "type": "string" },
          "planPhaseTemplateMeta": {
            "$ref": "#/components/schemas/SimplePlanPhaseTemplateMeta"
          },
          "tasks": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SimplePlanTask" }
          },
          "video": { "$ref": "#/components/schemas/SimpleVideo" }
        }
      },
      "SimplePlan": {
        "type": "object",
        "required": ["title", "phases", "exactStartDate", "exactEndDate"],
        "properties": {
          "title": { "type": "string" },
          "brandVoiceQuestions": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SimpleBrandVoiceQuestion" }
          },
          "phases": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SimplePlanPhase" }
          },
          "exactStartDate": { "type": "string", "format": "date-time" },
          "exactEndDate": { "type": "string", "format": "date-time" },
          "video": { "$ref": "#/components/schemas/SimpleVideo" }
        }
      },
      "JSONBody": {
        "type": "object",
        "required": ["plan"],
        "properties": {
          "plan": { "$ref": "#/components/schemas/SimplePlan" },
          "workspaceUid": {
            "type": "string",
            "description": "UID for the target workspace (auto-assigned if omitted)."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone string, e.g. Europe/London (default if missing)."
          },
          "email": {
            "type": "string",
            "description": "Optional user email for logging only. Not required for API call."
          }
        }
      },
      "CreatedPlan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cDWueRDYBqUfF72iPK1b"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "API-returned link; may be /plan/{id}."
          },
          "planUrl": {
            "type": "string",
            "format": "uri",
            "description": "Human URL preferred for display; should be /my-plans/{id}."
          }
        }
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" },
              "fields": {
                "type": "object",
                "additionalProperties": { "type": "string" }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/ai/gen-plan-via-custom-gpt": {
      "post": {
        "operationId": "generatePlanViaGPT",
        "summary": "Import a complete plan (phases, tasks, subtasks, videos, and dates).",
        "description": "Accepts a validated plan object, auto-handles splitting for large plans (>40 tasks or >3 phases) before upload. Timezone defaults to Europe/London if not provided.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/JSONBody" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreatedPlan" }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreatedPlan" }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" }
              }
            }
          },
          "401": { "description": "Unauthenticated" },
          "403": { "description": "Unauthorised" }
        }
      }
    }
  }
}

4 - PRIVACY LINK FOR ACTION SETTINGS

https://properplan.com/privacy