Skip to content

Create the Trade

With your investors onboarded and qualified, you can build the subscription process. A trade records an account's commitment to buy a number of units in an offering. Creating a trade doesn't move money: it reserves the units and sets the amount the investor owes. You collect the funds in the next step, Collect Payment, and the trade's status follows the money from there.

Before You Start

  • The offering exists and has an approved escrow account. See Set Up an Offering. Keep the offeringId.
  • The investing account exists and has an active primary party link. See Onboard Investors. Keep the accountId.
  • Your platform has finished the qualification checks it requires, such as KYC/AML, suitability, and accreditation. See Qualify Investors. createTrade doesn't check qualification statuses, so apply your eligibility rules before you call it.
  • You have registered webhooks for the trade methods listed under Webhooks.

Steps

1. Create the trade

Call createTrade to place the account's order against the offering.

curl -X POST "$TAPI_HOST/v3/createTrade" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d offeringId=12345 \
  -d accountId=A12345 \
  -d transactionType=ACH \
  -d transactionUnits=100 \
  -d createdIpAddress=10.0.0.9
Field Required Notes
offeringId Yes Must be numeric.
accountId Yes The investing account. The trade is recorded against the account's primary party.
transactionType Yes The payment method. See Transaction types.
transactionUnits Yes A positive number that doesn't exceed the offering's remaining units. The trade amount is the offering's unit price × transactionUnits, plus fees, and must fall between the offering's minimum and maximum amounts.
fees No A non-negative amount added to the trade amount.
createdIpAddress No The investor's IP address, stored on the trade.
field1, field2, field3 No Custom fields for your own references.
RRApprovalStatus, PrincipalApprovalStatus No Default to Pending.
closeId No Groups the trade into a closing.
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "purchaseDetails": [
    true,
    [
      {
        "tradeId": "100012345",
        "transactionId": "54321",
        "transactionAmount": "1000.000000",
        "transactionDate": "2026-01-15 10:30:00",
        "transactionStatus": "CREATED",
        "RRApprovalStatus": "Pending",
        "PrincipalApprovalStatus": "Pending",
        "closeId": null,
        "eligibleToClose": "no"
      }
    ]
  ]
}

Keep the tradeId from purchaseDetails[1][0]. Every later step (subscription documents, payments, status updates) uses it.

Transaction types

transactionType isn't checked against a fixed list. TransactAPI stores it uppercased, with spaces and underscores removed, so credit card is stored as CREDITCARD. Use one of these values so the payment step and the Transact Portal handle the trade correctly:

Value Payment method
ACH ACH transfer from the investor's linked bank account
WIRE Wire transfer
CHECK Check
CREDITCARD Credit card
IRA Payment from an IRA custodian
TBD Not decided yet

If the investor changes the payment method, call updateTradeTransactionType while the trade is still CREATED.

2. Confirm the trade

Read the trade back from GET /v3/trades to confirm the trade or to reconcile it later. Filter by tradeId or accountId (see Working with Lists).

curl -X GET "$TAPI_HOST/v3/trades" \
  -G \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  --data-urlencode "filter[tradeId]=100012345"
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "trades": [
    {
      "tradeId": "100012345",
      "accountId": "A12345",
      "offeringId": "12345",
      "partyId": "P12345",
      "transactionType": "ACH",
      "totalShares": "100.000000",
      "totalAmount": "1000.000000",
      "tradeStatus": "CREATED",
      "esignStatus": "NOTSIGNED",
      "archived": "0"
    }
  ],
  "pagination": { "totalRecords": 1, "startIndex": 0, "endIndex": 0 }
}

Use tradeStatus to track the trade through the statuses below, and esignStatus to track its subscription documents.

3. Edit the units (optional)

To change the number of units before the trade settles, call editTrade with accountId, offeringId, tradeId, and the new shares. The trade must be CREATED or FUNDED. The new unit count must fit within the offering's remaining units.

curl -X PUT "$TAPI_HOST/v3/editTrade" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d accountId=A12345 \
  -d offeringId=12345 \
  -d tradeId=100012345 \
  -d shares=150
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "TradeFinancialDetails": {
    "tradeId": "100012345",
    "shares": "150",
    "sharePrice": 1500,
    "totalShares": "10000.000000",
    "remainingShares": "8850.000000",
    "closeId": null
  }
}

sharePrice is the trade's new total value (unit price × shares). totalShares and remainingShares describe the offering, not the trade.

4. Cancel the trade (optional)

If the investor withdraws before paying, call deleteTrade with the accountId and tradeId. The trade must be CREATED. A credit card trade can't be canceled while its card payment is Pending or Submitted. The trade isn't removed: its status changes to CANCELED and it's archived. The errDesc field is optional and records a reason.

curl -X POST "$TAPI_HOST/v3/deleteTrade" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d accountId=A12345 \
  -d tradeId=100012345 \
  -d errDesc="Investor withdrew"
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "tradeDetails": [
    { "partyId": "P12345", "offeringId": "12345", "orderStatus": "CANCELED" }
  ]
}

A trade that has already been funded can't be canceled this way. To return funds to an investor, see Investor Refunds and Returns.

Trade Statuses

A trade's status tracks the investor's money, from commitment through escrow to the issuer. Payment processing has its own statuses, described in Collect Payment.

Status Meaning
CREATED The trade exists and funds haven't reached escrow yet.
FUNDED Funds have been received in escrow.
UNWIND PENDING Funds were received in escrow and a return to the investor is pending.
UNWIND SETTLED Funds were received in escrow and returned to the investor.
SETTLED Funds have been released from escrow to the issuer.
CANCELED The investor withdrew before funds reached escrow. Set by deleteTrade.

Flowchart of trade status transitions from Created through Funded, Settled, Canceled, and Unwind states

Statuses after CREATED change as payments settle and as you or North Capital call updateTradeStatus. Closing trades and marking them SETTLED is covered in Settle and Manage.

Webhooks

These methods send a webhook when they run in this step. See the Trades method reference for each payload.

  • createTrade: a trade is created. The payload carries the tradeId and transactionStatus.
  • editTrade: a trade's unit count is edited.
  • updateTradeTransactionType: a trade's payment method changes.
  • deleteTrade: a CREATED trade is canceled.
  • updateTradeStatus: a trade's status changes, for example to FUNDED or SETTLED.

Common Errors

See Error Codes for the full list.

Code Cause
106 A required field is missing, offeringId or transactionUnits isn't numeric, or the amount falls outside the offering's minimum or maximum. The Error(s) field names the problem.
135 The account doesn't exist, isn't active, or has no active primary party link.
137 The offering has no approved escrow account.
163 The offering doesn't have enough remaining units for the requested amount.
777 The offering is not accepting investments because its escrow account has been closed.
190 deleteTrade or updateTradeTransactionType was called on a trade that isn't CREATED, or editTrade on one that isn't CREATED or FUNDED.

Next

If the offering uses subscription agreements, send them for signature in Subscription Documents. Otherwise, go to Collect Payment.