Browse the API reference

Create Portfolio Block

post/extensions/roboinvestor/{graph_id}/operations/create-portfolio-block

Part of Extensions: RoboInvestor.

Create a portfolio with optional initial positions in a single atomic envelope. Each position references an existing security; this operation never mints securities (use create-security). Whole envelope validates before any write.

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.

Authentication

Authenticate in any one of these ways — not all of them:

  • API key in the X-API-Key header.
  • Bearer token in the Authorization header.

Path parameters

NameTypeDescription
graph_idrequiredstringGraph Id

Header parameters

NameTypeDescription
Idempotency-KeyoptionalstringIdempotency-Key

Request body

Required, application/json.

FieldTypeDescription
portfoliorequiredPortfolioBlockPortfolioFields

Core portfolio fields — name, currency, owning entity, etc.

PortfolioBlockPortfolioFields fields
FieldTypeDescription
namerequiredstring

Display name for the portfolio. 1-200 characters.

descriptionoptionalstring

Free-text description of the portfolio.

strategyoptionalstring

Free-text strategy classification (e.g. `value`, `growth`, `income`). Open vocabulary.

inception_dateoptionalstring (date)

Date the portfolio was established (YYYY-MM-DD).

base_currencyoptionalstring

ISO 4217 currency code used for portfolio-level aggregates (e.g. `total_cost_basis_dollars`).

Default: USD

entity_idoptionalstring

ID of the owning entity (e.g. fund, trust, or person). Optional — leave unset for unattributed portfolios.

positionsoptionalPortfolioBlockPositionAdd[]

Initial positions to mint inside the new portfolio. Each references an existing security; pass `[]` to create an empty portfolio.

PortfolioBlockPositionAdd fields
FieldTypeDescription
security_idrequiredstring

ID of the existing security this position holds. Securities are minted via `create-security`; the operation returns 404 if the ID is unknown.

quantityrequirednumber

Quantity held, in units defined by `quantity_type` (e.g. share count for `shares`, face value for `principal`).

quantity_typeoptionalstring

Unit basis for `quantity`. Common values: `shares` (equity units), `units` (generic), `principal` (debt face value).

Default: shares

cost_basisoptionalinteger

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`.

Default: 0

currencyoptionalstring

ISO 4217 currency code for `cost_basis` and `current_value`.

Default: USD

current_valueoptionalinteger

Latest mark-to-market value in **cents** of `currency`, or `null` if unmarked. Pair with `valuation_date` and `valuation_source` when set.

valuation_dateoptionalstring (date)

Date `current_value` was sourced (YYYY-MM-DD).

valuation_sourceoptionalstring

Free-text source attribution for `current_value` (e.g. `manual`, `broker_statement`, vendor name).

acquisition_dateoptionalstring (date)

Date the position was originally acquired (YYYY-MM-DD).

notesoptionalstring

Free-text notes attached to the position.

Example request

curl
curl -X POST "https://api.robosystems.ai/extensions/roboinvestor/{graph_id}/operations/create-portfolio-block" \
  -H "X-API-Key: $ROBOSYSTEMS_API_KEY" \
  -H "Idempotency-Key: <Idempotency-Key>" \
  -H "Content-Type: application/json" \
  -d '{
  "portfolio": {
    "base_currency": "USD",
    "description": "Mid-cap public equities",
    "entity_id": "ent_acme_holdings",
    "inception_date": "2026-01-01",
    "name": "Q1 2026 Growth",
    "strategy": "growth"
  },
  "positions": [
    {
      "acquisition_date": "2026-01-15",
      "cost_basis": 1850000,
      "currency": "USD",
      "current_value": 2010000,
      "quantity": 100,
      "quantity_type": "shares",
      "security_id": "sec_aapl",
      "valuation_date": "2026-04-30",
      "valuation_source": "broker_statement"
    },
    {
      "acquisition_date": "2026-02-08",
      "cost_basis": 2125000,
      "currency": "USD",
      "current_value": 2240000,
      "quantity": 50,
      "quantity_type": "shares",
      "security_id": "sec_msft",
      "valuation_date": "2026-04-30",
      "valuation_source": "broker_statement"
    }
  ]
}'

Responses

200 Successful Response

FieldTypeDescription
operationrequiredstring

Kebab-case operation name

operationIdrequiredstring

op_-prefixed ULID for audit and SSE correlation

statusrequiredstring

Operation lifecycle state

One of: completed, pending, failed

resultoptionalPortfolioBlockEnvelope

Command-specific result payload

PortfolioBlockEnvelope fields
FieldTypeDescription
idrequiredstring

Portfolio ID (`port_*` ULID).

namerequiredstring

Display name.

descriptionoptionalstring

Free-text description.

strategyoptionalstring

Free-text strategy classification.

inception_dateoptionalstring (date)

Date the portfolio was established.

base_currencyrequiredstring

ISO 4217 currency code for portfolio aggregates.

owneroptionalEntityLite

Embedded owning entity, when set. `null` for unattributed portfolios.

EntityLite fields
FieldTypeDescription
idrequiredstring

Entity ID (`ent_*` ULID).

namerequiredstring

Display name of the entity.

source_graph_idoptionalstring

Tenant graph this entity is anchored to, when known. `null` for entities not yet linked to a graph.

positionsrequiredPositionBlock[]

All positions in this portfolio, including disposed ones (filter by `status` for active-only display).

PositionBlock fields
FieldTypeDescription
idrequiredstring

Position ID (`pos_*` ULID).

quantityrequirednumber

Quantity held in `quantity_type` units.

quantity_typerequiredstring

Unit basis (`shares`, `units`, `principal`).

cost_basis_dollarsrequirednumber

Cost basis in dollars (pre-converted from cents).

current_value_dollarsoptionalnumber

Latest mark-to-market value in dollars. `null` when the position has not been marked.

valuation_dateoptionalstring (date)

Date the current value was sourced.

valuation_sourceoptionalstring

Free-text source attribution for the valuation.

acquisition_dateoptionalstring (date)

Date the position was acquired.

statusrequiredstring

Lifecycle state (`active`, `disposed`, `archived`). See `PositionResponse.status` for the full vocabulary.

notesoptionalstring

Free-text notes attached to the position.

securityrequiredSecurityLite

Embedded security details — name, type, issuer.

total_cost_basis_dollarsrequirednumber

Sum of `cost_basis_dollars` across every position.

total_current_value_dollarsoptionalnumber

Sum of `current_value_dollars` across every position. `null` when any active position lacks a mark.

active_position_countrequiredinteger

Count of positions with `status='active'`.

created_atrequiredstring (date-time)

Row creation timestamp (UTC).

updated_atrequiredstring (date-time)

Last-modified timestamp (UTC).

atrequiredstring

ISO-8601 UTC timestamp

createdByoptionalstring

User ID that initiated the operation (null for legacy callers)

idempotentReplayoptionalboolean

True when this envelope came from the idempotency cache — the underlying command did not execute again. False on fresh executions.

Default: false

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