Links

Creating natural persons as investors

This guide shows you how to create a basic investor account for a natural person via the API including information about the identity verification process.
In the course of this guide, we will create a simple script that shows the basic interactions with the API. At the end of this guide, you will also find the complete script for you to copy, paste and try out. Remember to insert your account specific information before running the script.

Getting started

First we are going to import the packages that we need and set up some basic variables. The client ID and client secret will be provided to you.
import binascii
import os
import requests
URL = 'https://<your-sandbox-domain-name>/api/external'
CLIENT_ID = '<your client ID>'
CLIENT_SECRET = '<your client secret>'
WALLET_ADDRESS = '<wallet address of the investor>'
Now we write a helper function that follows the OAuth protocol to retrieve an access token that we will use to authenticate the API calls.
def authenticate():
r = requests.post(f'{URL}/oauth/token', data={
'grant_type': 'client_credentials',
'scope': 'investors:write investors:read investments:write investments:read documents:write',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
})
assert r.status_code == 200, r.content
return r.json()['access_token']
We add an additional helper function that with every call creates a random idempotency key. In your application, you would use an idempotency key that correlates to the internal object on your side.
def make_key():
return binascii.hexlify(os.urandom(8)).decode()

Create an investor account

As we now can access the API we use it to create an investor.
if __name__ == '__main__':
headers = {
'Authorization': f'Bearer {authenticate()}',
}
# Note: in normal usage, you would use an idempotency key that correlates
# to the internal object on the customer side.
# create investor
r = requests.post(
f'{URL}/v2/investors/',
json={
"natural_person": {
"salutation": "MR",
"forename": "Peter",
"surname": "Parker",
"birth_date": "2020-08-10",
"birth_place": "New York",
"citizenship": "DEU",
"street": "Hauptstr. 37",
"city": "Frankfurt",
"zip": "60316",
"country": "DEU",
"phone": "+49 123 456 789"
},
"bank_account": {
"account_holder": "Peter Parker",
"iban": 'DE53500105173569146251',
"bic": "GENODEF1ERG",
"bank": "Commerzbank Frankfurt",
"country": "DEU",
"currency": "EUR"
},
"tax_information": {
"tax_identification_number": "12345678",
"non_assessment_certificate": True
},
"is_beneficiary": True,
"pep_status": False,
"account_setup_accepted_at": "2021-05-06T07:14:13.630308+00:00"
},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
investor_id = r.json()['id']

Adding an identification

We also add an identification to the investor. The identification needs a protocol document that we first have to upload.
# add an identification to created investor
# 1. upload the legitimation protocol document to reference it later
r = requests.post(
f'{URL}/v2/documents/',
files={'file': ('protocol.pdf', b'ASD', 'application/pdf')},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
doc_id = r.json()['id']
# 2. create the identification for investor
r = requests.post(
f'{URL}/v2/investors/{investor_id}/identifications/',
json={
"document_type": "IDCARD",
"document_id": "ID123456",
"document_issuer": "Buergeramt Frankfurt",
"document_valid_from": "2020-08-10",
"document_valid_to": "2025-08-10",
"identity_provider": "POSTIDENT",
"legitimation_process_id": "string",
"legitimation_protocol_id": doc_id,
"verified_at": "2020-08-10T14:06:22.134Z"
},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
identification_id = r.json()['id']

Create wallet for investor

We can now create a wallet for that investor by providing the address of the wallet.
# create a wallet for investor ...
r = requests.post(
f'{URL}/v2/investors/{investor_id}/wallets/eth-generic/',
json={"address": "{WALLET_ADDRESS}"},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
wallet_id = r.json()['id']

Retrieve information

We can now use the investors endpoint to retrieve information about the investor.
# Retrieve information about the investor
r = requests.get(
f'{URL}/v2/investors/{investor_id}/',
headers={**headers}
)
assert r.status_code < 300, r.content
print(r.json())

Full script

import binascii
import os
import requests
URL = 'https://<your-sandbox-domain-name>/api/external'
CLIENT_ID = '<your client ID>'
CLIENT_SECRET = '<your client secret>'
WALLET_ADDRESS = '<wallet address of the investor>'
def authenticate():
r = requests.post(f'{URL}/oauth/token', data={
'grant_type': 'client_credentials',
'scope': 'investors:write investors:read investments:write investments:read documents:write',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
})
assert r.status_code == 200, r.content
return r.json()['access_token']
def make_key():
return binascii.hexlify(os.urandom(8)).decode()
if __name__ == '__main__':
headers = {
'Authorization': f'Bearer {authenticate()}',
}
# Note: in normal usage, you would use an idempotency key that correlates
# to the internal object on the customer side.
# create investor
r = requests.post(
f'{URL}/v2/investors/',
json={
"natural_person": {
"salutation": "MR",
"forename": "Peter",
"surname": "Parker",
"birth_date": "2020-08-10",
"birth_place": "New York",
"citizenship": "DEU",
"street": "Hauptstr. 37",
"city": "Frankfurt",
"zip": "60316",
"country": "DEU",
"phone": "+49 123 456 789"
},
"bank_account": {
"account_holder": "Peter Parker",
"iban": 'DE53500105173569146251',
"bic": "GENODEF1ERG",
"bank": "Commerzbank Frankfurt",
"country": "DEU",
"currency": "EUR"
},
"tax_information": {
"tax_identification_number": "12345678",
"non_assessment_certificate": True
},
"is_beneficiary": True,
"pep_status": False,
"account_setup_accepted_at": "2021-05-06T07:14:13.630308+00:00"
},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
investor_id = r.json()['id']
# add an identification to created investor
# 1. upload the legitimation protocol document to reference it later
r = requests.post(
f'{URL}/v2/documents/',
files={'file': ('protocol.pdf', b'ASD', 'application/pdf')},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
doc_id = r.json()['id']
# 2. create the identification for investor
r = requests.post(
f'{URL}/v2/investors/{investor_id}/identifications/',
json={
"document_type": "IDCARD",
"document_id": "ID123456",
"document_issuer": "Buergeramt Frankfurt",
"document_valid_from": "2020-08-10",
"document_valid_to": "2025-08-10",
"identity_provider": "POSTIDENT",
"legitimation_process_id": "string",
"legitimation_protocol_id": doc_id,
"verified_at": "2020-08-10T14:06:22.134Z"
},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
identification_id = r.json()['id']
# create a wallet for investor ...
r = requests.post(
f'{URL}/v2/investors/{investor_id}/wallets/eth-generic/',
json={"address": "{WALLET_ADDRESS}"},
headers={**headers, 'X-Idempotency-Key': make_key()}
)
assert r.status_code < 300, r.content
wallet_id = r.json()['id']
# Retrieve information about the investor
r = requests.get(
f'{URL}/v2/investors/{investor_id}/',
headers={**headers}
)
assert r.status_code < 300, r.content
print(r.json())