ACH and Plaid funding
NinjaTrader Connect supports ACH deposits and withdrawals from a checking or savings account linked through Plaid. The flow creates or repairs an ACH application for a NinjaTrader trading account, then uses the approved application for funding.
createPlaidLinkToken, linkPlaidItem, cancelAchApplication, or submitFundTransaction to the Demo base URL.For testing, use a bearer access token for the NinjaTrader staging Live host, which is backed by Plaid Sandbox.
Prerequisites
Your integration needs:
- a bearer access token for the user
- the user’s eligible live trading account
idand exactname - Plaid Link in the user’s client
- a registered
redirectUrifor a browser or iOS OAuth return flow, or a registeredandroidPackageNamefor an Android app-link flow - the USD currency ID resolved for the target environment
Store durable workflow state in your own backend. A page reload, tab close, app restart, or OAuth redirect must not lose the selected mode, target, or reconciliation state.
Complete the funding disclosure
Before an ACH deposit, the user must review and sign the Payment Processor Disclosure and Authorization. Follow Funding disclosures, and confirm that the signature was stored before you enable the deposit action.
The disclosure applies to ACHR deposits. It does not gate ACHS withdrawals. NinjaTrader remains the source of truth and rejects a deposit with AchDisclosureNotAccepted when the disclosure is missing.
Load the accounts and ACH applications
Before you create a Plaid Link token, load both prerequisite lists:
- Call
accountList. Hide accounts whoselegalStatusisIRA. - Call
achApplicationList. Match applications to trading accounts bydormanAccountId.
Keep each eligible account’s numeric id and exact name. You send them later as dormanAccountId and dormanAccountName; a name that doesn’t match the account record causes linkPlaidItem to fail.
An account can have only one active ACH application. An application is active when it isn’t archived and its status is neither Rejected nor RequiresRelink. Don’t start a new link for an account that already has an active application.
Choose the link mode
New-link and relink modes are mutually exclusive:
- New link: select one eligible trading account. Don’t send
achApplicationIdwhen you create the link token. - Relink: select one unarchived application whose status is
RequiresRelink, and send itsidasachApplicationId. The application determines the NinjaTrader trading account. DerivedormanAccountIdfrom the application and use that account’s current exact name fromaccountList; don’t accept or use a separate account selection.
Changing the mode or target invalidates an existing Plaid Link token. Discard the token and create a new one before opening Plaid Link.
Create the Plaid Link token
For a new link, call createPlaidLinkToken with an empty JSON object:
For a relink, include the selected RequiresRelink application’s ID:
The platform fields are optional and mutually exclusive:
- Send
redirectUrifor a browser or iOS OAuth return flow. - Send
androidPackageNamefor an Android app-link flow. - Send neither when the client flow doesn’t use one.
- Never send both.
Register the value in NinjaTrader’s Plaid configuration before using it, and omit blank optional fields. Changing either platform field invalidates an existing token.
Prevent concurrent token requests. While one request is in flight, keep the create action unavailable. If the request times out, clear the in-flight guard and require an explicit manual retry; don’t start a second request automatically.
Inspect errorText even when the response is HTTP 200. Continue only when it is absent, null, or empty and the response contains a non-empty token. Never log, place in a URL, or display the complete token. Keep it only for the life of the link flow, in protected state that can survive an OAuth return when the client needs one.
receivedRedirectUri. This applies only to native mobile apps on iOS and Android. The flow requires durable state for the token. Implement and test the return flow before enabling OAuth institutions.Run Plaid Link
Open Plaid Link with the token. If the user exits, show Plaid’s exit error and metadata, and don’t call NinjaTrader.
After Plaid succeeds, select the first returned account that:
- Has type
depository - Has subtype
checkingorsavings - Doesn’t have a
verification_status
If no returned account matches, stop the flow instead of sending an incomplete request.
Link the Plaid item
Map Plaid’s onSuccess(publicToken, metadata) result into linkPlaidItem:
Use Checking for a Plaid checking subtype and Savings for savings. Use the account mask for accountNumber, or "****" when no mask is returned. Use the Plaid institution ID for routingNumber, or an empty string when none is returned. NinjaTrader replaces these placeholder account and routing values with the bank details it retrieves from Plaid.
Inspect errorText even when the response is HTTP 200. Continue only when it is absent, null, or empty and the response contains a numeric achApplicationId.
After linkPlaidItem succeeds, call achApplicationList once and find the returned ID:
Approvedmeans ACH funding can proceed.UnderReviewis a valid link result, but funding must wait. Use a limited number of later checks with increasing delays; don’t poll indefinitely.- If the read fails or doesn’t contain the returned ID, report the link as submitted with confirmation unavailable. Don’t call
linkPlaidItemagain. Reconcile with a later read or contact NinjaTrader support.
Submit an ACH funding request
Call submitFundTransaction only when the selected account has an unarchived Approved ACH application.
Resolve fundCurrencyId with currencyList. Currency IDs differ by environment. The examples below use the staging USD ID 1; don’t treat that value as an application invariant.
For a deposit, use ACHR and outgoing: false:
For a withdrawal, use ACHS and outgoing: true:
Send a positive amount with no more than two decimal places, except for a full-balance withdrawal. Don’t add fee, bank-account, or description fields.
Withdraw the full balance
Send an ACHS withdrawal with fundAmount: 0 and fullBalance: true:
NinjaTrader determines the amount during processing. The request locks the trading account for immediate liquidation until it is approved or rejected. Open positions, working orders, ACH holds, pending deposits, or another pending full-balance request can cause rejection. Require an explicit confirmation that explains this effect before sending the request.
Guard against duplicates
Keep the deposit or withdrawal action unavailable while a request is in flight. After the request might have reached NinjaTrader, don’t send another one until you reconcile the transaction and account balance.
Handle the funding response
Most business failures arrive in an HTTP 200 response. Always inspect errorText, errorHeader, and errorCode before treating the operation as successful. A successful response must also contain a valid fundTransaction object. Display unknown status and error-code values as returned instead of assuming a fixed enumeration.
- Known business error: correct the reported condition before allowing another request. For example,
AchNoApprovedApplicationsmeans the selected account doesn’t have an approved ACH application. - Network error,
HTTP 5xx, non-JSON body, malformed response, orerrorCode: Unknown: the transaction may have been created. Keep the flow locked against duplicates, and check the transaction and account balance before sending another request. - Valid
fundTransaction: show the returned ID and status.Pending,InTransit, andLockedare processing states, not failures.
Never retry a submitted funding request automatically.
Cancel an ACH application
Call cancelAchApplication with the application’s ID from achApplicationList:
Cancellation archives the application and removes its stored Plaid connection. The API has no operation to undo it, so require an explicit confirmation before sending the request.
Business failures arrive in an HTTP 200 response with ok: false and errorText. Treat the mutation as accepted only when the response is { "ok": true }.
After an accepted cancellation, call achApplicationList once and find the target application:
- Confirm cancellation only when the application has
archived: true. - If the read fails, the application is missing, or it still has
archived: false, report the cancellation as submitted with confirmation unavailable. Don’t submit another cancellation automatically.
To use ACH funding again, start a new link after cancellation is confirmed.
Next steps
- Keep the ACH application and fund-transaction status visible so the user can distinguish a linked bank from a fundable bank.
- Redact bearer tokens, Plaid link tokens, and Plaid public tokens from logs and user-visible errors.
- Reconcile uncertain mutations before permitting another submission.
- If you prefer a NinjaTrader-hosted flow, see Embedding the Funding Page with an iframe.