Projects

Update a project

Rename or archive a project, and/or change its content-retention settings (trace_content_retention_days, trace_content_mode), its execution ceilings (max_concurrent_runs, max_chain_generations, max_orchestration_run_depth), its priced-model gate (require_priced_model), its project-scope guardrails (guardrail_ids) and managed conversion (managed_conversion). Archiving is reversible; resources are retained. Requires the admin role in the project (an owner has it too). These are the terms every member works under, which is why setting them sits above the role that works under them. The ceilings and the priced-model gate are uncapped by plan: each one only ever narrows what the project may spend, so setting one takes on a restriction rather than claiming an entitlement. On the three ceilings null clears the project's own bound and omission leaves it alone — they are different instructions. guardrail_ids is the floor under every tool call by every agent in the project, including tools added later. The list is replaced wholesale, so send the ids you want to keep; [] detaches every one. An id naming no guardrail in the project responds 400 with guardrail_not_found, whose details.missing lists the ids. It is uncapped by plan, like the ceilings: a guardrail can only tighten what runs. The two retention controls answer different questions. The window bounds how long content stays — a daily sweep purges anything past it, leaving auditable skeletons behind. trace_content_mode: none means content is never written, which is the stronger guarantee: it cannot be missed by a sweep or survive in a backup.

Your plan sets the longest window you may keep content for. A wider one — null included, which keeps content indefinitely — responds 403 with plan_limit_reached, whose details carry the plan and the limit in days. Anything shorter is always allowed. Moving to a plan with a shorter window takes effect at the end of the billing cycle, and content already stored is then purged by age like everything else.

patch/v1/projects/{project_id}

Request

  • Base URL: https://api.naturali.ai
  • URL: https://api.naturali.ai/v1/projects/{project_id}
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://api.naturali.ai/authorize, token URL https://api.naturali.ai/token, scopes: mcp:access)

Request body

namestring
status'active' | 'archived'
trace_content_retention_daysinteger nullable

Days of trace and generation content retention before the daily sweep purges it. Send null to disable retention (content is then kept until purged on demand). Omitting the field leaves the current window unchanged — null and absent are different instructions.

Bounded by your plan: a window longer than the plan allows, and null on any plan that sets a window, respond 403 plan_limit_reached.

trace_content_mode'full' | 'none'

Set none for zero-retention: content is never written for any agent in this project. Tightening to none does not erase content already on disk — purge it explicitly, or set a retention window to have the sweep do it.

max_concurrent_runsinteger nullable

Orchestration runs driven at once. Send null to lift the limit. Omitting the field leaves it unchanged.

max_chain_generationsinteger nullable

Generations one continuation chain may hold. Send null to drop back to the platform-wide ceiling. Omitting the field leaves it unchanged.

max_orchestration_run_depthinteger nullable

Nesting levels a run tree may reach. Send null to drop back to the platform-wide bound. Omitting the field leaves it unchanged.

require_priced_modelboolean

Refuse a generation whose model carries no price, before the provider is called. Uncapped by plan — it only ever narrows what the project may spend.

guardrail_idsstring[]

Guardrails attached at the project scope, replaced wholesale. Send [] to detach every one; omitting the field leaves them unchanged. Uncapped by plan — a guardrail can only tighten what runs.

managed_conversionboolean

Turn managed conversion off or back on. Off removes the managed ingestion rules; rules of your own stay.

Example request

{
  "name": "acme-renamed",
  "status": "archived",
  "trace_content_retention_days": 90,
  "trace_content_mode": "none",
  "max_concurrent_runs": 5,
  "max_chain_generations": 25,
  "max_orchestration_run_depth": 3,
  "require_priced_model": true,
  "guardrail_ids": [
    "guard_V1StGXR8Z5jdHi6B"
  ]
}

Response

Project updated.

idstring required

Public project ID (proj_ prefix).

namestring required
status'active' | 'archived' required
role'owner' | 'admin' | 'member' required

What the member may do in this project. owner — everything, including deleting it and paying for it; exactly one per project. admin — everything a member may do, plus managing who else is in the project and how the project itself is configured. member — every read and write on the project's own resources, including minting project API keys. When returned on a Project, this is your role, not a property of the project: it is what lets a client hide an action the request would refuse.

owner_user_idstring required

The user who pays for the project — its billing owner, and the one member holding the owner role. Membership decides who may act in a project; this decides who is charged for it.

transfer_to_user_idstring nullable required

The member a pending transfer would make the owner, until they accept or decline it; null when none is pending.

trace_content_retention_daysinteger nullable required

How long trace and generation content is kept before a daily sweep purges it. null (the default) disables retention, so content is kept until purged on demand. A swept record is content-purged the same way an on-demand purge does it — the row survives as an auditable skeleton with content_redacted_at set.

trace_content_mode'full' | 'none' required

Whether trace and generation content is persisted at all. full (the default) stores it; none is zero-retention — content is never written, for every agent in this project. none is a floor, not a default: an agent may tighten itself to none, but cannot loosen a none project back to full.

max_concurrent_runsinteger nullable required

Orchestration runs of this project driven at once. null (the default) is unlimited. Enforced when a run is claimed — runs past the limit wait for a slot rather than failing.

max_chain_generationsinteger nullable required

Generations one continuation chain in this project may hold before it stops being resumed. null (the default) leaves the platform-wide ceiling in force. The budget actually applied is the smallest of that ceiling, this number, and the agent's own — an agent author can be stricter than this, never looser.

max_orchestration_run_depthinteger nullable required

Nesting levels a run tree in this project may reach before the next child is refused. null (the default) leaves the platform-wide bound in force; the bound applied is the smaller of the two.

require_priced_modelboolean required

Whether a generation whose model carries no price is refused before the provider is called. false by default, which runs the model and meters it at no cost. Mainly of use with your own providers — see Requiring a priced model.

guardrail_idsstring[] required

Guardrails attached at the project scope — the floor under every tool call by every agent in the project, including tools added later. Empty by default. See Attaching one.

paused_atstring date-time nullable required

When the project was paused; null while it runs. See Pausing a project.

pause_reasonstring nullable required

The reason the pause named; null while the project runs, or when the pause named none.

managed_conversionboolean required

Whether scanned PDFs, images and audio are converted to text on ingest with no setup. true by default. See Managed conversion.

created_atstring date-time required
updated_atstring date-time required

Example response

{
  "id": "proj_V1StGXR8Z5jdHi6B",
  "name": "acme-perpetual",
  "status": "active",
  "role": "owner",
  "owner_user_id": "user_V1StGXR8Z5jdHi6B",
  "trace_content_mode": "full",
  "guardrail_ids": [],
  "managed_conversion": true,
  "created_at": "2026-07-17T00:00:00.000Z",
  "updated_at": "2026-07-17T00:00:00.000Z"
}

Changes

No recorded changes to this operation across all 1 revision of this API.