---
title: "Update Placement"
method: PATCH
path: "/api/external/v2/placements/{placement_id}"
tags: ["external-v2-placements"]
---

# Update Placement

`PATCH /api/external/v2/placements/{placement_id}`

Partially update an existing placement (JSON Merge Patch semantics).

Only the fields present in the request body are updated.  An empty body
(all fields absent) returns 400 because no meaningful update was requested.
Use ``status="archived"`` to remove a placement from active views — this
mirrors the existing app convention (no row-level delete is supported).

Returns 404 for placements on foreign-account deals or non-existent
placements.

## Path parameters

- `placement_id` integer, required

## Request body

- UpdatePlacementRequest — PATCH /api/external/v2/placements/<id> request body. Only the fields present in the request body are updated (partial update / JSON Merge Patch semantics). ``deal_id``, ``private_company_id``, and ``contact_id`` are intentionally absent — a placement's deal, lender, and contact are set at create-time and cannot be reassigned (mirrors F-016 on ``UpdateContactRequest`` and the GraphQL ``UpdatePlacementInput`` shape). To "move" a placement to a different lender or contact, archive the existing placement (``status='archived'``) and create a new one. Set ``status='archived'`` to remove a placement from active views — this is the convention used by the rest of the app (see ``Placement.NON_ACTIVE_PLACEMENT_STATUSES``).
  - `status` 'new' | 'sent' | 'lender_reviewing' | 'terms_received' | 'term_sheet_received' | 'executed_ts_in_closing' | 'closed' | 'unresponsive' | 'willing_to_negotiate' | 'lender_passed' | 'archived'
  - `visibility` 'hidden' | 'masked' | 'shared'
  - `description` string, nullable — Free-text description / per-lender note.
  - `score` number, nullable — Manual relevance score (0-100).
  - `outreach_date` string, date-time, nullable — Timestamp the lender was first reached out to (ISO 8601).
  - `lender_status` 'origination' | 'new' | 'lead_qualification' | 'quotation' | 'negotiation' | 'offer' | 'term_sheet' | 'good_faith_deposit' | 'diligence' | 'in_closing' | 'closed' | 'archived'

## Response `200`

Successful Response

- PlacementObjectResponse — OpenAPI schema for GET /api/external/v2/placements/<id> (object envelope).
  - `request_id` string, required
  - `timestamp` string, required
  - `data` PlacementResponse, required
    - `id` integer, required
    - `deal_id` integer, required
    - `contact_id` integer, nullable
    - `private_company_id` integer, nullable
    - `lender_name` string, nullable — Lender display name for this placement — the account's own CRM / address-book name for the lender, falling back to the canonical lender (Organization) name when the CRM record is unnamed. Null when no lender is set. Embedded so callers need not resolve private_company_id via a separate lookup. For non-owner viewers of masked placements, this is a stable masked label such as 'Lender A'.
    - `contact_name` string, nullable — Full name of the lender contact on this placement. Null when no contact is set, or when a non-owner viewer is reading a masked placement.
    - `status` string, nullable
    - `visibility` string, nullable
    - `lender_status` string, nullable
    - `description` string, nullable
    - `score` number, nullable
    - `lev_score` number, nullable
    - `outreach_source` string, nullable
    - `outreach_date` string, nullable
    - `lender_first_response_date` string, nullable
    - `last_communication_date` string, nullable
    - `created_at` string, nullable
    - `updated_at` string, nullable

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/lev/apis/lev-api.md) · [All operations](https://skmtc.net/lev/apis/lev-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/lev/lev-api/revisions/e1915e1423cf/schema)
