---
title: "Update Portfolio Block"
method: POST
path: "/extensions/roboinvestor/{graph_id}/operations/update-portfolio-block"
tags: ["RoboInvestor"]
---

# Update Portfolio Block

`POST /extensions/roboinvestor/{graph_id}/operations/update-portfolio-block`

## Request

- Base URL: `https://api.robosystems.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.robosystems.ai/extensions/roboinvestor/{graph_id}/operations/update-portfolio-block`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Patch portfolio fields and apply position deltas (`add` / `update` / `dispose`) atomically. Partial failures roll back.

**Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict.

## Path parameters

- `graph_id` string, required

## Headers

- `Idempotency-Key` string, nullable

## Request body

- UpdatePortfolioBlockOperation: CQRS body for `POST /operations/update-portfolio-block`. Carries an optional patch to portfolio fields and three position delta lists (`add` / `update` / `dispose`). All apply atomically with the portfolio patch — partial failures roll back.
  - `portfolio_id` string, required: Target portfolio ID.
  - `portfolio` PortfolioBlockPortfolioPatch: Patchable portfolio fields on `update-portfolio-block`. Unset fields ignored.
    - `name` string, nullable: New display name. Unset = unchanged.
    - `description` string, nullable: New description. Unset = unchanged.
    - `strategy` string, nullable: New strategy classification. Unset = unchanged.
    - `inception_date` string, date, nullable: New inception date (YYYY-MM-DD). Unset = unchanged.
    - `base_currency` string, nullable: New ISO 4217 base currency code. Unset = unchanged. Note: changing base currency does not retroactively reprice historical positions.
    - `entity_id` string, nullable: New owning-entity ID. Unset = unchanged.
  - `positions` PortfolioBlockPositions: Position deltas applied atomically inside `update-portfolio-block`.
    - `add` PortfolioBlockPositionAdd[]: New positions to mint inside this portfolio. Each references an existing `security_id`.
      - `security_id` string, required: ID of the existing security this position holds. Securities are minted via `create-security`; the operation returns 404 if the ID is unknown.
      - `quantity` number, required: Quantity held, in units defined by `quantity_type` (e.g. share count for `shares`, face value for `principal`).
      - `quantity_type` string: Unit basis for `quantity`. Common values: `shares` (equity units), `units` (generic), `principal` (debt face value).
      - `cost_basis` integer: Total cost basis for this lot, in **cents** of `currency`. Stored as integer cents to avoid float precision drift; $1,250.00 USD is `125000`.
      - `currency` string: ISO 4217 currency code for `cost_basis` and `current_value`.
      - `current_value` integer, nullable: Latest mark-to-market value in **cents** of `currency`, or `null` if unmarked. Pair with `valuation_date` and `valuation_source` when set.
      - `valuation_date` string, date, nullable: Date `current_value` was sourced (YYYY-MM-DD).
      - `valuation_source` string, nullable: Free-text source attribution for `current_value` (e.g. `manual`, `broker_statement`, vendor name).
      - `acquisition_date` string, date, nullable: Date the position was originally acquired (YYYY-MM-DD).
      - `notes` string, nullable: Free-text notes attached to the position.
    - `update` PortfolioBlockPositionUpdate[]: Patches to existing positions, addressed by position `id`. Unset fields on each entry are left unchanged.
      - `id` string, required: Target position ID. Must belong to the portfolio identified by `portfolio_id` on the parent operation.
      - `quantity` number, nullable: New quantity in units of `quantity_type`. Unset = unchanged.
      - `quantity_type` string, nullable: New unit basis (`shares` | `units` | `principal`). Unset = unchanged.
      - `cost_basis` integer, nullable: New cost basis in **cents** of the position's currency. Unset = unchanged.
      - `current_value` integer, nullable: New mark-to-market value in **cents**. Unset = unchanged. Set alongside `valuation_date` / `valuation_source` to record a fresh valuation event.
      - `valuation_date` string, date, nullable: New valuation date (YYYY-MM-DD). Unset = unchanged.
      - `valuation_source` string, nullable: New valuation source attribution. Unset = unchanged.
      - `acquisition_date` string, date, nullable: New acquisition date (YYYY-MM-DD). Unset = unchanged.
      - `notes` string, nullable: New notes. Unset = unchanged.
    - `dispose` PortfolioBlockPositionDispose[]: Positions to soft-dispose, addressed by position `id`. Status flips to `disposed` and `disposition_date` is stamped.
      - `id` string, required: Target position ID to dispose. Must belong to the portfolio identified by `portfolio_id` on the parent operation.
      - `disposition_reason` string, nullable: Optional free-text reason recorded under `metadata.disposition_reason` on the disposed position.

## Response `200`

Successful Response

- OperationEnvelopePortfolioBlockEnvelope
  - `operation` string, required: Kebab-case operation name
  - `operationId` string, required: op_-prefixed ULID for audit and SSE correlation
  - `status` 'completed' | 'pending' | 'failed', required: Operation lifecycle state
  - `result` PortfolioBlockEnvelope: Molecular response shape for portfolio-block operations. Bundles the portfolio core, its embedded positions, and pre-computed totals into a single payload — the contract for `create-portfolio-block`, `update-portfolio-block`, and the read-side `get-portfolio-block`. Cents-precision values aren't surfaced here; use `PositionResponse` / `PortfolioResponse` for those.
    - `id` string, required: Portfolio ID (`port_*` ULID).
    - `name` string, required: Display name.
    - `description` string, nullable: Free-text description.
    - `strategy` string, nullable: Free-text strategy classification.
    - `inception_date` string, date, nullable: Date the portfolio was established.
    - `base_currency` string, required: ISO 4217 currency code for portfolio aggregates.
    - `owner` EntityLite: Lightweight entity projection for embedding in portfolio-block / position envelopes. Carries identity-only fields; full entity data lives behind the Master Data entity APIs.
      - `id` string, required: Entity ID (`ent_*` ULID).
      - `name` string, required: Display name of the entity.
      - `source_graph_id` string, nullable: Tenant graph this entity is anchored to, when known. `null` for entities not yet linked to a graph.
    - `positions` PositionBlock[], required: All positions in this portfolio, including disposed ones (filter by `status` for active-only display).
      - `id` string, required: Position ID (`pos_*` ULID).
      - `quantity` number, required: Quantity held in `quantity_type` units.
      - `quantity_type` string, required: Unit basis (`shares`, `units`, `principal`).
      - `cost_basis_dollars` number, required: Cost basis in dollars (pre-converted from cents).
      - `current_value_dollars` number, nullable: Latest mark-to-market value in dollars. `null` when the position has not been marked.
      - `valuation_date` string, date, nullable: Date the current value was sourced.
      - `valuation_source` string, nullable: Free-text source attribution for the valuation.
      - `acquisition_date` string, date, nullable: Date the position was acquired.
      - `status` string, required: Lifecycle state (`active`, `disposed`, `archived`). See `PositionResponse.status` for the full vocabulary.
      - `notes` string, nullable: Free-text notes attached to the position.
      - `security` SecurityLite, required: Lightweight security projection for embedding in position envelopes. Skips `terms`, `outstanding_shares`, etc. — fetch the full `SecurityResponse` when those are needed.
        - `id` string, required: Security ID (`sec_*` ULID).
        - `name` string, required: Display name of the security.
        - `security_type` string, required: Instrument family (e.g. `common_stock`, `preferred_stock`, `warrant`).
        - `security_subtype` string, nullable: Optional subtype refinement (e.g. `class_a`).
        - `is_active` boolean, required: `true` when the security is in active status.
        - `issuer` EntityLite: Lightweight entity projection for embedding in portfolio-block / position envelopes. Carries identity-only fields; full entity data lives behind the Master Data entity APIs.
          - `id` string, required: Entity ID (`ent_*` ULID).
          - `name` string, required: Display name of the entity.
          - `source_graph_id` string, nullable: Tenant graph this entity is anchored to, when known. `null` for entities not yet linked to a graph.
        - `source_graph_id` string, nullable: Tenant graph the security is pre-associated to, if any.
    - `total_cost_basis_dollars` number, required: Sum of `cost_basis_dollars` across every position.
    - `total_current_value_dollars` number, nullable: Sum of `current_value_dollars` across every position. `null` when any active position lacks a mark.
    - `active_position_count` integer, required: Count of positions with `status='active'`.
    - `created_at` string, date-time, required: Row creation timestamp (UTC).
    - `updated_at` string, date-time, required: Last-modified timestamp (UTC).
  - `at` string, required: ISO-8601 UTC timestamp
  - `createdBy` string, nullable: User ID that initiated the operation
  - `idempotentReplay` boolean: True when this envelope came from the idempotency cache — the underlying command did not execute again. False on fresh executions.

## Other responses

- `400`: Invalid request
- `401`: Authentication required
- `403`: Access denied
- `404`: Resource not found
- `409`: Idempotency-Key conflict — key reused with different body
- `422`: Validation error
- `429`: Rate limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/robosystems/apis/robosystems-api.md) · [All operations](https://skmtc.dev/robosystems/apis/robosystems-api/llms.txt) · [OpenAPI document](https://skmtc.dev/robosystems/apis/robosystems-api/revisions/e661e2d5ca6a?raw)
