Equity Transactions

Equity transactions track ownership changes in company shares. The API uses double-entry bookkeeping: each transaction creates balanced entries where shares move from one party to another (or from/to a void pool for issuances and retirements).

Endpoints

List Transactions

GET /api/v2/equity/transactions

Retrieves a paginated list of equity transactions.

Query Parameters

Parameter Type Required Description
client_account_id integer Yes Filter by client account
business_partner_id integer No Filter by shareholder
share_class string No Filter by share class (e.g., COMMON, PREFERRED)
transaction_type string No Filter by transaction type (e.g., ISSUANCE, TRANSFER)
date_from date No Filter transactions from this date
date_to date No Filter transactions to this date
page integer No Page number (default: 1)
per_page integer No Items per page (default: 100, max: 100)
with string No Include related resources (supported: business_partner, created_by, updated_by)

Response

{
  "data": [
    {
      "id": 1,
      "client_account_id": 7,
      "transaction_date": "2024-03-15",
      "transaction_type": "ISSUANCE",
      "transaction_group_id": "550e8400-e29b-41d4-a716-446655440000",
      "business_partner_id": 56,
      "share_class": "COMMON",
      "quantity": "1000.000000",
      "price_per_share": "100.000000",
      "notes": "Initial share issuance",
      "split_ratio_numerator": null,
      "split_ratio_denominator": null,
      "created_at": "2024-03-15T10:00:00Z",
      "created_by_id": 7,
      "updated_at": "2024-03-15T10:00:00Z",
      "updated_by_id": null
    }
  ],
  "meta": {
    "page": 1,
    "pages": 1,
    "per_page": 100,
    "records": 1
  }
}

Get Transaction

GET /api/v2/equity/transactions/{id}

Retrieves a specific equity transaction by ID.

Query Parameters

Parameter Type Required Description
with string No Include related resources (supported: business_partner, created_by, updated_by)

Response

{
  "id": 1,
  "client_account_id": 7,
  "transaction_date": "2024-03-15",
  "transaction_type": "ISSUANCE",
  "transaction_group_id": "550e8400-e29b-41d4-a716-446655440000",
  "business_partner_id": 56,
  "share_class": "COMMON",
  "quantity": "1000.000000",
  "price_per_share": "100.000000",
  "notes": "Initial share issuance",
  "split_ratio_numerator": null,
  "split_ratio_denominator": null,
  "created_at": "2024-03-15T10:00:00Z",
  "created_by_id": 7,
  "updated_at": "2024-03-15T10:00:00Z",
  "updated_by_id": null
}

Issue Shares

POST /api/v2/equity/transactions/issue

Issues new shares to a shareholder.

Request Body

Field Type Required Description
client_account_id integer Yes The client account ID
business_partner_id integer Yes The shareholder receiving shares
share_class string Yes Share class (see Share Classes)
quantity decimal Yes Number of shares to issue (must be positive)
price_per_share decimal No Price per share
transaction_date date No Transaction date (defaults to today)
notes string No Additional notes

Example Request

{
  "client_account_id": 7,
  "business_partner_id": 56,
  "share_class": "COMMON",
  "quantity": "1000",
  "price_per_share": "100",
  "transaction_date": "2024-03-15",
  "notes": "Series A funding round"
}

Response

Returns the shareholder’s transaction entry with status 201 Created.

Transfer Shares

POST /api/v2/equity/transactions/transfer

Transfers shares between shareholders.

Request Body

Field Type Required Description
client_account_id integer Yes The client account ID
from_business_partner_id integer Yes The shareholder transferring shares
to_business_partner_id integer Yes The shareholder receiving shares
share_class string Yes Share class being transferred
quantity decimal Yes Number of shares to transfer (must be positive)
price_per_share decimal No Transfer price per share
transaction_date date No Transaction date (defaults to today)
notes string No Additional notes

Example Request

{
  "client_account_id": 7,
  "from_business_partner_id": 56,
  "to_business_partner_id": 57,
  "share_class": "COMMON",
  "quantity": "500",
  "price_per_share": "150",
  "transaction_date": "2024-06-01",
  "notes": "Secondary sale"
}

Response

Returns the recipient’s transaction entry with status 201 Created.

Buyback Shares

POST /api/v2/equity/transactions/buyback

Company buys back shares from a shareholder. The shares become treasury stock held by the company.

Request Body

Field Type Required Description
client_account_id integer Yes The client account ID
from_business_partner_id integer Yes The shareholder selling shares
company_business_partner_id integer Yes The company entity receiving treasury stock
share_class string Yes Share class being bought back
quantity decimal Yes Number of shares to buy back (must be positive)
price_per_share decimal No Buyback price per share
transaction_date date No Transaction date (defaults to today)
notes string No Additional notes

Example Request

{
  "client_account_id": 7,
  "from_business_partner_id": 56,
  "company_business_partner_id": 58,
  "share_class": "COMMON",
  "quantity": "200",
  "price_per_share": "120",
  "notes": "Share buyback program"
}

Response

Returns the company’s transaction entry with status 201 Created.

Retire Shares

POST /api/v2/equity/transactions/retire

Retires treasury shares, permanently reducing total outstanding shares.

Request Body

Field Type Required Description
client_account_id integer Yes The client account ID
company_business_partner_id integer Yes The company entity holding treasury stock
share_class string Yes Share class being retired
quantity decimal Yes Number of shares to retire (must be positive)
transaction_date date No Transaction date (defaults to today)
notes string No Additional notes

Example Request

{
  "client_account_id": 7,
  "company_business_partner_id": 58,
  "share_class": "COMMON",
  "quantity": "100",
  "notes": "Treasury share cancellation"
}

Response

Returns the company’s transaction entry with status 201 Created.

Split Shares

POST /api/v2/equity/transactions/split

Performs a stock split or reverse split for a shareholder’s position.

Request Body

Field Type Required Description
client_account_id integer Yes The client account ID
business_partner_id integer Yes The shareholder whose shares are being split
share_class string Yes Share class being split
old_quantity decimal Yes Current number of shares (must match actual position)
new_quantity decimal Yes New number of shares after split
transaction_date date No Transaction date (defaults to today)
notes string No Additional notes

Example Request (2-for-1 Split)

{
  "client_account_id": 7,
  "business_partner_id": 56,
  "share_class": "COMMON",
  "old_quantity": "1000",
  "new_quantity": "2000",
  "notes": "2-for-1 stock split"
}

Example Request (Reverse Split 1-for-10)

{
  "client_account_id": 7,
  "business_partner_id": 56,
  "share_class": "COMMON",
  "old_quantity": "1000",
  "new_quantity": "100",
  "notes": "1-for-10 reverse split"
}

Response

Returns the resulting transaction entry with status 201 Created.

Get Positions

GET /api/v2/equity/positions

Retrieves current share positions (holdings) per shareholder and share class.

Query Parameters

Parameter Type Required Description
client_account_id integer Yes Filter by client account
business_partner_id integer No Filter by specific shareholder
share_class string No Filter by share class
include_void boolean No Include void (unissued) shares (default: false)

Response

{
  "positions": [
    {
      "business_partner_id": 56,
      "share_class": "COMMON",
      "quantity": "1500.000000",
      "cost_basis": "150000.000000"
    },
    {
      "business_partner_id": 57,
      "share_class": "COMMON",
      "quantity": "500.000000",
      "cost_basis": "75000.000000"
    }
  ]
}

Get Cap Table

GET /api/v2/equity/cap-table

Generates a capitalization table showing ownership distribution.

Query Parameters

Parameter Type Required Description
client_account_id integer Yes The client account ID
company_business_partner_id integer Yes The company entity (excluded from shareholder list)

Response

{
  "shareholders": [
    {
      "business_partner_id": 56,
      "name": "Investor A",
      "positions": {
        "COMMON": {
          "shares": "1500.000000",
          "percentage": "75.00"
        }
      },
      "total_shares": "1500.000000",
      "total_percentage": "75.00"
    },
    {
      "business_partner_id": 57,
      "name": "Investor B",
      "positions": {
        "COMMON": {
          "shares": "500.000000",
          "percentage": "25.00"
        }
      },
      "total_shares": "500.000000",
      "total_percentage": "25.00"
    }
  ],
  "share_classes": ["COMMON"],
  "total_shares": "2000.000000"
}

Get Share Classes

GET /api/v2/equity/share-classes

Returns available share class types.

Response

{
  "share_classes": [
    {"value": "COMMON", "label": "COMMON"},
    {"value": "PREFERRED", "label": "PREFERRED"},
    {"value": "SERIES_A", "label": "SERIES_A"},
    {"value": "SERIES_B", "label": "SERIES_B"},
    {"value": "SERIES_C", "label": "SERIES_C"},
    {"value": "SEED", "label": "SEED"},
    {"value": "CONVERTIBLE_NOTE", "label": "CONVERTIBLE_NOTE"},
    {"value": "SAFE", "label": "SAFE"}
  ]
}

Get Transaction Types

GET /api/v2/equity/transaction-types

Returns available transaction types.

Response

{
  "transaction_types": [
    {"value": "ISSUANCE", "label": "ISSUANCE"},
    {"value": "TRANSFER", "label": "TRANSFER"},
    {"value": "BUYBACK", "label": "BUYBACK"},
    {"value": "RETIREMENT", "label": "RETIREMENT"},
    {"value": "SPLIT", "label": "SPLIT"},
    {"value": "CONVERSION", "label": "CONVERSION"}
  ]
}

Share Classes

Value Description
COMMON Common/ordinary shares with voting rights
PREFERRED Preferred shares with priority dividends
SERIES_A Series A funding round shares
SERIES_B Series B funding round shares
SERIES_C Series C funding round shares
SEED Seed round shares
CONVERTIBLE_NOTE Convertible note instrument
SAFE Simple Agreement for Future Equity

Transaction Types

Value Description
ISSUANCE New shares issued to a shareholder
TRANSFER Shares transferred between shareholders
BUYBACK Company buys back shares from shareholder
RETIREMENT Company retires treasury stock
SPLIT Stock split or reverse split
CONVERSION Convert shares from one class to another

Error Responses

Status Code Description
400 Invalid request (missing fields, invalid share class, insufficient shares)
403 Forbidden (no access to client account)
404 Transaction not found

Insufficient Shares Error

When a transfer, buyback, retirement, or split cannot complete due to insufficient shares:

{
  "error": "Insufficient shares: shareholder has 500 but 1000 required",
  "status": 400
}

Business Rules

  1. Double-entry bookkeeping: Every transaction creates balanced entries (shares received = shares given)
  2. Quantity must be positive: All quantity parameters must be greater than zero
  3. Balance validation: Transfers, buybacks, retirements, and splits validate sufficient shares before proceeding
  4. Row-level locking: Concurrent transactions are prevented using database locks
  5. Cost basis tracking: Weighted average cost method is used when shares are sold
  6. Self-transfer prevention: Cannot transfer or buyback shares to/from the same entity
  7. Split validation: The old_quantity must exactly match the shareholder’s current position

Common Use Cases

  1. Company formation: Issue initial shares to founders
  2. Funding rounds: Issue new shares to investors (Series A, B, C)
  3. Secondary transactions: Transfer shares between existing shareholders
  4. Employee equity: Issue shares or options to employees
  5. Share buybacks: Company repurchases shares from shareholders
  6. Share cancellation: Retire treasury shares to reduce outstanding stock
  7. Stock splits: Adjust share count while maintaining ownership percentages