This guide shows you how to create an investor account for a legal 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.
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.
As we now can access the API we use it to create an investor. Note that we first need to upload the documents needed for the legal person. Besides the company data and personal data of a person inauthority, the investor also needs a valid identification to be able to invest. If you've already identified the user, you can upload the data here. Depending on your setup, the investor might need to go through an identification process again. See Investors -> Identification for more details.
if__name__=='__main__': headers ={'Authorization':f'Bearer {authenticate()}',}# Upload documents to verify the investor's identity r = requests.post(f'{URL}/v2/documents/', files={'file': ('commercial-register.pdf', b'ASD', 'application/pdf')}, headers={**headers, 'X-Idempotency-Key': make_key()} )assert r.status_code <300, r.content identity_proof_doc_id = r.json()['id'] r = requests.post(f'{URL}/v2/documents/', files={'file': ('shareholder-list.pdf', b'ASD', 'application/pdf')}, headers={**headers, 'X-Idempotency-Key': make_key()} )assert r.status_code <300, r.content structure_proof_doc_id = r.json()['id']# Create investor using the uploaded files r = requests.post(f'{URL}/v2/investors/', json={'natural_person': {'salutation': 'MR','forename': 'Peter','surname': 'Parker','birth_date': '2000-08-10','birth_place': 'New York','citizenship': 'DEU','street': 'Hauptstr. 37','city': 'Frankfurt','zip': '60316','country': 'DEU','phone': '+49 123 456 789','occupation': 'Apprentice','educational_qualification': 'Secondary school diploma','is_pep': False },'legal_person': {'company_name': 'Test GmbH','street': 'Teststr. 80','city': 'Test','zip': '111111','country': 'DEU','commercial_register_number': 'HRB 12344','commercial_register': 'Amtsgericht München','company_identity_proof_id': identity_proof_doc_id,'company_structure_proof_id': structure_proof_doc_id },'bank_account': {'account_holder': 'Peter Parker','iban': 'DE53500105173569146251','bic': 'GENODEF1ERG','bank': 'Commerzbank Frankfurt','country': 'DEU','currency': 'EUR' },'is_beneficiary': True,'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']# 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']# Create the identification for the investor using the uploaded file r = requests.post(f'{URL}/v2/investors/{investor_id}/identifications/', json={'document_type': 'PASSPORT','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
Add benefitting persons
For the legal person to successfully finish the KYC/AML process, you need to provide information about the benefitting persons of the investor via the API.
We can now use the investors endpoint to retrieve information about the investor.
# Retrieve information about the investorr = requests.get(f'{URL}/v2/investors/{investor_id}/', headers={**headers})assert r.status_code <300, r.contentprint(f'Successfully created investor with ID {investor_id}.')
Full script
import binasciiimport osimport requestsURL ='https://demo.cashlink.de/api/external'CLIENT_ID ='<your client ID>'CLIENT_SECRET ='<your client secret>'defauthenticate(): r = requests.post(f'{URL}/oauth/token', data={'grant_type': 'client_credentials','scope': 'investors:read investors:write investments:write investments:read documents:write','client_id': CLIENT_ID,'client_secret': CLIENT_SECRET })assert r.status_code ==200, r.contentreturn r.json()['access_token']defmake_key():return binascii.hexlify(os.urandom(8)).decode()if__name__=='__main__': headers ={'Authorization':f'Bearer {authenticate()}',}# Upload documents to verify the investor's identity r = requests.post(f'{URL}/v2/documents/', files={'file': ('commercial-register.pdf', b'ASD', 'application/pdf')}, headers={**headers, 'X-Idempotency-Key': make_key()} )assert r.status_code <300, r.content identity_proof_doc_id = r.json()['id'] r = requests.post(f'{URL}/v2/documents/', files={'file': ('shareholder-list.pdf', b'ASD', 'application/pdf')}, headers={**headers, 'X-Idempotency-Key': make_key()} )assert r.status_code <300, r.content structure_proof_doc_id = r.json()['id']# Create investor using the uploaded files 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','occupation': 'Apprentice','educational_qualification': 'Secondary school diploma','is_pep': False },'legal_person': {'company_name': 'Test GmbH','street': 'Teststr. 80','city': 'Test','zip': '111111','country': 'DEU','commercial_register_number': 'HRB 12344','commercial_register': 'Amtsgericht München','company_identity_proof_id': identity_proof_doc_id,'company_structure_proof_id': structure_proof_doc_id },'bank_account': {'account_holder': 'Peter Parker','iban': 'DE53500105173569146251','bic': 'GENODEF1ERG','bank': 'Commerzbank Frankfurt','country': 'DEU','currency': 'EUR' },'is_beneficiary': True,'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']# 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']# Create the identification for the investor using the uploaded file r = requests.post(f'{URL}/v2/investors/{investor_id}/identifications/', json={'document_type': 'PASSPORT','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# Add benefiting persons to the investor r = requests.post(f'{URL}/v2/investors/{investor_id}/benefiting-persons/', json= [ {'salutation': 'MR','forename': 'Petra','surname': 'Parker','citizenship': 'AFG','birth_date': '2000-11-02','birth_place': 'Frankfurt','street': 'Teststr. 10','city': 'Frankfurt','zip': '60316','country': 'DEU','phone': '+49 123 456 789','occupation': 'Apprentice','educational_qualification': 'Secondary school diploma','is_pep': False } ], headers={**headers, 'X-Idempotency-Key': make_key()} )assert r.status_code <300, r.content# Retrieve information about the investor r = requests.get(f'{URL}/v2/investors/{investor_id}/', headers={**headers} )assert r.status_code <300, r.contentprint(f'Successfully created investor with ID {investor_id}.')