Skip to content

Publishing

POST /prompts/active-prompt-version

Makes new content the active version of a prompt, immediately.

INFO

On-prem only. Requires a write-scoped key — see Authentication.

This skips the review workflow, never the authority check. What it does depends on the project's publishing flow — read that page before you build.

It cannot create a prompt. The prompt must already exist in the console with a first version approved. This publishes new versions of existing prompts.

Request

The key goes in the header here, not the query string — a write path should not leave credentials in access logs.

bash
curl -s -X POST "$IM_URL/prompts/active-prompt-version\
?project_id=8112d9c4-8334-43dd-a3c0-436b5cf1f475\
&prompt_name=sampleAgent" \
  -H "X-API-Key: $IM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "content": {
          "kind": "instruction",
          "text": "Print the word \"hello\" exactly 4 times.",
          "system_prompt": ""
        },
        "message": "bump to 4 times",
        "expected_active_sha": "c8aceef013a8"
      }'

Body

contentobjectrequired

The new prompt content. Must match the prompt's kind — see Prompt kinds.

Always include kind inside it. Validation is driven by that field: declare it and a mismatch is rejected with 422; omit it and your content is accepted as a plain instruction with no further checking.

Capped in size — see Content size.

messagestringrequired

Why it changed. Non-empty. Shows in version history like a commit message, so write it for whoever reads the history later.

expected_active_shastringrequired

The sha you read before editing. This is the concurrency guard — see Safe concurrent writes.

Required in practice: omit it without force and you get 422.

forceboolean

Skips the expected_active_sha check. For canonical publishes that should overwrite whatever is there — a CI job pushing from a repository, a bulk update. Recorded in the audit trail as a deliberate overwrite.

It waives a concurrency conflict only. It does not waive a reviewer finding.

environmentsstring[]

Where to release this version. Omit to keep the outgoing version's environments.

Omission means inherit, not release nowhere — treating it as "none" would silently drop a prompt out of production while it still reported Active.

acknowledge_reviewstring

AI-assisted projects only. A review_id from a previous 422, meaning "publish despite these findings". Ignored, not rejected, on other flows — so one integration works unchanged across a flow change. See Publishing flows.

Response

201 Created:

json
{
  "prompt_id": "3d7735aa-8e34-4e58-b5e9-e93181526403",
  "prompt_name": "sampleAgent",
  "kind": "instruction",
  "sha": "83efc9591f18",
  "version_label": "v1.1",
  "status": "active",
  "environments": ["development", "test"],
  "published_via": "api",
  "published_by": "Mohanpathi S",
  "flow_mode": "direct_publish",
  "review_status": null,
  "unchanged": false
}

Note v1.0v1.1: a publish bumps the minor version. environments was not sent, so it was inherited.

The new version is live on the next read. There is no cache to wait for.

Publishing identical content

If content is byte-for-byte identical to the live version, nothing is created and you get 200:

json
{ "sha": "83efc9591f18", "version_label": "v1.1", "status": "active", "unchanged": true }

Treat 200 and 201 the same way; check unchanged only if you care. This keeps auto-saving editors, retries and double-clicked buttons out of the version history.

The comparison is an exact match on the content object — adding or removing a field, including kind, counts as a change even if the text is identical.

Safe concurrent writes

Two people editing the same prompt is normal. Without a guard, both publishes succeed and one person's work disappears with no error:

10:00  Ravi   GET   → v1.2
10:01  Priya  GET   → v1.2
10:05  Ravi   POST  → v1.3   "…and detect sentiment"
10:06  Priya  POST  → v1.4   "…and route to billing"    Ravi's change is gone

So send the sha your edit was based on. If the active version has moved, you get 409 instead of overwriting someone:

json
{
  "detail": {
    "code": "active_version_changed",
    "message": "The active version has changed since you last read it.",
    "current_active_sha": "83efc9591f18"
  }
}

The check runs under a row lock, so two publishes landing in the same instant are serialised — exactly one gets 201, the other 409.

DANGER

Do not auto-retry a 409. Re-fetch, show the person that the prompt changed underneath them, and let them reconcile. Retrying just overwrites the other person a moment later — which is the failure this guard exists to prevent.

Content size

content is capped. The default ceiling is 1 MB of serialised JSON — roughly a quarter of a million words. Over it:

json
{
  "detail": {
    "code": "content_too_large",
    "message": "Content is 2000035 bytes, which exceeds this deployment's limit of 1048576 bytes.",
    "limit_bytes": 1048576,
    "content_bytes": 2000035
  }
}

413, and nothing is published. Two things worth knowing: the size is measured on the whole serialised object, not any one field, so putting the weight in an unexpected key does not avoid the check; and it is measured in bytes, not characters, so non-ASCII text counts for more than its length suggests.

The ceiling is per deployment. Ask your Instructions Manager team what yours is if you expect to approach it.

Errors

StatuscodeCause
401key missing, invalid or revoked
403read-scoped key, or the owner lacks the approver tag on a Manual review project
404unknown project or prompt, or no access
409active_version_changedstale expected_active_sha
413content_too_largeover the size cap
422missing expected_active_sha, blank message, content/kind mismatch, unknown kind
422review_suggestions_openthe AI reviewer has findings — see flows

Full list, with the retry policy: Errors.

Publishing skills

POST /skills/active-version is the same contract for a project-scoped skill: same authority checks, same expected_active_sha guard, same flows and review handshake.

Three things differ, and each will bite a client that assumes otherwise:

  • it takes the key in the X-API-Key header only — no ?api_key=
  • the body is frontmatter + body, with no environments (skills are not environment-gated)
  • skill content carries a security scan, which is skipped on this path by default and is not overridable

Full reference: Skills Manager → HTTP API → Publishing.

Next

Copyright © 2026 elsai foundry.