Webhooks¶
TransactAPI can notify your system when an API method completes. For each method you register, TransactAPI sends an HTTPS POST to your URL with details of the record that changed, so you do not have to poll for status changes. To set up webhooks, follow Register Webhooks; this page is the reference for how they behave and what they send.
How Webhooks Work¶
- Registrations are per API method. You register a webhook for a method name, such as
createTradeorupdateTradeStatus, and one or more URLs. When that method completes successfully for your client, each registered URL receives aPOST. - Webhooks fire after the API response. The request that triggered the webhook has already returned
statusCode101, and all of its data changes are complete, before the webhook is sent. A webhook never changes data. - Every successful call fires. Webhooks are not deduplicated. Repeating a call, for example resending
updatePartyafter a timeout, sends the webhook again. Resource-stylePATCHendpoints do not send webhooks. - Register the method name you call. A webhook matches the name of the endpoint that was called. Where a method has an older alias, such as
requestCustodialAccountforcreateCustodyAccountRequest, register the name your integration calls. - Most portal actions fire webhooks too. Most changes made in the Transact Portal go through the same API methods and send the same webhooks.
Request Format¶
Each delivery is an HTTP POST with these properties:
| Property | Value |
|---|---|
Content-Type | application/x-www-form-urlencoded |
| Body | The method's payload fields, form-encoded. See the Method Reference. |
User-Agent | NorthCapital-TAPI/1.0 |
X-NC-Token | Your webhook identification tokens, if you have generated any. See Identifying Webhook Traffic. |
Encoding rules:
- Fields whose value is null are omitted from the body. Treat a missing field as null. Empty strings are sent as an empty value, for example
field1=. - Boolean values are sent as
1and0.
For example, a createParty webhook body looks like this:
If you have set a webhook encryption key, the body is a single field named params that holds the encrypted payload. See Setting Up Encrypted Webhooks.
Delivery¶
- Timeout. TransactAPI waits up to 2 seconds to connect and 5 seconds in total for your endpoint to respond.
- Single attempt. Each webhook is delivered once. It is not retried if your endpoint times out or returns an error.
- Response. Return any
2xxstatus. The response body is not read. Respond quickly and do any slow processing after you respond. - TLS. Your endpoint's certificate is verified on every delivery, so it must be valid and issued by a trusted certificate authority.
Because deliveries are not retried, use webhooks as a prompt to act rather than as the only record of a change. Because every successful call sends a webhook, make your handler idempotent. To reconcile, read the current state with the resource endpoints, for example GET /v3/parties or GET /v3/trades. See Endpoint Styles.
Identifying Webhook Traffic¶
Webhooks include headers your infrastructure can use to identify it, for example to allow the traffic through a firewall or WAF instead of subjecting it to bot-prevention rules:
| Header | Value |
|---|---|
User-Agent | NorthCapital-TAPI/1.0, on every webhook. |
X-NC-Token | Your active webhook identification tokens, comma-separated. Sent only after you have generated at least one token. |
To generate a token:
- In the Transact Portal, open the Webhook page.
- In the Webhook Identification Tokens section, select Generate Token.
- Copy the token into your firewall or WAF rule. The value shown on the page is exactly what arrives in the
X-NC-Tokenheader.
Tokens are shared across your organization: webhooks for every client ID under your parent client carry the same tokens.
To rotate a token without downtime:
- Generate a new token. Both tokens are now sent on every webhook, comma-separated, so match the header with a contains rule rather than exact equality.
- Update your firewall rule to the new token.
- Retire the old token from the same page.
A token grants no access to TransactAPI, but treat it as a secret: your endpoint can require it and reject requests without it. Do not expose it in client-side code or in logs you share.
Webhooks sent directly by the ATS, updateOrder and the ATS delivery of matchedTradenotify, do not currently include these headers. See Secondary Trading.
A token is a fixed value and is not derived from the request body, so it does not show whether a payload was modified. Signed payloads are not currently supported; contact your North Capital representative if your integration requires them. If you need the payload itself encrypted at the application layer, see Setting Up Encrypted Webhooks.
Method Reference¶
The tables below list each method you can register, when it fires, and the fields it sends. Fields marked * are sent only when they have a value. Values of developerAPIKey are masked.
Accounts¶
| Method | Sent when | Fields |
|---|---|---|
createAccount | An account is created. | accountId, providerid, status, developerAPIKey, accountName, type, entityType, residentType, socialSecurityNumber (always empty), dateOfBirth (always empty), address1, address2, city, state, zip, country, email, phone, taxID, kycStatus, amlStatus, amlDate, suitabilityScore, suitabilityDate, suitabilityApprover, accreditedStatus, accreditedInvestor, accreditedInvestorDate, 506cLimit, accountTotalLimit, singleInvestmentLimit, associatedAC, syndicate, tags, notes, approvalStatus, approvalPrincipal, approvalLastReview, virtualStatus, field1, field2, field3, createdIpAddress, client_id |
updateAccount | An account is updated. | accountId and the account's fields as stored after the update (the createAccount fields except providerid, status, developerAPIKey, createdIpAddress, and client_id), plus socialSecurityNumber, dateOfBirth, and updatedIpAddress |
getAccount | getAccount is called. | accountId, accountName, type, entityType, residentType, address1, address2, city, state, zip, country, email, phone, taxID, kycStatus, kycDate, amlStatus, amlDate, suitabilityScore, suitabilityDate, suitabilityApprover, accreditedStatus, accreditedInvestor, accreditedInvestorDate, 506cLimit, accountTotalLimit, singleInvestmentLimit, associatedAC, syndicate, tags, notes, approvalStatus, approvalPrincipal, approvalLastReview, archived_status, field1, field2, field3, createdDate, updatedDate |
getAccountLinkId | getAccountLinkId is called for an account that has links. | The getAccount fields, with fivenotsixcLimit in place of 506cLimit, plus linkIds |
updateAccountArchivestatus | An account is archived or unarchived. | accountId, archiveStatus |
uploadAccountDocument | Documents are uploaded to an account. Sent once per request. | accountId |
Parties and Entities¶
| Method | Sent when | Fields |
|---|---|---|
createParty | An individual party is created. | partyId, KYCstatus, AMLstatus |
updateParty | An individual party is updated. | partyId, KYCstatus, AMLstatus |
updateEntity | An entity party is updated. | partyId, KYCstatus, AMLstatus |
updatePartyEntityArchivestatus | A party or entity is archived or unarchived. | partyId, archiveStatus |
uploadPartyDocument | Documents are uploaded to a party. Sent once per request. | partyId |
createEntitySupp | Supplemental entity details are created. | entityID, poliCont, poliContDate, CFTC, CFTCrole, boName, boSSN, planassetLimit, insassetLimit, notes, TaxYEmonth, USPerson, BPpurchaser, BPemployers, BPaffiliates, BPsponsor, BankHoldingCo, InvCompanyAct, InvCompanyAct_individualowners, InvCompanyAct_entityowners, CFIUS, PurchaserRep, OtherOccupations, createdDate, createdIpAddress |
updateEntitySupp | Supplemental entity details are updated. | The createEntitySupp fields, with updatedDate in place of createdIpAddress |
Links¶
| Method | Sent when | Fields |
|---|---|---|
createLink | A link is created. | id, firstEntryType, firstEntry, relatedEntry, relatedEntryType, linkType, notes |
deleteLink | A link is deleted. | The createLink fields for the deleted link |
KYC/AML and Accreditation¶
| Method | Sent when | Fields |
|---|---|---|
performKycAml | An enhanced KYC/AML check completes. | partyId, kycstatus, amlstatus |
performKycAmlBasic | A basic KYC/AML check completes. | partyId, kycstatus, amlstatus |
performAml | An AML check completes. | The request fields (except credentials), plus apiMethodName, tblFields, devPerms, amlStatus, amlList, amlScore, expected_id, idologyResponse |
updateKycAml | KYC/AML questions are answered and the answers pass. | partyId, kycStatus |
updateKycAmlRequest | North Capital sets a party's KYC/AML status to "Needs More Info" during manual review. | Not listed |
updateKycAmlStatus | A KYC/AML status is changed with Update KYC/AML Status in the Transact Portal. | Not listed |
requestAiVerification | Accredited investor verification is requested. | accountId, aiRequestStatus, airequestId, notes, accreditedStatus |
updateAiVerification | The accreditation verification status changes. | accountId, aiRequestStatus, airequestId, notes, accreditedStatus |
updateAiRequest | The investor adds information to a verification request. | accountId, aiRequestStatus, airequestId, accreditedStatus |
uploadVerificationDocument | A document is uploaded for accreditation verification. | accountId |
Offerings¶
| Method | Sent when | Fields |
|---|---|---|
updateOffering | An offering is updated. | issuerId, offeringId, issueName, issueType, targetAmount, minAmount, maxAmount, unitPrice, totalShares, remainingShares, startDate, endDate, offeringStatus, offeringText, stampingText, escrowAccountNumber, field1, field2, field3, createdDate, createdIPAddress |
closeOffering | An offering is closed. | offeringId, offeringStatus (CLOSED) |
cancelOffering | An offering is canceled. | offeringId, offeringStatus (CANCELED) |
reopenOffering | An offering is reopened. | offeringId, offeringStatus (REOPENED) |
deleteOffering | An offering is deleted. | offeringId, offeringStatus (DELETED) |
updateEligibleToCloseStatus | An offering's escrow status changes to Eligible to Close. | Not listed |
Trades¶
| Method | Sent when | Fields |
|---|---|---|
createTrade | A trade is created. | tradeId, transactionId, transactionAmount, transactionDate, transactionStatus, RRApprovalStatus, RRName, RRApprovalDate, PrincipalApprovalStatus, PrincipalName, PrincipalDate, closeId*, eligibleToClose |
updateTrade | A trade is updated. | tradeId, accountId, offeringId, orderStatus, RRApprovalStatus, RRName, RRApprovalDate, PrincipalApprovalStatus, PrincipalName, PrincipalDate, field1, field2, field3, closeId* |
updateTradeStatus | A trade's status changes. Not sent when the new status equals the current one. | tradeId, id, offeringId, accountId, partyId, party_type, escrowId, transactionType, totalAmount, totalShares, orderStatus, createdDate, createdIpAddress, errors, documentKey, esignStatus, users, field1, field2, field3, RRApprovalStatus, RRName, RRApprovalDate, PrincipalApprovalStatus, PrincipalName, PrincipalDate, archived_status, closeId*, eligibleToClose |
editTrade | A trade's share count is edited. | tradeId, shares, sharePrice (the trade's total value: shares × unit price), totalShares, remainingShares, closeId* |
editTradeUnits | A trade's unit count or unit price is edited. | tradeId, sharePrice (the trade's total value), unitPrice, totalShares |
updateTradeTransactionType | A trade's payment method (such as ACH, Wire, or Check) changes. | tradeId, transactionType |
updateTradeArchivestatus | A trade is archived or unarchived. | tradeId, partyId, offeringId, orderStatus, archiveStatus |
deleteTrade | A trade in CREATED status is canceled. | tradeId |
cancelInvestment | An investment is canceled. The methods it runs internally, such as updateTradeStatus and deleteTrade, send their own webhooks. | accountId, OrderId, Transaction Type, OrderStatus. The Transaction Type key contains a space and arrives form-encoded as Transaction+Type. |
uploadTradeDocument | Documents are uploaded to a trade. Sent once per request. | tradeId |
updateTradeDocArchivestatus | A trade document is archived or unarchived. | tradeId, documentid, documentTitle, documentFileName, documentFileReferenceCode, virtualStatus, createdDate, archiveStatus |
updateDocuSignStatus | A subscription document's DocuSign status changes, to any status. | tradeId, id, documentId, templateId, esignstatus (CREATED, SIGNED, NOTSIGNED, DECLINED, or VOIDED), updatedDate, updatedIpAddress |
updateNdaDocuSignStatus | An NDA is signed through DocuSign. | refNum, maasuserId, accountId, partyId, offeringId, eSignedStatus (SIGNED) |
ACH and External Accounts¶
| Method | Sent when | Fields |
|---|---|---|
createExternalAccount | An external bank account is added. | accountId or issuerId, ExtAccountfullname, Extnickname, ExtRoutingnumber, ExtAccountnumber, types, accountType. Routing and account numbers are Base64-encoded. |
updateExternalAccount | An external bank account is updated. | The createExternalAccount fields |
deleteExternalAccount | An external bank account is deleted. | accountId and Ext_status, or issuerId and status |
linkExternalAccount | An investor finishes linking a bank account through Plaid, after linkExternalAccount. | id, accountId, refNum, institutionId, institution_name, account_number (encrypted), account_name, account_subtype, account_mask, account_id, account_plaidId, routing_number (encrypted), wire_routing (encrypted), account_type, externalAccount, createdDate, createdIpAddress, updatedDate, updatedIpAddress |
updateLinkExternalAccount | An investor finishes replacing a Plaid-linked bank account, after updateLinkExternalAccount. | The linkExternalAccount fields |
externalFundMove | An ACH transfer from an investor's external account is initiated. | tradeId, RefNum |
updateExternalFundMoveStatus | An ACH transfer's status changes through updateExternalFundMoveStatus, for example from Pending to Submitted. It is not sent when a transfer is voided. | accountId, tradeId, transactionstatus, fundStatus, RefNum, errors |
updateExternalFundMoveApprovedStatus | An ACH transfer's approval status changes. | accountId, tradeId, transactionstatus, fundStatus, RefNum, errors |
requestForVoidACH | A pending ACH transfer is voided. | accountId, tradeId, transactionstatus, fundStatus (Voided), RefNum, errors |
Voids send their own webhook
Voiding a pending ACH transfer sets fundStatus to Voided through requestForVoidACH, which sends the requestForVoidACH webhook. No updateExternalFundMoveStatus webhook is sent for that transition. Subscribe to both methods for full coverage of a transfer's status changes.
Credit Card¶
| Method | Sent when | Fields |
|---|---|---|
ccFundMove | A credit card payment is submitted with ccFundMove. | accountId, tradeId, offeringId, totalAmount, ccreferencenumber, fundStatus, transactionstatus |
ccFundMovement | A credit card payment is submitted with ccFundMovement. | The ccFundMove fields |
stripePaymentProcess | A Stripe payment is processed. It also sends updateCCFundMoveStatus. | accountId, tradeId, transactionstatus, fundStatus, RefNum, errors |
updateCCFundMoveStatus | A credit card transaction's status changes through updateCCFundMoveStatus. It is not sent when a transaction is voided. | accountId, tradeId, transactionstatus, fundStatus, RefNum, errors, vantivTransactionMessage |
updateCCFundMoveApprovedStatus | A credit card transaction's approval status changes. | accountId, tradeId, transactionstatus, fundStatus, RefNum, errors |
requestForVoidCCTransaction | A pending credit card transaction is voided. | accountId, tradeId, transactionstatus, fundStatus (Voided), RefNum, errors |
Voids send their own webhook
Voiding a pending credit card transaction sets fundStatus to Voided through requestForVoidCCTransaction, which sends the requestForVoidCCTransaction webhook. No updateCCFundMoveStatus webhook is sent for that transition. Subscribe to both methods for full coverage of a transaction's status changes.
Custody¶
| Method | Sent when | Fields |
|---|---|---|
createCustodyAccountRequest | A custodial account is requested. Calls to the older requestCustodialAccount match a registration under that name. | accountId, custAccStatus, accountStatus, custAccRequestID, createdDate, approvalStatus |
updateCustodyAccountRequest | A custodial account request is updated or approved. Each update is sent to registrations under all four names: updateCustodyAccountRequest, updateCustodialAccountRequest, approveCustodyAccountRequest, and approveCustodialAccountRequest. Register only one of them to avoid duplicate deliveries. | accountId, custAccStatus, accountStatus, custAccRequestID, createdDate |
createCustodyFundMove | A deposit into a custody account is initiated. Calls to the older fundCustodyAccount match a registration under that name. | accountId, referenceNumber, status |
updateCustodyFundMove | A custody fund move is updated. | accountId, referenceNumber, status |
updateCustodyFundMoveStatus | A custody fund move's status changes. | accountId, transactionstatus, fundStatus, RefNum, errors |
updateCustodyFundDisbursement | A custody disbursement's status changes. | requestId, accountId, amount, type, bankId, bankAccountId, additionalDetails, status, createdDate, updatedDate |
Users¶
| Method | Sent when | Fields |
|---|---|---|
createUser | A user is created. | userid, emailAddress, firstname, lastname |
createMaaSUser | A Marketplace-as-a-Service user is created. | userId, emailAddress, firstname, lastname, field1, createdIpAddress |
updateMaaSUser | A Marketplace-as-a-Service user is updated. | The user record, excluding password, field2, and field3 |
Secondary Trading (PPEX/ATS)¶
| Method | Sent when | Fields |
|---|---|---|
matchedTradenotify | Orders are matched on the ATS. | matchId, bidOrderId, askOrderId, numberOfShares, Price, executionTime. Deliveries sent directly by the ATS also include bidOrderStatus, askOrderStatus, and clientID, and can use an alternate format, statusCode=200&body=<JSON array>. |
updateOrder | An ATS order is updated. | Not listed |
notifySettlement | A trade's settlement status is reported with notifySettlement. | tradeID, tradeStatus, memberid, issuerid |
Fields are not listed for some methods; contact North Capital support for their payloads.
Webhooks sent directly by the ATS (updateOrder, and the ATS delivery of matchedTradenotify) do not include the identifying headers, and their timeouts differ from those under Delivery.