Custody Accounts¶
A custody account lets North Capital Private Securities hold an investor's assets. Opening a custody account is a separate process from the integration path, needed only if your platform opens custody accounts for investors. You record the investor's acceptance of the custody agreement, submit a custody account request for an existing account, and track the request until North Capital approves or rejects it.
Before You Start¶
- The investor has an account with its owner linked. See Onboard Investors.
- Webhooks are registered for
createCustodyAccountRequestandupdateCustodyAccountRequest. See Register Webhooks. - Your API key has the
custody_account.readscope if you will read custody accounts withGET /v3/custody/accounts/{id}.
Steps¶
1. Record the custody agreement attestation¶
Record that the account holder has reviewed and accepted the custody agreement. The attestation is required before the custody account request in the next step. accountId, isAttested (must be true), and documentUrl are required. documentUrl must be a valid URL that returns HTTP 200 directly, without a redirect.
curl -X POST "$TAPI_HOST/v3/createCustodyAgreementAttestation" \
-H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
-d accountId=A12345 \
-d isAttested=true \
-d documentUrl=https://example.com/custody-agreement.pdf
{
"statusCode": "101",
"statusDesc": "Ok",
"attestation": {
"accountId": "A12345",
"isAttested": "1",
"documentUrl": "https://example.com/custody-agreement.pdf",
"createdDate": "2026-01-15 10:30:00"
}
}
isAttested of 1 confirms the attestation is on file. See POST /v3/createCustodyAgreementAttestation.
To collect a formal eSignature as well, createCustodyAgreementEsign sends the custody agreement through DocuSign to the account's primary party. It supplements the attestation and does not replace it.
2. Submit the custody account request¶
Submit the account for review. accountId is the only request field. An account can have one custody account request.
curl -X POST "$TAPI_HOST/v3/createCustodyAccountRequest" \
-H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
-d accountId=A12345
{
"statusCode": "101",
"statusDesc": "Ok",
"custodialAccountDetails": [
{
"accountId": "A12345",
"custAccStatus": "Pending",
"accountStatus": "Pending",
"custAccRequestID": "abc1234",
"createdDate": "2026-01-15 10:31:00",
"approvalStatus": "Pending"
}
]
}
Keep custAccRequestID; you need it to update the request. New requests start with custAccStatus Pending. See POST /v3/createCustodyAccountRequest.
3. Track the request¶
North Capital reviews the request and updates its status, which sends the updateCustodyAccountRequest webhook. Account openings are processed daily at 8:00 AM MT, with statuses updated by 10:00 AM MT. To check the status at any time, read the custody account.
curl -X GET "$TAPI_HOST/v3/custody/accounts/A12345" \
-H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY"
{
"statusCode": "101",
"statusDesc": "Ok",
"custody_account": {
"accountId": "A12345",
"requestId": "abc1234",
"status": "Approved",
"restrictedStatus": "No",
"restrictedReason": null,
"approvalDate": "2026-01-16 09:15:00",
"notes": "",
"createdDate": "2026-01-15 10:31:00",
"updatedDate": "2026-01-16 09:15:00"
}
}
status is the request status:
| Status | Meaning |
|---|---|
Pending | The request is waiting for review. |
Need More Info | North Capital needs more information before it can decide. See step 4. |
New Info Added | You have supplied the requested information and the request is waiting for another review. |
Approved | The custody account is open. |
Rejected | The request was denied. |
See GET /v3/custody/accounts/{id}.
4. Respond to a request for more information¶
If the status is Need More Info, supply the missing information, then set the request to New Info Added to send it back for review. custAccRequestID and custAccRequestStatus are required; custAccRequestStatus must be New Info Added or Pending.
curl -X POST "$TAPI_HOST/v3/updateCustodyAccountRequest" \
-H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
-d custAccRequestID=abc1234 \
-d "custAccRequestStatus=New Info Added" \
-d "notes=Updated address supplied"
{
"statusCode": "101",
"statusDesc": "Ok",
"custodialAccountDetails": [
{
"accountId": "A12345",
"custAccStatus": "New Info Added",
"accountStatus": "Pending",
"custAccRequestID": "abc1234",
"createdDate": "2026-01-15 10:31:00"
}
]
}
custAccStatus confirms the new status. See POST /v3/updateCustodyAccountRequest.
Webhooks¶
createCustodyAccountRequestfires when the request is submitted, withaccountId,custAccRequestID,custAccStatus, andaccountStatus.updateCustodyAccountRequestfires whenever the request's status changes, whether you update it or North Capital approves, rejects, or asks for more information.
Register the current method names. The older names requestCustodialAccount, updateCustodialAccountRequest, approveCustodyAccountRequest, and approveCustodialAccountRequest still work, but every status change is delivered to registrations under all four update names, so registering more than one of them sends duplicate deliveries. See Custody in the Webhooks method reference.
Common Errors¶
| Code | When it happens here |
|---|---|
1422 | The attestation was not recorded before createCustodyAccountRequest (HTTP 422, account must attest to custody agreement), or documentUrl is not a valid, reachable URL, or isAttested is not true. |
227 | A custody account request already exists for this account. |
148 | The accountId does not exist or is not active. |
228 | The custAccRequestID sent to updateCustodyAccountRequest does not exist. |
106 | A required parameter is missing, or custAccRequestStatus is not an allowed value. |
See Error Codes for the full list.
Next¶
Return to the Developer Guide.