Skip to content

KYC/AML Verification

A KYC/AML check verifies an investor's identity (Know Your Customer) and screens their name against global watch lists (Anti-Money Laundering). TransactAPI runs the automated check in real time against the details stored on the party, and writes the result to the party's kycStatus and amlStatus. When the automated check does not pass, or when the investor is an entity that needs a Know Your Business review, you can request a manual review by North Capital.

Before You Start

Billing

In production, each call to performKycAmlBasic, performKycAml, performAml, and requestKycAml is billed as a separate check, including a repeat call for the same party. Sandbox calls are not billed. If a call times out or the connection drops, read the stored result back with getKycAmlResponse or GET /v3/parties/{id} before you retry. See the Fee Schedule.

Basic or enhanced

Basic (performKycAmlBasic) Enhanced (performKycAml)
Result Pass or fail Pass or fail
Challenge questions No Yes, answered with updateKycAml
getKycAmlResponse type Basic Enhanced

Flowchart: after Create Party, choose Basic or Enhanced KYC/AML. Enhanced adds an Update KYC/AML step for the challenge questions. If the party auto-passes, the flow is complete. If not, the investor uploads a government-issued photo ID, North Capital reviews it, and the party status is updated.

Steps

1. Run the check

Call performKycAmlBasic for a basic check, or performKycAml for an enhanced check. Both take only the party ID.

curl -X POST "$TAPI_HOST/v3/performKycAmlBasic" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d partyId=P12345
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "kyc": {
    "response": {
      "id-number": "1234567890",
      "summary-result": { "key": "id.success", "message": "PASS" },
      "results": { "key": "result.match", "message": "ID Located" }
    },
    "kycstatus": "Auto Approved",
    "amlstatus": "Auto Approved"
  }
}

Keep kyc.kycstatus and kyc.amlstatus. Each check overwrites the party's kycStatus and amlStatus with its result:

  • kycstatus is Auto Approved when the provider's summary result is PASS, and Disapproved otherwise.
  • amlstatus is Disapproved when the provider reports a watch-list restriction or an error, and Auto Approved otherwise.

For an enhanced check, also keep kyc.response.id-number and the questions in kyc.response.questions.question. Each question has a prompt, a type, and a list of answer choices.

{
  "statusCode": "101",
  "statusDesc": "Ok",
  "kyc": {
    "response": {
      "id-number": "1234567890",
      "summary-result": { "key": "id.success", "message": "PASS" },
      "questions": {
        "question": [
          {
            "prompt": "In which city is ANY STREET?",
            "type": "city.of.residence",
            "answer": ["ALMO", "ATLANTA", "MINOT", "None of the above"]
          }
        ]
      }
    },
    "kycstatus": "Auto Approved",
    "amlstatus": "Auto Approved"
  }
}

2. Submit the challenge answers (enhanced only)

Show the questions to the investor, then send the answers with updateKycAml. Pass the id-number as idNumber, the number of questions as noOfqns, and for each question n its type as type{n} and the chosen answer as qns{n}.

curl -X PUT "$TAPI_HOST/v3/updateKycAml" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d partyId=P12345 \
  -d idNumber=1234567890 \
  -d noOfqns=5 \
  -d "type1=city.of.residence -d qns1=ATLANTA" \
  -d "type2=previous.address -d qns2="4344 BACKTRAIL DR"" \
  -d "type3=person.not.known -d qns3="SUSAN BROWN"" \
  -d "type4=property.size -d qns4="1,501 - 2,000"" \
  -d "type5=prior.residence.state.multiyear -d qns5="NEW YORK""
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "Financial investor details": {
    "partyId": "P12345",
    "kycStatus": "Auto Approved"
  }
}

When the answers pass, kycStatus is Auto Approved. When they fail, the call returns HTTP 200 with statusCode 145, the provider's message in statusDesc, and the party's kycStatus is set to Disapproved. If the provider returns an error instead of a pass or fail, the call returns HTTP 404 with statusCode 145 and the party's kycStatus is left unchanged. Check statusCode, not only the HTTP status.

3. Screen an entity (entities only)

For an entity party, call performAml to screen the entity name against watch lists. This check is required on entities when North Capital is the escrow agent for your offering.

curl -X POST "$TAPI_HOST/v3/performAml" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d partyId=E12345
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "partyDetails": {
    "response": {
      "id-number": "1234567890",
      "restriction": { "key": "global.watch.list.no.match", "message": "Patriot Act - No Match" }
    },
    "amlStatus": "Auto Approved"
  }
}

Keep partyDetails.amlStatus.

4. Read the stored result

Call getKycAmlResponse to read the most recent stored result of a check without running it again. Set type to Basic (performKycAmlBasic), Enhanced (performKycAml), or AML Only (performAml). Use this before retrying a check.

curl -X POST "$TAPI_HOST/v3/getKycAmlResponse" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d partyId=P12345 \
  -d type=Basic
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "createdAt": "2026-01-15 09:21:47",
  "kycamlDetails": {
    "statusCode": "101",
    "statusDesc": "Ok",
    "kyc": {
      "response": {
        "id-number": "1234567890",
        "summary-result": { "key": "id.success", "message": "PASS" }
      },
      "kycstatus": "Auto Approved",
      "amlstatus": "Auto Approved"
    }
  }
}

kycamlDetails holds the stored response of the check and createdAt shows when it ran. The results of updateKycAml are not stored here; read the party's current status with GET /v3/parties/{id} or getKycAml.

5. Request a manual review (if needed)

If the automated check does not pass, or an entity needs a Know Your Business review, call requestKycAml. investorId takes a party ID (P…), entity ID (E…), or account ID (A…). A party can have only one manual request.

For entities, the review looks through the organization documents to the beneficial owners (see FinCEN guidance). Upload all entity documents with uploadEntityDocument before requesting the review. For individuals, upload a government-issued photo ID with uploadPartyDocument.

curl -X POST "$TAPI_HOST/v3/requestKycAml" \
  -H "Authorization: Bearer $TAPI_CLIENT_ID:$TAPI_API_KEY" \
  -d investorId=P12345
{
  "statusCode": "101",
  "statusDesc": "Ok",
  "requestDetails": [
    { "investorId": "P12345", "requestId": "123456789" }
  ]
}

Keep requestId. North Capital reviews the request and sets the status to Manually Approved, Disapproved, or Needs More Info. When more information is needed, upload the documents and call updateKycAmlStatus with status New Info Added so the review continues.

Flowchart: onboard the entity, then request KYC/AML. North Capital reviews within one to two business days. If approved, North Capital sets the status to Manually Approved and the flow is complete. If not, North Capital sets the status to Need More Info and adds account notes; the needed information is uploaded and the review repeats. Webhooks notify you of each status update.

Webhooks

These methods send webhooks. See KYC/AML and Accreditation for the payload of each.

  • performKycAmlBasic and performKycAml fire when the check completes, with partyId, kycstatus, and amlstatus.
  • performAml fires when the entity screening completes.
  • updateKycAml fires only when the answers pass, with partyId and kycStatus. A failed or errored answer submission sends no webhook, so check the response.
  • updateKycAmlRequest fires when North Capital sets a party to Needs More Info during a manual review, and updateKycAmlStatus fires when a status is changed in the Transact Portal.

requestKycAml itself sends no webhook; the review outcome arrives through the status webhooks above.

Common Errors

See Error Codes for the full list.

Code When
106 partyId is missing, or getKycAmlResponse has a missing or invalid type.
198 The party does not exist or is not active. requestKycAml also returns 198 with Request already in progress or Already requested when a manual request exists.
145 updateKycAml answers failed (HTTP 200) or the provider returned an error (HTTP 404).
404 getKycAmlResponse found no stored result of that type for the party.
110 The API key lacks permission for the method or a required field.

Next

If the offering requires it, continue to Suitability or Accredited Investor Verification. Otherwise continue to Create the Trade.