Vault HTTP API

Public vault endpoints return indexed state and history. Capital transactions are wallet-signed. Operator commands go over the authenticated /vault WebSocket session.

Base URL and types

Devnet: https://devnet-api.acta.markets/api/v1. Beta: https://beta-api.acta.markets/api/v1.

Addresses are base58 strings. Token amounts, share amounts, large counters and Unix-second timestamps are decimal strings unless a field is listed as a JSON number. Share prices and the high-water mark use a scale of 1_000_000_000. Parse exact values with BigInt or another integer-safe representation.

Basis-point fields are JSON numbers. 100 basis points is 1%. Percent-return fields are JSON numbers in percent. A nullable field is null when the value is not available.

Vault list and detail

  • GET /vaults returns { "vaults": Vault[] }.
  • GET /vaults/{pda} returns one Vault object.

The list has no pagination. Optional query delegate=<pubkey> returns only vaults that key can operate as delegate: it is the primary_delegate and holds an unexpired delegate grant. A value that is not a base58 pubkey returns 400 invalid_delegate. Apply other filters on the client.

Closed vaults are left out of the list. Detail for a closed or unknown vault returns 404. History routes still serve closed vaults.

Vault fields

FieldsJSON typeMeaning
vault_pda, governance, fee_recipient, primary_delegatestringVault and authority addresses.
vault_idstring32-byte identifier encoded as 64 lowercase hex characters, without 0x.
main_mint, second_mint, share_mintstringAsset and share-mint addresses.
main_decimals, second_decimalsnumberToken decimals.
main_token_program, second_token_programlegacy_spl or token_2022Token-program family.
phaseidle, active, settling, processing_capitalTrading/capital phase.
safetynormal, frozen, emergency_unwind, withdraw_only, closingSafety mode.
capabilitiesnumberStrategy capability bitmask.
accepting_deposits, equity_computedbooleanIntake and capital-pricing flags.
active_expiry, open_positionsstringCurrent expiry and position count.
total_sharesstringContract's boundary supply checkpoint, not the live mint supply.
share_price, share_price_hwmstringFixed-scale price per share and high-water mark.
equity, capital_generationstringAccounted value in main atoms and capital generation.
pending_deposit_count, pending_withdraw_countnumberQueue counts.
pending_deposit_amount, pending_withdraw_sharesstringPending main-token amount and pending shares.
performance_fee_bps, management_fee_bps, manager_stake_min_bpsnumberFee and stake settings.
last_hwm_update_ts, last_hwm_reset_ts, last_settlement_tsstringRecorded timestamps.
cap_limit, capital_fallback_delay_secsstringDeposit capacity and fallback delay.
deposit_window_set_tsstring or nullRecorded intake-window timestamp.
main_balance, second_balance, live_share_supply, observed_manager_stake_sharesstring or nullBalances and supply read from chain separately from events.
balance_updated_at, balance_chain_slotstring or nullWhen those balances were read, and at which chain slot.
policyobjectPolicy fields below.
projectionobjectIndexed event coordinate below.
performanceobjectPerformance variant below.

policy contains the numeric fields max_open_positions, max_rebalance_drift_bps and min_main_liquidity_bps.

projection contains version and slot as strings, transaction_index and event_index as numbers, and signature as a string. Balances carry their own timestamps in balance_updated_at and balance_chain_slot.

performance is one of:

  • { "status": "unavailable" }
  • { "status": "no_track_record" }
  • status: "short_track_record" with cycles_completed, last_cycle_return_pct, cumulative_return_pct as numbers and track_record_secs as a string.
  • status: "annualized" with the same fields plus numeric annualized_return_pct.

Annualization needs at least 30 days of completed-cycle history. Shares, equity and fees explains boundary equity, share price and live share ownership.

Position memberships

GET /vaults/{pda}/positions

QueryTypeDefault / range
settledbooleanOptional settlement filter.
limitinteger100; 1–200.
cursorstringOptional opaque cursor.

The response is { "positions": VaultPosition[], "next_cursor": string | null }.

Position fieldsJSON type
vault, position, market, counterpartystring
order_idstring
rolewriter or holder
position_typecovered_call or cash_secured_put
statusopen, funded, liquidated, settled
strike, quantity, net_premiumstring
created_at, acquired_atstring
funded_amount, settled_at, transaction_signaturestring or null
is_otmboolean or null

A dual-vault position has one chain position and a role-specific membership for each participating vault.

Cycles

GET /vaults/{pda}/cycles?limit=50&cursor=...

limit defaults to 50 and accepts 1–200. The response is { "cycles": VaultCycle[], "next_cursor": string | null }.

Cycle fieldsJSON type
cycle_number, expiry, started_atstring
share_price_start, equity_startstring
performance_fee_assessed, management_fee_assessedstring
finished_at, share_price_end, equity_endstring or null
positions_opened, positions_settlednumber
return_pctnumber or null

An unfinished cycle can have valuation data without a completed-cycle return. Read capital_generation from vault detail.

Pending request queues

  • GET /vaults/{pda}/deposit-requests
  • GET /vaults/{pda}/withdraw-requests

Both accept limit (default 50, range 1–100) and an optional cursor. Both return { "requests": Request[], "next_cursor": string | null }.

A deposit request contains wallet, amount, created_at as strings and nullable string transaction_signature. A withdrawal request contains wallet, shares, created_at as strings and nullable string transaction_signature.

Completed payouts are in depositor history.

Depositor state

  • GET /vaults/{pda}/depositors/{wallet} returns one DepositorState.
  • GET /depositors/{wallet} returns { "wallet": string, "vaults": DepositorState[] }.
DepositorState fieldJSON type
vault, walletstring
deposit_requestobject or null
withdraw_requestobject or null
totalsobject or null

deposit_request contains string amount, string created_at and nullable string transaction_signature. withdraw_request contains string shares, string created_at and nullable string transaction_signature.

totals contains string fields shares_minted, shares_burned, total_deposited, total_withdrawn and last_activity_at.

For a valid wallet with no indexed activity, the single-vault route returns vault and wallet with the three optional fields set to null. The cross-vault route can return an empty vaults array.

The totals sum indexed capital activity. Shares can move between wallets, so read current balances from the wallet's token accounts on Solana.

Depositor history

  • GET /vaults/{pda}/depositors/{wallet}/history
  • GET /depositors/{wallet}/history

Both accept limit (default 50, range 1–200) and an optional opaque cursor. The response is { "events": DepositorEvent[], "next_cursor": string | null }.

Event fieldJSON type
vaultstring
actiondeposit_processed, withdraw_processed, deposit_cancelled, withdraw_cancelled, deposit_refunded
amount, second_amount, shares, event_time, transaction_signaturestring
boundary_pricestring or null

A final redemption can pay out the second asset. second_amount records it apart from the main-asset amount.

Pagination example

Fetch the first page, then pass the returned cursor back:

curl 'https://devnet-api.acta.markets/api/v1/vaults/<vault-pda>/cycles?limit=50'
curl --get 'https://devnet-api.acta.markets/api/v1/vaults/<vault-pda>/cycles' \
  --data-urlencode 'limit=50' \
  --data-urlencode 'cursor=<returned-next_cursor>'

next_cursor: null is the last page. Send the cursor unchanged to the same route with the same filters, URL-encoded.

Errors and freshness

List and detail are served from memory. Other routes read the database. List, detail, positions, cycles and pending queues can be cached for five seconds.

Errors use { "error": "Human-readable message", "code": "error_code" }.

HTTP statusCodesHandling
400invalid_cursor, invalid_limit, invalid_wallet, invalid_delegate, invalid_requestCorrect the input.
404not_foundCheck the address and route. Closed vaults no longer have list/detail entries.
503db_disabledDatabase access is not configured for this route.
503db_busy, unavailable, caps_projection_unavailable, chain_replay_unavailable, position_history_unavailableRetry later. Keep showing the last result with its timestamp.
500history_projection_incomplete, data_validation_error, schema_error, db_errorReport the failed read. Keep the previous data.
429Rate limitSlow down.

HTTP data changes only after the backend indexes a transaction, so read chain accounts right after you submit one. See Backend services and data and Transaction recovery.