Browse the extensions reference

Create Portfolio Block

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

Part of 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