curl --request GET \
--url https://api.openagent.to/api/v1/investors/{id}/securities \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.openagent.to/api/v1/investors/{id}/securities"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.openagent.to/api/v1/investors/{id}/securities', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.openagent.to/api/v1/investors/{id}/securities",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.openagent.to/api/v1/investors/{id}/securities"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.openagent.to/api/v1/investors/{id}/securities")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.openagent.to/api/v1/investors/{id}/securities")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"docs": [
{
"_id": "ccc000000000000000000001",
"allowsNonAccredited": false,
"authorizationSource": "board_resolution",
"canceledShares": {
"$numberDecimal": "0"
},
"chain": "ethereum",
"chainId": "1",
"chainType": "evm",
"corporateActionBlackoutActive": false,
"createdAt": "2026-09-01T09:15:32.104Z",
"cusip": "CUSIP-SEED-001",
"decimalPlaces": 0,
"ercStandard": "ERC-20",
"externalId": "ext-sec-seed",
"isin": null,
"issuedShares": {
"$numberDecimal": "45000"
},
"issuerId": "aaa000000000000000000001",
"issuerName": "Acme Tokenization LLC",
"lastReconciliationAt": null,
"multiSigAddress": null,
"name": "Seed Preferred Equity",
"onChainTotalSupply": null,
"outstandingShares": {
"$numberDecimal": "45000"
},
"parValue": {
"$numberDecimal": "1.25"
},
"reconciliationStatus": "matched",
"reservedShares": {
"$numberDecimal": "10000"
},
"securityClass": "equity",
"securityType": "equity",
"status": "active",
"ticker": null,
"tokenAddress": "0x000000000000000000000000000000000000abcd",
"treasuryShares": {
"$numberDecimal": "0"
},
"updatedAt": "2026-09-01T09:15:32.104Z",
"updatedBy": null,
"uuid": "b92dd238-d117-4e41-85f8-cfb3fec02ec2",
"whitelistOnly": false
}
],
"hasNextPage": true,
"hasPrevPage": true,
"limit": 0,
"nextPage": 0,
"page": 0,
"pagingCounter": 0,
"prevPage": 0,
"totalDocs": 0,
"totalPages": 0
},
"message": "Success",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 200,
"success": true
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}{
"data": "<unknown>",
"message": "Success",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 404,
"success": false
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}List an investor's securities
Returns a page of the securities this investor holds KYC records against. Each row is the whole security document plus the issuer’s issuerName. Every share figure is BSON extended JSON, not a string and not a number: parValue, issuedShares, outstandingShares, treasuryShares, canceledShares, reservedShares and onChainTotalSupply all arrive as {"$numberDecimal": "…"}, because this pipeline returns the documents through a bare $replaceRoot with no $toString. Read the inner string and parse it with a decimal library. The /transactions endpoints return plain decimal strings and the reports return JSON numbers, so this is a third encoding — do not reuse a parser across them. authorizedShares is the exception: a plain string, and absent rather than null when unset. Doubly issuer-scoped, and both halves matter. An issuer_admin asking about an investor with no relationship to its issuer gets 404; for an investor it can see, the page is filtered to that issuer’s securities, applied before pagination so the counts are scoped too. An investor holding securities from several issuers therefore yields a smaller totalDocs for an issuer admin than for a ta_admin. Defaults: page 1, 10 per page, newest first. search matches the security’s name, externalId and uuid. Requires investor:read.
curl --request GET \
--url https://api.openagent.to/api/v1/investors/{id}/securities \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.openagent.to/api/v1/investors/{id}/securities"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.openagent.to/api/v1/investors/{id}/securities', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.openagent.to/api/v1/investors/{id}/securities",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.openagent.to/api/v1/investors/{id}/securities"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.openagent.to/api/v1/investors/{id}/securities")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.openagent.to/api/v1/investors/{id}/securities")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"docs": [
{
"_id": "ccc000000000000000000001",
"allowsNonAccredited": false,
"authorizationSource": "board_resolution",
"canceledShares": {
"$numberDecimal": "0"
},
"chain": "ethereum",
"chainId": "1",
"chainType": "evm",
"corporateActionBlackoutActive": false,
"createdAt": "2026-09-01T09:15:32.104Z",
"cusip": "CUSIP-SEED-001",
"decimalPlaces": 0,
"ercStandard": "ERC-20",
"externalId": "ext-sec-seed",
"isin": null,
"issuedShares": {
"$numberDecimal": "45000"
},
"issuerId": "aaa000000000000000000001",
"issuerName": "Acme Tokenization LLC",
"lastReconciliationAt": null,
"multiSigAddress": null,
"name": "Seed Preferred Equity",
"onChainTotalSupply": null,
"outstandingShares": {
"$numberDecimal": "45000"
},
"parValue": {
"$numberDecimal": "1.25"
},
"reconciliationStatus": "matched",
"reservedShares": {
"$numberDecimal": "10000"
},
"securityClass": "equity",
"securityType": "equity",
"status": "active",
"ticker": null,
"tokenAddress": "0x000000000000000000000000000000000000abcd",
"treasuryShares": {
"$numberDecimal": "0"
},
"updatedAt": "2026-09-01T09:15:32.104Z",
"updatedBy": null,
"uuid": "b92dd238-d117-4e41-85f8-cfb3fec02ec2",
"whitelistOnly": false
}
],
"hasNextPage": true,
"hasPrevPage": true,
"limit": 0,
"nextPage": 0,
"page": 0,
"pagingCounter": 0,
"prevPage": 0,
"totalDocs": 0,
"totalPages": 0
},
"message": "Success",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 200,
"success": true
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}{
"data": "<unknown>",
"message": "Success",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 404,
"success": false
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}{
"error": {
"code": "Validation error",
"details": [
{
"field": "email",
"message": "Invalid email format",
"allowedValues": [
"<string>"
]
}
]
},
"message": "Validation error",
"meta": {
"timestamp": "2026-09-01T09:15:32.104Z",
"requestId": "3f1c9d2e-6b7a-4f18-9c53-0a2b6d4e8f10"
},
"statusCode": 422,
"success": false
}Authorizations
Staff access token. Sent as Authorization: Bearer <token>, or — when that header is absent — read from the accessToken cookie, which is how the admin app authenticates. Tokens carry a tokenVersion; logout and password reset bump it, revoking every outstanding token for that account.
Path Parameters
^[a-f\d]{24}$Query Parameters
1-based page number. Defaults to 1.
x <= 9007199254740991Records per page, 1-100. Defaults to 20.
x <= 100Field names separated by spaces (or commas, which are normalized to spaces), - prefix for descending. Defaults to -createdAt.
^-?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?:[\s,]+-?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)*$Case-insensitive substring matched against securities.name, securities.externalId, securities.uuid.
Comma-separated subset of securities.name, securities.externalId, securities.uuid to match search against. Names outside that list are ignored, and an empty intersection falls back to all of them.

