← All Modules

assay.plane

Plane client covering sprint execution on self-hosted or cloud Plane: projects, work items, Cycles (Plane's sprints), Modules, workflow states, labels, members, comments, and links.

Client

local plane = require("assay.plane")
local c = plane.client({
  api_key = env.get("PLANE_API_KEY"),
  workspace = "acme",
  base_url = "https://plane.example.com",
})

plane.client(opts) accepts:

The key travels in X-API-Key. Plane does not read Authorization, so a Bearer token is silently ignored rather than rejected.

A client with a blank workspace slug errors on first use instead of building /workspaces//.

Projects

Work items

Collections answer with a cursor envelope (results, next_cursor, next_page_results); a few smaller endpoints answer with a bare array, and both are accepted.

Cycles (sprints)

Modules, states, labels, members

Comments and links

Work items are served under /work-items/, but their comments and links are rooted under /issues/ — a leftover from the pre-rename API. The module keeps both paths straight.

Intake

Helpers

Example — file this sprint's work

local plane = require("assay.plane")
local c = plane.client({ workspace = "acme" })

local project = plane.resolve_project(c, "Development")
local cycle = c.cycles:create(project.id, {
  name = "DEV Sprint 2026-W33",
  start_date = "2026-08-10",
  end_date = "2026-08-16",
})

local item = plane.ensure_item(c, project.id, { name = "Publish the Q3 pricing page" })
c.cycles:add_items(project.id, cycle.id, { item.id })
c.links:create(project.id, item.id, { url = "https://github.com/acme/site/issues/42" })