Perforce

Updated July 2026

Dousen connects your everyday Perforce work to your Jira tasks. DousenCore talks to the Perforce server directly (via the p4 CLI in -ztag machine-readable mode) to open, submit, and shelve changelists on your behalf; separately, the desktop app and every DCC addon also run local p4 commands under your own Perforce identity for lock visibility, checkout, sync, and revert. This page covers both halves.

Endpoint reference

Everything below lives under /api/vcs/..., requires a signed-in JWT, and is normally triggered from the desktop app or a DCC panel rather than called directly — the table is here for scripting and troubleshooting.

EndpointRequest bodyResponse body
POST /api/vcs/open {"jira_key":"DOU-31","project_id":"<uuid, optional>"} {"changelist_id":"<uuid>","vcs_changelist_id":"<p4 CL#>"}
POST /api/vcs/submit {"changelist_id":"<uuid>","message":"...","project_id":"<uuid, optional>"} {"submitted_vcs_changelist_id":"<p4 CL#>","files_submitted":<int>}
GET /api/vcs/info {"is_stream":bool,"stream_name":str|null,"stream_root":str|null,"server_version":str|null,"client_name":str}
GET /api/vcs/shelved?jira_key=DOU-42 {"shelved":[{"changelist_id","description","user"}]}
POST /api/vcs/unshelve {"changelist_id":"<p4 CL#>"} {"changelist_id":"<p4 CL#>"}

Submit is ownership-gated: only the user who opened the changelist, or an Admin, gets a 200 — anyone else gets 403 Forbidden. There is no changelist-level revert exposed over this API; the VCS layer supports it internally, but the only revert a REST caller can reach is the per-file one described below, run locally by the DCC addon itself.

All Perforce actions live under /api/vcs/.... There is no /api/changelists/... endpoint — a fallback lookup in the DCC-side Python (resolve_task_changelist()) does call one, but since the route doesn't exist it always 404s and silently falls back to Perforce's default changelist. In practice this fallback is rarely hit: the live task.context bridge event the desktop app pushes on task selection carries the real Perforce CL number, and that's what addons use whenever a task is actually selected.

Changelists are keyed to a Jira issue

When you open a changelist through Dousen, its description is stamped in a fixed format so it's immediately traceable back to the ticket that opened it:

TEXT[dousen DOU-31] Alice Smith

The pattern is [dousen <JIRA-KEY>] <your display name>. Inside DousenCore, the changelist row itself is keyed by the plain jira_key string — there's no foreign key to a task table, because Jira is the task table.

That tag lives in the changelist description only while the changelist is pending. Submitting requires a message of your own (at least 5 characters, enforced client-side), and DousenCore rewrites the changelist's description with that message before running p4 submit — it replaces the [dousen ...] text rather than appending to it. So the tag you see in P4V while the CL is open does not automatically survive into the depot's submitted history; if you want the Jira key visible in the permanent record, include it yourself in your submit message. The authoritative link between a changelist and its task lives in DousenCore's database either way.

Working with changelists from the desktop app

  1. Open. Selecting a task and clicking Open CL calls POST /api/vcs/open, which runs p4 change -i against a template fetched with p4 change -o, stamping the description above and returning the new Perforce CL number.
  2. Work and publish. Exports from any DCC addon target that changelist automatically via the live task context — see Jira tasks.
  3. Submit. Clicking Submit opens a message dialog, then calls POST /api/vcs/submit, which updates the description (see the callout above) and runs p4 submit -c <CL#>. The response's files_submitted count comes straight from Perforce's own submit output.
The SubmitDialog prompting for a changelist submit message before Submit calls POST /api/vcs/submit.
A message of at least 5 characters is required before the changelist submits.

The desktop re-derives whether a task has an open changelist from DousenCore (which keys changelists by issue key), so Submit stays enabled across task-list refreshes and Open CL is idempotent — it returns the existing changelist instead of opening a duplicate. See the equivalent note in Jira tasks.

Automatic workspace from the depot path

Each project has a depot_path set by your admin (e.g. //depot/MyGame/...). During onboarding, the Workspace page's Check button runs p4 -ztag where against that path: if it's already mapped in an existing client, Dousen pre-fills the local root and workspace name from the result (and auto-detects a .uproject inside it for the next onboarding page). If it isn't mapped, a creation form appears — pick a local root and a workspace name (defaulted to <p4user>_<last depot segment>), and Create Workspace generates a client spec and pipes it straight into p4 client -i.

The workspace this creates is always a classic view mapping, even when the depot path lives inside a Perforce stream. Onboarding doesn't ask whether the path is a stream root, so it never writes a Stream: field to the client spec. A classic mapping into a stream path still works in Perforce, but the status bar will show it as (classic) rather than the stream name until you create a true stream client yourself (e.g. p4 client -S //depot/main).

Onboarding does not run a full sync — it only sets up the workspace mapping, and says so on screen ("Workspace created. Sync it from P4V or UnrealGameSync before continuing."). Run your first sync yourself before opening any DCCs.

Streams support

Perforce Streams are detected automatically from p4 info's clientStream field — there is nothing to configure. The DousenDesktop status bar tells you what kind of workspace you're connected to, fetched once right after you sign in:

Each DCC addon's Dousen panel runs the same check locally and shows a compact version right next to your file lock status: Stream: <name> for a stream workspace, or Classic depot otherwise.

File locks inside your DCC

Blender, Maya, 3ds Max, Houdini, Substance Painter, and Substance Designer all show live Perforce status right where you're working, via p4 fstat (P4Python if it's installed, the p4 CLI otherwise). You can checkout (p4 edit), revert (p4 revert), sync (p4 sync), and add (p4 add) — all under your own Perforce identity. Checkout and add target whatever changelist the active Jira task resolves to (falling back to Perforce's default changelist if none is active), which is how a file ends up associated with the right CL without you having to pick one by hand.

Lock status polls roughly every 30 seconds and shows lines such as:

The Maya Dousen dock's Perforce tab, showing file lock and checkout status, sync, and changelist association.
Every DCC addon runs the same lock-status check inside its own panel.

If Perforce can't answer — server unreachable, or the file isn't in the depot at all — the row instead reads P4 error: <detail> or Not in Perforce.

Validated export also runs a pre-export lock check: if a file it needs to write is locked by someone else, the export is blocked before it starts so you don't lose work.

Shelving and unshelving

Perforce lets you shelve a changelist's files on the server without submitting them — handy for handing work to a reviewer or another artist without losing your local edits. GET /api/vcs/shelved?jira_key=... queries Perforce live for shelved changelists (p4 changes -s shelved -l) and keeps only the ones whose description carries the matching [dousen <jira_key>] marker — so it lists changelists Dousen opened for that task, not every shelved CL in the depot. There's no separate database flag that can go stale. The Unshelve button in the My Tasks detail pane calls POST /api/vcs/unshelve, which runs p4 unshelve -s <CL#> -f — the -f clobbers any writable local copy you already have, so it always wins over local edits to the same file.

Preview: shelved-changelist tracking is still being verified end-to-end against a live Perforce server and the desktop UI. The underlying p4 shelve / p4 unshelve plumbing works today, but don't build a hard team workflow around it until it's called out as generally available.

Auto Jira transition on submit

If your project admin has set up a project-level Jira connection and jira.on_submit_transition (a transition name, not a status name), submitting a Dousen changelist moves the linked Jira issue forward automatically — for example, sending it to review the moment you submit. Full details, including the two separate pieces of setup this needs and a known gap in the portal UI: Jira tasks.

Server connection (admin)

The server's connection to Perforce is configured by an administrator with environment variables. Artists never touch these — your personal Perforce identity lives in DousenDesktop.

VariablePurpose
DOUSEN_P4PORTPerforce server address.
DOUSEN_P4USERService user the server acts as.
DOUSEN_P4CLIENTService workspace used for the server's changelist operations.
DOUSEN_P4PASSWDOptional; falls back to the P4 ticket file if unset.

The server uses a single service workspace for its own changelist operations. Per-artist Perforce identity is handled entirely by DousenDesktop on each artist's machine.