Skip to content

Create an artifact ​

POST/api/v2/workspaces/{slug}/artifacts/

Create an artifact together with its first HTML version. The new artifact starts at current_version: 1 and is unpublished until you call Publish an artifact.

Requires the Applets feature and workspace admin or owner — see Artifacts overview.

Path Parameters ​

slug:requiredstring

The workspace slug. It appears in your Plane URLs — in https://app.plane.so/my-team/projects/, the slug is my-team.

Body Parameters ​

html:requiredstring

The rendered HTML for version 1. This is the only genuinely required field — an empty or missing value is a 400.

name:optionalstring

Display name. Truncated to 255 characters. Falls back to Untitled dashboard when omitted, empty, or whitespace — it never rejects a missing name.

description:optionalstring

Free-form description. Truncated to 2000 characters rather than rejected.

prompt:optionalstring

The prompt that produced this HTML, stored against the version for provenance. Not returned by any read endpoint.

project:optionalstring (uuid)

Optionally scope the artifact to a project. Note the field is project, not project_id — the *_id convention used elsewhere in v2 does not apply on this surface.

data_mode:optionalstring

How the artifact's data is sourced. One of snapshot (frozen at generation time) or live (re-read on view). Defaults to snapshot. Any other value is a 400.

A project id from another workspace is silently dropped

project is validated for membership in the calling workspace, and a value that fails that check is set to null rather than rejected — the artifact is created workspace-scoped instead. If project scoping matters to you, read the project back rather than assuming it stuck.

Scopes ​

workspaces.artifacts:write

Errors ​

StatusCodeCause
400—html is missing or empty, or data_mode is outside the enum. See the note below.
401unauthorizedMissing or invalid credentials.
402payment_requiredThe Applets feature isn't enabled on your plan.
403forbiddenYou are not a workspace admin or owner, or your token lacks the scope.
404not_foundNo such workspace, or it's outside your tenant.
406not_acceptableThe Accept header asks for a representation the API can't produce.
409conflictDeclared by the schema; no current condition produces it on this route.
413payload_too_largeThe request body is over the size limit. Large HTML can hit this.
415unsupported_media_typeThe Content-Type isn't one this endpoint accepts.
429rate_limitedThrottled. Honor the Retry-After header before retrying.

The 400 here is not problem+json

Unlike the rest of v2, the two validation failures on this route return a bare {"detail": "…"} body with no type or code member. Code that branches on problem.code needs a fallback for this shape. The schema declares the standard ValidationProblemDetail for 400, so this is a known inconsistency rather than intended behavior.

Create an artifact
bash
curl -X POST \
  "https://api.plane.so/api/v2/workspaces/my-team/artifacts/" \
  -H "X-Api-Key: $PLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Q1 velocity by squad",
  "description": "Throughput and cycle time, split by squad.",
  "html": "<section><h1>Q1 velocity by squad</h1></section>",
  "data_mode": "snapshot"
}'
Response201
json
{
  "id": "b7e42a19-3c5d-4f80-9a26-8d1c0f4e7b53",
  "name": "Q1 velocity by squad",
  "current_version": 1,
  "is_published": false,
  "anchor": null,
  "data_mode": "snapshot"
}
Response400
json
{
  "detail": "`html` is required."
}

The response status is 201, not 200 ​

A successful create answers 201 Created. The OpenAPI document declares 200 for this operation — a schema annotation gap, not a behavior you should code against. Accept 2xx rather than matching 200 exactly.

The body is deliberately compact: it echoes the artifact's identity and publish state, not its HTML. Read the HTML back with Get an artifact if you need it.

Next steps ​