Transfer Stock
In /app, open /app/companies/<issuerId>?view=transfer-stock. The connected ADMIN wallet calls CapTable.transferStock. There is no transfer registration endpoint: the poller mirrors the confirmed transfer into MongoDB. The server-signed API alternative below uses transferController.js.
Transfer shares from one stakeholder to another. The recipient (transferee) must already exist on the cap table before you can transfer stock to them.
Confirm the transferee exists
The recipient must already be a stakeholder on this issuer. If needed, complete Create a Stakeholder, then return with the recipient’s stakeholder ID.
Transfer the stock
Send a POST request to http://localhost:8293/transactions/transfer/stock
{
"issuerId": "<YOUR_ISSUER_ID>",
"data": {
"transferorId": "<FROM_STAKEHOLDER_ID>",
"transfereeId": "<TO_STAKEHOLDER_ID>",
"stockClassId": "<STOCK_CLASS_ID>",
"quantity": "13",
"sharePrice": "4.20",
"isBuyerVerified": true
}
}The response returns "success" when the transfer is recorded onchain.
sharePrice is the human price per share. The contract stores it scaled by 1e10 (10,000,000,000). Divide raw onchain values by 1e10 before comparing. The server handles scaling automatically.
Verify the transfer
Check historical transactions to confirm:
GET /historical-transactions/issuer-id/<YOUR_ISSUER_ID>Required fields
| Field | Description |
|---|---|
transferorId | Stakeholder transferring the shares (seller). |
transfereeId | Stakeholder receiving the shares (buyer). |
stockClassId | The class of stock being transferred. |
quantity | Number of shares to transfer, as a string integer. |
sharePrice | Human price per share. The contract stores sharePrice * 1e10 (10,000,000,000). |
isBuyerVerified | true once the buyer has cleared whatever KYC/eligibility check your application requires. The contract reverts with UnverifiedBuyer if this is false. |
Partial transfers
The transfer API body has no security_id. transferStock walks the transferor’s live lots for that stock class and salts new issuance/security ids with an in-memory issuanceOrdinal so multi-lot transfers stay distinct. If the requested quantity is less than a lot, the contract issues a balance security to the transferor for the leftover shares. Read the new security_id from history after the poller catches up; do not reuse validation UUIDs from /transactions/issuance/stock.