Account Creation & KYC
Why it's important
Account creation and KYC (Know Your Customer) processes are essential for verifying customer identities and ensuring regulatory compliance before service activation. This process helps financial institutions comply with anti-money laundering (AML) and counter-terrorism financing (CTF) regulations.
When to use
Use this flow when onboarding new customers. EMDs (Electronic Money Distributors) typically handle their own KYC validation and then use these APIs to open accounts for approved customers.
Testing Endpoints
You can test these endpoints directly in our API Sandbox.
Complete Onboarding Flow
Here's the end-to-end process for account creation:
- List available user profiles to determine the appropriate onboarding path
- Retrieve KYC document requirements (if applicable for your setup)
- Create a new user account
- Upload KYC documents (if required for your compliance setup)
- Open the user account (change status to OPEN)
- Create financial products for the approved user
Step 1: List Available Profiles
Before starting the onboarding process, retrieve available user profiles to determine the appropriate path.
Endpoint
https://sandbox.revsto.com/api/distributor/v1/users/profilesprofile_view- cURL
- Python
- JavaScript
curl -X GET "https://sandbox.revsto.com/api/distributor/v1/users/profiles" \
-H "Authorization: Bearer your_api_token"
import requests
url = "https://sandbox.revsto.com/api/distributor/v1/users/profiles"
headers = {"Authorization": "Bearer your_api_token"}
response = requests.get(url, headers=headers)
print(response.json())
fetch("https://sandbox.revsto.com/api/distributor/v1/users/profiles", {
headers: {"Authorization": "Bearer your_api_token"}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));
Sample Response
{
"items": [
{
"id": "306",
"role": "Company",
"name": "REVSTO TEST Unregulated_B2B_1",
"description": ""
},
{
"id": "307",
"role": "Company",
"name": "REVSTO TEST Regulated_B2B_C2B_1",
"description": ""
},
{
"id": "308",
"role": "Company",
"name": "REVSTO TEST Regulated_B2B_C2B_2",
"description": ""
},
{
"id": "309",
"role": "Company",
"name": "REVSTO TEST_Regulated_B2B_1",
"description": ""
},
{
"id": "151",
"role": "DelegateUser",
"name": "REVSTO Users",
"description": "",
"owner": {
"id": "1016",
"role": "DISTRIBUTOR"
}
}
],
"count": 5,
"limit": 20,
"offset": 0,
"sort": "+id"
}
Step 2: Retrieve KYC Documents (Optional)
This step only applies to distributors who provide KYC documents to Revsto. If you only have legal entities as clients, this step may not be applicable.
Endpoint
https://sandbox.revsto.com/api/distributor/v1/kyc/documentskyc_view- cURL
- Python
- JavaScript
curl -X GET "https://sandbox.revsto.com/api/distributor/v1/kyc/documents" \
-H "Accept: application/json" \
-H "Authorization: Bearer your_access_token"
import requests
url = "https://sandbox.revsto.com/api/distributor/v1/kyc/documents"
headers = {"Authorization": "Bearer your_api_token"}
response = requests.get(url, headers=headers)
print(response.json())
fetch("https://sandbox.revsto.com/api/distributor/v1/kyc/documents", {
headers: {"Authorization": "Bearer your_api_token"}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));
Sample Response
{
"items": [
{
"id": null,
"type": "PROOF_OF_IDENTITY",
"label": "Proof of identity",
"minimumRequiredStatus": "UNKNOWN",
"required": false
},
{
"id": null,
"type": "PROOF_OF_RESIDENCE",
"label": "Proof of residence",
"minimumRequiredStatus": "UNKNOWN",
"required": false
}
],
"count": 2
}
Step 3: Create a New User
Create a new user account. This creates the identity but the account will need to be opened in a subsequent step.
For Natural Persons
Endpoint
https://sandbox.revsto.com/api/distributor/v1/usersuser_creationCode Examples
- cURL
- Python
- JavaScript
curl -X POST "https://sandbox.revsto.com/api/distributor/v1/users" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_token" \
-d '{
"legalType":"NATURAL_PERSON",
"profileId":"341",
"firstName":"Jo",
"lastName":"Christoforidou",
"birthDate":"1996-07-16",
"externalId":"string",
"email":"j.christoforidou1@revsto.com",
"contactPhone":"35722376006",
"address":
{
"line1":"62 Athalassas Avenue",
"line2":"Office 102",
"zipcode":"2023",
"city":"Nicosia",
"province":"Strovolos",
"country":"CY"
},
"specialAttributes":{
"residence_country":"CY"
}
}'
import requests
import json
def create_natural_person():
url = "https://sandbox.revsto.com/api/distributor/v1/users"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer your_api_token"
}
data = {
"legalType":"NATURAL_PERSON",
"profileId":"341",
"firstName":"Jo",
"lastName":"Christoforidou",
"birthDate":"1996-07-16",
"externalId":"string",
"email":"j.christoforidou1@revsto.com",
"contactPhone":"35722376006",
"address":
{
"line1":"62 Athalassas Avenue",
"line2":"Office 102",
"zipcode":"2023",
"city":"Nicosia",
"province":"Strovolos",
"country":"CY"
},
"specialAttributes":{
"residence_country":"CY"
}
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
return response.json()
else:
print(f"Error: {response.status_code}")
print(response.text)
return None
if __name__ == "__main__":
result = create_natural_person()
if result:
print(json.dumps(result, indent=2))
const axios = require('axios');
const createNaturalPerson = async () => {
const response = await axios.post(
'https://sandbox.revsto.com/api/distributor/v1/users',
{
"legalType":"NATURAL_PERSON",
"profileId":"341",
"firstName":"Jo",
"lastName":"Christoforidou",
"birthDate":"1996-07-16",
"externalId":"string",
"email":"j.christoforidou1@revsto.com",
"contactPhone":"35722376006",
"address":
{
"line1":"62 Athalassas Avenue",
"line2":"Office 102",
"zipcode":"2023",
"city":"Nicosia",
"province":"Strovolos",
"country":"CY"
},
"specialAttributes":{
"residence_country":"CY"
}
}
);
return response.data;
};
createNaturalPerson()
.then(data => console.log(JSON.stringify(data, null, 2)))
.catch(error => console.error('Error:', error.response?.data || error.message));
Request Body
{
"profileId": 341,
"legalType": "NATURAL_PERSON",
"role": "CLIENT",
"externalId": "string",
"contactPhone": "35722376006",
"lang": "en_GB",
"email": "j.christoforidou1@revsto.com",
"age": 28,
"specialAttributes": {
"residence_country": "196"
},
"address": {
"line1": "62 Athalassas Avenue",
"line2": "Office 102",
"zipcode": "2023",
"city": "Nicosia",
"province": "Strovolos",
"country": "CY"
},
"lastName": "Christoforidou",
"firstName": "Jo",
"birthDate": "1996-01-01",
"gender": "NONE"
}
Sample Response
{
"id": 3822,
"role": "CLIENT",
"profileId": 341,
"createdAt": "2025-06-23T11:27:29+03:00",
"legalType": "NATURAL_PERSON",
"status": "PENDING",
"externalId": "string",
"contactPhone": "35722376006",
"lang": "en_GB",
"email": "j.christoforidou1@revsto.com",
"age": 28,
"specialAttributes": {
"residence_country": "196"
},
"address": {
"line1": "62 Athalassas Avenue",
"line2": "Office 102",
"zipcode": "2023",
"city": "Nicosia",
"province": "Strovolos",
"country": "CY"
},
"lastName": "Christoforidou",
"firstName": "Jo",
"birthDate": "1996-01-01",
"gender": "NONE"
}
For Legal Entities
Endpoint
https://sandbox.revsto.com/api/distributor/v1/usersuser_creationCode Examples
- cURL
- Python
- JavaScript
curl -X POST "https://sandbox.revsto.com/api/distributor/v1/users" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_token" \
-d '{
"login": "JC@2456",
"legalType": "LEGAL_ENTITY",
"profileId": "306",
"email": "j.christoforidou@revsto.com",
"address": {
"line1": "88 rue du dôme",
"line2": "Apt 3",
"zipcode": "92100",
"province": "Île-de-France",
"city": "Boulogne-Billancourt",
"country": "FR"
},
"brandName": "My 100 testing",
"legalForm": "Inc",
"legalName": "My Test Business",
"registrationDate": "2019-08-24",
"registrationPlace": "Paris",
"registrationNumber": "RCS123546",
"registrationCountry": "FR",
"specialAttributes": {
"UBO_Name": "Joanna",
"UBO_LastName": "Christoforidou",
"residence_country": "CY"
},
"boardMember": {
"legalType": "NATURAL_PERSON",
"profileId": "280",
"externalId": "EXT123456789",
"email": "j.christoforidou@revsto.com",
"address": {
"line1": "62 Athalassas Avenue",
"line2": "Office 102",
"zipcode": "2023",
"province": "Strovolos",
"city": "Nicosia",
"country": "CY"
},
"idNumber": "AZE123456789",
"nationality": "French",
"otherNationality": "German",
"contactPhone": 35722376006,
"gender": "FEMALE",
"personTitle": "MS",
"firstName": "Joanna",
"lastName": "Christoforidou",
"birthDate": "2019-08-24",
"birthCountry": "CY",
"birthPlace": "Nicosia",
"jobTitle": "Account manager"
}
}'
import requests
import json
def create_legal_entity():
url = "https://sandbox.revsto.com/api/distributor/v1/users"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer your_api_token"
}
data = {
"login": "JC@2456",
"legalType": "LEGAL_ENTITY",
"profileId": "306",
"email": "j.christoforidou@revsto.com",
"address": {
"line1": "88 rue du dôme",
"line2": "Apt 3",
"zipcode": "92100",
"province": "Île-de-France",
"city": "Boulogne-Billancourt",
"country": "FR"
},
"brandName": "My 100 testing",
"legalForm": "Inc",
"legalName": "My Test Business",
"registrationDate": "2019-08-24",
"registrationPlace": "Paris",
"registrationNumber": "RCS123546",
"registrationCountry": "FR",
"specialAttributes": {
"UBO_Name": "Joanna",
"UBO_LastName": "Christoforidou",
"residence_country": "CY"
},
"boardMember": {
"legalType": "NATURAL_PERSON",
"profileId": "280",
"externalId": "EXT123456789",
"email": "j.christoforidou@revsto.com",
"address": {
"line1": "62 Athalassas Avenue",
"line2": "Office 102",
"zipcode": "2023",
"province": "Strovolos",
"city": "Nicosia",
"country": "CY"
},
"idNumber": "AZE123456789",
"nationality": "French",
"otherNationality": "German",
"contactPhone": 35722376006,
"gender": "FEMALE",
"personTitle": "MS",
"firstName": "Joanna",
"lastName": "Christoforidou",
"birthDate": "2019-08-24",
"birthCountry": "CY",
"birthPlace": "Nicosia",
"jobTitle": "Account manager"
}
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
return response.json()
else:
print(f"Error: {response.status_code}")
print(response.text)
return None
if __name__ == "__main__":
result = create_legal_entity()
if result:
print(json.dumps(result, indent=2))
const axios = require('axios');
const createLegalEntity = async () => {
const response = await axios.post(
'https://sandbox.revsto.com/api/distributor/v1/users',
{
login: 'JC@2456',
legalType: 'LEGAL_ENTITY',
profileId: '306',
email: 'j.christoforidou@revsto.com',
address: {
line1: '88 rue du dôme',
line2: 'Apt 3',
zipcode: '92100',
province: 'Île-de-France',
city: 'Boulogne-Billancourt',
country: 'FR'
},
brandName: 'My 100 testing',
legalForm: 'Inc',
legalName: 'My Test Business',
registrationDate: '2019-08-24',
registrationPlace: 'Paris',
registrationNumber: 'RCS123546',
registrationCountry: 'FR',
specialAttributes: {
UBO_Name: 'Joanna',
UBO_LastName: 'Christoforidou',
residence_country: 'CY'
},
boardMember: {
legalType: 'NATURAL_PERSON',
profileId: '280',
externalId: 'EXT123456789',
email: 'j.christoforidou@revsto.com',
address: {
line1: '62 Athalassas Avenue',
line2: 'Office 102',
zipcode: '2023',
province: 'Strovolos',
city: 'Nicosia',
country: 'CY'
},
idNumber: 'AZE123456789',
nationality: 'French',
otherNationality: 'German',
contactPhone: 35722376006,
gender: 'FEMALE',
personTitle: 'MS',
firstName: 'Joanna',
lastName: 'Christoforidou',
birthDate: '2019-08-24',
birthCountry: 'CY',
birthPlace: 'Nicosia',
jobTitle: 'Account manager'
}
},
{
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your_api_token'
}
}
);
return response.data;
};
createLegalEntity()
.then(data => console.log(JSON.stringify(data, null, 2)))
.catch(error => console.error('Error:', error.response?.data || error.message));
Request Body
{
"profileId": 306,
"legalType": "LEGAL_ENTITY",
"role": "COMPANY",
"address": {
"line1": "62 Athalassas Avenue",
"zipcode": "2023",
"city": "Nicosia",
"country": "CY"
},
"lang": "en_US",
"specialAttributes": {
"UBO_Name": "J",
"UBO_LastName": "C"
},
"login": "June",
"legalName": "JUNE"
}
Sample Response
{
"id": 3781,
"role": "COMPANY",
"profileId": 306,
"createdAt": "2025-06-06T10:00:49+03:00",
"legalType": "LEGAL_ENTITY",
"status": "PENDING",
"address": {
"line1": "62 Athalassas Avenue",
"zipcode": "2023",
"city": "Nicosia",
"country": "CY"
},
"lang": "en_US",
"specialAttributes": {
"UBO_Name": "J",
"UBO_LastName": "C"
},
"login": "June",
"legalName": "JUNE"
}
Step 4: Upload KYC Documents (If Required)
Upload the required KYC documents for verification. This step is only applicable when the user is in PENDING status and you need to provide documents to Revsto.
Endpoint
https://sandbox.revsto.com/api/distributor/v1/users/{userId}/documentsdocument_managementCode Examples
- cURL
- Python
- JavaScript
curl -X POST "https://sandbox.revsto.com/api/distributor/v1/users/{userId}/documents" \
-H "Authorization: Bearer your_api_token" \
-H "Content-Type: multipart/form-data" \
-F "documentType=passport" \
-F "file=@/path/to/passport.jpg"
import requests
userId = "user123" # Replace with your actual user ID
url = f"https://sandbox.revsto.com/api/distributor/v1/users/{userId}/documents"
files = {"file": open("/path/to/passport.jpg", "rb")}
data = {"documentType": "passport"}
headers = {"Authorization": "Bearer your_api_token"}
response = requests.post(url, files=files, data=data, headers=headers)
print(response.json())
const userId = "user123"; // Replace with your actual user ID
// Using FormData for multipart/form-data
const formData = new FormData();
formData.append("documentType", "passport");
formData.append("file", fileInput.files[0]); // Assuming fileInput is a DOM element
fetch(`https://sandbox.revsto.com/api/distributor/v1/users/${userId}/documents`, {
method: "POST",
headers: {
"Authorization": "Bearer your_api_token"
},
body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));
Request Body
This endpoint uses multipart/form-data encoding. The request should include:
documentType: The type of document (e.g., "passport", "national_id", "driver_license", "residence_permit", "utility_bill", "bank_statement", "tax_return", "company_registration", "PORTRAIT")file: The binary data of the document file
Sample Response
{
"id": "795",
"ownerId": 3544,
"type": "PROOF_OF_IDENTITY",
"status": "NEW",
"directory": "UNSORTED",
"description": "test document for USER 3544",
"uploadDate": "2025-04-24T10:02:11+03:00",
"metadata": {
"type": "PROOF_OF_IDENTITY"
},
"links": [
{
"rel": "preview",
"href": "https://sandbox.revsto.com/api/distributor/v1/documents/795/preview"
},
{
"rel": "content",
"href": "https://sandbox.revsto.com/api/distributor/v1/documents/795/content"
}
]
}
Step 5: Open User Account
Once the user is created and any required KYC documents are uploaded, you can open the account by changing the status to OPEN.
Endpoint
https://sandbox.revsto.com/api/distributor/v1/identities/{identityId}/actions/openopen_identityCode Examples
- cURL
- Python
- JavaScript
# Expected response: 204 No Content (no response body)
curl -X POST "https://sandbox.revsto.com/api/distributor/v1/identities/{identityId}/actions/open" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_token" \
-d '{
"reason": "client approved"
}'
import requests
identityId = "identity123" # Replace with your actual identity ID
url = f"https://sandbox.revsto.com/api/distributor/v1/identities/{identityId}/actions/open"
payload = {
"reason": "client approved"
}
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer your_api_token"
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 204:
print("User account opened successfully")
else:
print(f"Error: {response.status_code}")
const identityId = "identity123"; // Replace with your actual identity ID
fetch(`https://sandbox.revsto.com/api/distributor/v1/identities/${identityId}/actions/open`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer your_api_token"
},
body: JSON.stringify({
"reason": "client approved"
})
})
.then(response => {
if (response.status === 204) {
console.log("User account opened successfully");
} else {
throw new Error(`Error: ${response.status}`);
}
})
Request Body
{
"reason": "client approved"
}
Response
This endpoint returns 204 No Content on success.
Step 6: Create Product Accounts
After the user account is opened, you can create financial product accounts.
Endpoint
https://sandbox.revsto.com/api/distributor/v1/users/{userId}/accountsaccount_creationCode Examples
curl -X POST "https://sandbox.revsto.com/api/distributor/v1/users/{userId}/accounts" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_token" \
-d '{"productId": 235}'
Request Body
{
"productId": 235
}
Sample Response
{
"id": "10000097583",
"externalId": null,
"userId": 3633,
"productId": 235,
"status": "OPENED",
"label": "REVSTO_TESTING EUR #10000097583",
"balance": {
"value": 0,
"currency": "EUR"
},
"availableBalance": {
"value": 0,
"currency": "EUR"
},
"createdAt": "2025-05-08T14:45:37+03:00",
"lastUsedAt": "2025-05-08T14:45:37+03:00"
}
You can create product accounts when the client is in PENDING state or after the user is in OPEN status.
Webhook Notifications
You will receive relevant webhooks during the account creation process:
User Creation Webhook
{
"id": "14940",
"webhookId": "0196aa75-6d9d-71ca-b4b6-e86be8d4d148",
"type": "transaction",
"event": "transaction.new",
"data": {
"transactionLogId": "14940",
"transactionType": "USER_CREATION"
}
}
Account Opening Webhook
{
"id": "15013",
"webhookId": "0196afb7-268e-730e-917f-c690256e7784",
"type": "transaction",
"event": "transaction.new",
"data": {
"transactionLogId": "15013",
"transactionType": "OPEN_ACCOUNT"
}
}
Supported Document Types
| Document Type | Description | Usage |
|---|---|---|
PROOF_OF_IDENTITY | Identity documents (passport, ID) | Required for identity verification |
PROOF_OF_RESIDENCE | Utility bills, bank statements | Required for address verification |
KYC_CERTIFICATE | KYC certification documents | Optional additional verification |
PORTRAIT | Portrait/selfie documents | Required for facial verification |
Best Practices
-
Character Support: Only Latin characters are supported for account creation.
-
Implement Webhook Notifications: Subscribe to relevant events to get real-time updates instead of polling. See Events & Webhooks.
-
Handle Different Legal Types: Ensure your implementation can handle both natural persons and legal entities with their different data requirements.
-
Store Reference IDs: Always store the
identityIdanduserIdvalues for future reference and account management. -
Document Quality: When uploading documents, ensure they are clear, legible, and meet the requirements to reduce rejection rates.
EMDs typically handle their own customer KYC validation. The KYC review mentioned in this documentation refers to Revsto's internal compliance checks, not customer-facing KYC requirements.
See the Customer Accounts section for details on managing the created accounts.