Create a KYC link
curl --request POST \
--url https://api.sandbox.brickken.com/create-kyc-link \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"email": "investor@example.com",
"needKyc": true,
"walletAddress": "0x1111111111111111111111111111111111111111"
}
'import requests
url = "https://api.sandbox.brickken.com/create-kyc-link"
payload = {
"email": "investor@example.com",
"needKyc": True,
"walletAddress": "0x1111111111111111111111111111111111111111"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
email: 'investor@example.com',
needKyc: true,
walletAddress: '0x1111111111111111111111111111111111111111'
})
};
fetch('https://api.sandbox.brickken.com/create-kyc-link', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.brickken.com/create-kyc-link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'email' => 'investor@example.com',
'needKyc' => true,
'walletAddress' => '0x1111111111111111111111111111111111111111'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.brickken.com/create-kyc-link"
payload := strings.NewReader("{\n \"email\": \"investor@example.com\",\n \"needKyc\": true,\n \"walletAddress\": \"0x1111111111111111111111111111111111111111\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.brickken.com/create-kyc-link")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"investor@example.com\",\n \"needKyc\": true,\n \"walletAddress\": \"0x1111111111111111111111111111111111111111\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.brickken.com/create-kyc-link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"email\": \"investor@example.com\",\n \"needKyc\": true,\n \"walletAddress\": \"0x1111111111111111111111111111111111111111\"\n}"
response = http.request(request)
puts response.read_body{
"email": "jsmith@example.com",
"needKyc": true,
"userCreated": true,
"invitationSent": true,
"tokenSymbol": "<string>",
"walletAddress": "<string>",
"url": "<string>"
}KYC
Create KYC Link
Create or reuse an investor and return a Sumsub verification link.
POST
/
create-kyc-link
Create a KYC link
curl --request POST \
--url https://api.sandbox.brickken.com/create-kyc-link \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"email": "investor@example.com",
"needKyc": true,
"walletAddress": "0x1111111111111111111111111111111111111111"
}
'import requests
url = "https://api.sandbox.brickken.com/create-kyc-link"
payload = {
"email": "investor@example.com",
"needKyc": True,
"walletAddress": "0x1111111111111111111111111111111111111111"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
email: 'investor@example.com',
needKyc: true,
walletAddress: '0x1111111111111111111111111111111111111111'
})
};
fetch('https://api.sandbox.brickken.com/create-kyc-link', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.brickken.com/create-kyc-link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'email' => 'investor@example.com',
'needKyc' => true,
'walletAddress' => '0x1111111111111111111111111111111111111111'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.brickken.com/create-kyc-link"
payload := strings.NewReader("{\n \"email\": \"investor@example.com\",\n \"needKyc\": true,\n \"walletAddress\": \"0x1111111111111111111111111111111111111111\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.brickken.com/create-kyc-link")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"investor@example.com\",\n \"needKyc\": true,\n \"walletAddress\": \"0x1111111111111111111111111111111111111111\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.brickken.com/create-kyc-link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"email\": \"investor@example.com\",\n \"needKyc\": true,\n \"walletAddress\": \"0x1111111111111111111111111111111111111111\"\n}"
response = http.request(request)
puts response.read_body{
"email": "jsmith@example.com",
"needKyc": true,
"userCreated": true,
"invitationSent": true,
"tokenSymbol": "<string>",
"walletAddress": "<string>",
"url": "<string>"
}This endpoint always requires
When
Confirm the result with
x-api-key. The email is normalized before lookup, and needKyc defaults to true.
Testing in Sandbox? Pass
needKyc: false and skip identity verification entirely. The KYC flow
is a Sumsub verification with document upload, not something you need to prove your integration
works, and every test investor you create without it is one less manual step in your loop.Rehearse the real KYC flow once before you go live, since needKyc: false is rejected in
production with needKyc=false is only available in the sandbox environment.This operation can create an investor account and send an invitation email. The returned Sumsub URL grants access to a verification flow; do not log it, commit it, or expose it to another user.
needKyc is false, the investor is created without a KYC requirement and url is null.
Fields
| Field | Required | Notes |
|---|---|---|
email | yes | Normalized to lowercase before lookup |
needKyc | no | Defaults to true. false creates the investor with no KYC requirement, and is accepted in Sandbox only |
walletAddress | no | The investor’s wallet, as a valid EVM address |
tokenSymbol | no | Scopes the investor to a tokenized asset |
Attach the wallet address
An investor record with no wallet address cannot invest. PasswalletAddress here so the record is
complete from the start:
{
"email": "investor@example.com",
"needKyc": false,
"walletAddress": "0x1111111111111111111111111111111111111111"
}
A wallet address is set once. If the investor already has a different address on file, the call is
rejected with
Investor <email> is already associated with a different wallet address rather than
overwriting it. Preparing a whitelist transaction
also attaches the address when the record does not yet have one.GET /get-investor-info, which returns walletAddress and
complianceStatus. A complianceStatus of NOT_REQUIRED together with a non-null walletAddress
is a ready-to-invest test investor.
needKyc is only applied when the investor record is created. For an email that already has an
account, the stored value wins and cannot be downgraded — use a fresh address, such as a + alias.Client examples
walletAddress and tokenSymbol are currently available through the API only; the CLI, MCP and SDK
clients still accept email and needKyc.
- CLI
- MCP
- SDK
brickken kyc create-link \
--email investor@example.com \
--need-kyc true \
--json
{
"name": "create_kyc_link",
"arguments": {
"email": "investor@example.com",
"needKyc": true
}
}
const result = await bkn.kyc.createLink({
email: 'investor@example.com',
needKyc: true,
})
Response
{
"email": "investor@example.com",
"needKyc": true,
"userCreated": true,
"invitationSent": true,
"tokenSymbol": null,
"walletAddress": "0x1111111111111111111111111111111111111111",
"url": "https://in.sumsub.com/..."
}
Authorizations
Body
application/json
Optional. Investor wallet address. It is attached to the investor record when that record does not already have one. A different stored address is rejected rather than replaced.
Pattern:
^0x[a-fA-F0-9]{40}$Optional. Tokenized asset the investor is scoped to.
Response
Investor access resolved and invitation state returned.
Tokenized asset the investor is scoped to, or null.
Investor wallet address on record, or null when none is set.
Sumsub verification URL. Null when KYC is not required. Treat this value as sensitive.