Plan Plays API
POST /api/plan-plays
Create a new plan play for the authenticated client/user.
This endpoint participates in GOFA's commercial API controls for activity creation. Depending on the client's configured commercial policy, a request can be rejected before creation when request-rate, quota, or available-credit limits are exceeded. Successful requests may consume credits according to the client's active commercial setup.
Headers:
Authorization: Bearer <JWT>
Request Body:
{
"planId": "string (required)",
"userId": "string (optional)",
"plannedLessons": ["string", "..."],
"email": "string (optional)",
"displayName": "string (optional)",
"photoURL": "string (optional)",
"assignmentSource": "string (optional)",
"riskLevel": "string (optional)"
}
Response:
201 Created:{ "data": PlanPlay }400 Bad Request:{ "error": string, "details": unknown[] }401 Unauthorized:{ "error": string }429 Too Many Requests:{ "error": string, "code": "api_rate_limited" | "api_quota_exceeded" | "api_balance_exhausted", "retryAfterSeconds": number | null }500 Internal Server Error:{ "error": string }
GET /api/plan-plays
List plan plays for the authenticated client/user.
Query Parameters
clientId: string (optional) — Overrides the inferred client when permitted.userId: string (optional) — Filter by user ID.status: string (optional) — Filter by status.planId: string (optional) — Filter by plan ID.
Headers:
Authorization: Bearer <JWT>
Response:
200 OK:{ "data": PlanPlay[], "count": number }401 Unauthorized:{ "error": string }500 Internal Server Error:{ "error": string }
GET /api/plan-plays/[planPlayId]
Fetch a specific plan play.
Headers:
Authorization: Bearer <JWT>
Response:
200 OK:{ "data": PlanPlay }401 Unauthorized:{ "error": string }403 Forbidden:{ "error": "Access denied" }404 Not Found:{ "error": "Plan play not found" }500 Internal Server Error:{ "error": string }
PATCH /api/plan-plays/[planPlayId]
Update a plan play. A first transition to ended is treated as a billable completion event.
When a request changes a plan play into its first completed state, the same commercial controls used for other billable activity endpoints apply before the update is accepted. Repeated completion retries that do not create a new completion event are not billed as a new successful completion.
Headers:
Authorization: Bearer <JWT>
Request Body:
Send the supported plan-play update fields exposed by the API, such as status, currentLessonIndex, completedLessons, completedLessonPlays, totalLessonsCompleted, completedAt, or lastPlayedAt.
Response:
200 OK:{ "data": PlanPlay }400 Bad Request:{ "error": string, "details": unknown[] }401 Unauthorized:{ "error": string }403 Forbidden:{ "error": "Access denied" }404 Not Found:{ "error": "Plan play not found" }429 Too Many Requests:{ "error": string, "code": "api_rate_limited" | "api_quota_exceeded" | "api_balance_exhausted", "retryAfterSeconds": number | null }500 Internal Server Error:{ "error": string }