Managing users
All authentication in EVA relates to users in one way ore another. Users are exactly what you would think, nothing exciting. Employees are users, customers are users, we even have special user types for API integrations.
UserType
The distinction between customers or employees is made on the Type property of the user:
This means that customers and employees also fall into the same pool of UserID's.
Use of each type
- Employee - Someone with permissions in EVA, either as a store staff member accessing our Apps or a head office admin using Admin Suite
- Customer - A consumer account which can be used as part of a checkout process
- Anonymous - Only used on API calls when there is no Auth Token given. Not all APIs are available to be called annonymously
- Business - Can be ignored
- System - EVA system processes e.g. Data exporter or Data Lake
- Debtor - Used to instruct relevent payment methods
- Limited Trust - Can be ignored
- Tester - Can be ignored
- Removed by Request - GDPR accounts which were requested for annonymisation
- API - An external system API call identified by its header
If a user is both an employee and a customer, they have UserType 3 (1+2). UserType 3 is the default for newly created employees.
UserAccountType
Aside from a UserType, you can also specify a UserAccountType. This type lets you define the account's login and searchability options, divided into three types:
Standard (0)
- Has a unique login identifier (email/nickname)
- Can login
- Can be found in the
UserSearch
Basic (1)
- No unique identifier
- Cannot login
- Can be found in the
UserSearch
Incognito (2)
- No unique identifier
- Cannot login
- Cannot be found in the
UserSearch
Changing user account types
To change the account type of a user, you can use the service UpdateUserAccountType:
When changing the AccountType from Standard to Incognito or Basic:
- all credentials and roles are removed.
When changing the AccountType from Incognito or Basic to Standard:
- Uniqueness checks are done for the EmailAddress and Nickname;
- Default customer roles are generated;
- When no password is provided, one is generated and returned in the response;
- If configured, the user will receive a welcome to EVA email. If no valid password is provided, the email will also contain a generated password.
Create
There are several ways to create users, but since we're talking about integrations, we're going to assume you'd like to sync users to EVA from an external system. For this, we use either PushUser
or PushUsers_Async
(see our API Reference doc).
The former will be your bread and butter for daily use, while the latter is for importing a large number of users at once - a service aimed at backfill. Since both services make use of the same data model, we will be going through the flow based on PushUser
but circle back with some pointers for PushUsers
later on.
Basics of PushUser
In its most basic form, this request requires only five properties:
{
"UserType": "1",
"EmailAddress": "pete@tortugapirate.com",
"FirstName": "Pete",
"LastName": "Pirate",
"PhoneNumber": "0612345678"
}
When the request is successful, EVA returns the UserID for the newly created User. If the user already exists, EVA simply returns the existing user's ID.
In general, EVA determines whether the user is new by checking the following values:
- BackendID (seeing as that PushUser's often used in synergy with a 3rd party system)
- Email address
- Nickname
DuplicateFiscalID
(optional setting)
Incognito
If a user is of the type Incognito, there will be no EmailAddress check. A unique NickName however is required, as it's used to log in and check the corresponding order; there will be no profile in the account and no password recovery service. This also means you can create as many anonymous accounts as you like with a single email address. Lastly, any changes made to an incognito user's order address, will only be applicable to that specific order.
Addresses
To include Addresses:
{
"UserType": "1",
"EmailAddress": "pete@tortugapirate.com",
"FirstName": "Pete",
"LastName": "Pirate",
"PhoneNumber": "0612345678",
"ShippingAddress": {
"Address1": "Conch Street",
"Address2": "124",
"City": "Bikini Bottom",
"Country": "Pacific Ocean"
}
}
BillingAddress
follows the same method.
Subscriptions
To include Subscriptions:
{
"UserType": "1",
"EmailAddress": "pete@tortugapirate.com",
"FirstName": "Pete",
"LastName": "Pirate",
"PhoneNumber": "0612345678",
"Subscriptions": [
{
"SubscriptionID": "5",
"Subscribed": "true"
}
]
}
CustomFields
To include CustomFields:
{
"UserType": "1",
"EmailAddress": "pete@tortugapirate.com",
"FirstName": "Pete",
"LastName": "Pirate",
"PhoneNumber": "0612345678",
"CustomFields": [
{
"CustomFieldID": "5",
"NumberValue": "10"
}
]
}
Get
To get information on a user, use GetUser. Naturally, the information that's returned depends on what has been set on the User in the first place.
{
"ID": 56,
"BackendID": "54",
"EmailAddress": "michael@sfs.com",
"FirstName": "Michael",
"LastName": "Shipper",
"FullName": "Michael Shipper",
"Type": 2,
"LanguageID": "en",
"CountryID": "NL",
"IsDeleted": false,
"IsIncognito": false,
"IsDebtor": false,
"GravatarHash": "d2c8ea9ff0e75b1f1dae2e087bb10000",
"Data": {},
"CreatedByID": 54,
"CreatedByFullName": "Pedro Pascal",
"CreationTime": "2022-02-16T14:18:34.983Z",
"ModifiedByFullName": "",
"CustomFields": [
{
"CustomFieldID": 66,
"Name": "Loyalty member",
"DisplayName": "Loyalty member",
"DataType": "Bool",
"DataTypeID": 1,
"Options": {
"IsArray": false,
"IsRequired": false
},
"BackendID": "is_loyalty_member",
"IsEditableByUser": true,
"IsArray": false
},
{
"CustomFieldID": 67,
"Name": "Coffee add-ons",
"DisplayName": "Coffee add-ons",
"DataType": "Enum",
"DataTypeID": 4,
"Options": {
"IsArray": true,
"IsRequired": false,
"EnumValues": {
"sugar": "Sugar",
"mil": "Milk",
"soy_milk": "Soy milk"
}
},
"BackendID": "coffee",
"IsEditableByUser": true,
"IsArray": true
},
{
"CustomFieldID": 68,
"Name": "Favorite color",
"DisplayName": "Favorite color",
"DataType": "String",
"DataTypeID": 0,
"Options": {
"IsArray": false,
"IsRequired": false,
"MinimumLength": 2
},
"BackendID": "favo_color",
"IsEditableByUser": true,
"IsArray": false
},
{
"CustomFieldID": 72,
"Name": "Zip Code for Reporting",
"DisplayName": "Zip Code for Reporting",
"DataType": "String",
"DataTypeID": 0,
"Options": {
"IsArray": false,
"IsRequired": false
},
"BackendID": "Zip Code for Reporting",
"IsEditableByUser": true,
"IsArray": false
}
],
"AllowPasswordLogin": true,
"AccountType": 0
}
Update
In order to Update an existing User, you can use UpdateUser. It's possible to update all properties on a User, except for its BackendID, CustomID, UserType and EmailAddress. The request only expects a UserID and the properties you'd like to update.
To update a User's e-mail address, use UpdateUserEmailAddress.
Delete
Deleting Users is a somewhat strange process. Whenever we delete Users, we don't actually delete them. Take a look at the response we got from GetUser
; the User has a property IsDeleted. Whenever we delete a User, this property changes to true and the User will no longer be visible in any of our front ends. The data however, will still be there for the sake of historical accuracy.
To delete a User, use DeleteUser. Example request:
{
"ID": "7"
}
Privacy data removals
Generally, we do not allow for user deletion, in order for us to maintain historical order data. It is possible however, to formally delete user data for GDPR reasons. Such a deletion can only be requested, it will then take a certain amount of time before the user data is actually 'deleted'.
We can schedule a privacy removal request using CreatePrivacyRemovalRequest. Example request:
{
"UserID": "6"
}
{
"ID": 1,
"Hash": "EgVQOvouQ4CId0HSZJFysU6ZVHTolpRo"
}
This service returns the ID for your newly created removal request.
After creating your request, we will kick off the process of replacing all personal information with bogus placeholders in order to maintain order history. This exceeds only the user data model. We're talking about customer interaction history, order history, any place really where your personal information is stored.
This process can only take place if there are no pending invoices for the requested user. If there are, EVA will try again in 24 hours.
To check on your removal progress, use GetPrivacyRemovalRequestByID. Use the ID that was returned to you by CreatePrivacyRemovalRequest
. Example request:
{
"ID": 1
}
{
"ID": 1,
"UserID": 6,
"Status": 2,
"RemovalTime": "2021-11-04T12:52:32.15Z",
"Hash": "EgVQOvouQ4CId0HSZJFysU6ZVHTolpRo"
}
This will return one of the following three statuses:
"Status": 0
= Requested"Status": 1
= Processing"Status": 2
= Done
Automated removals
EVA offers two settings allowing for automated clearing of customer data.
The goal of these settings is to make sure there are no customers present in EVA which are not actively needed to finalize an order.
Details
PrivacyRemovalRequests:TriggerForCompletedOrderAfterXMinutes
By specifying a number of minutes in this setting, EVA removes a created customer from any completed orders and then wipes the customer (after the number of minutes have passed). This is regardless of the presence of any other uncompleted orders with this customer.
PrivacyRemovalRequests:RemoveCustomersAfterXMinutes
By specifying a number of minutes in this setting, EVA finds customers without orders and wipes them (after the number of minutes have passed).
If you try to find such a customer based on its ID, the GetUser
call will return an error of type EntityDeleted. You can still recreate the exact same customer after having been wiped.
PushUsers_Async
The PushUsers_Async
service works with the same data model as its singular version. This means that if any field changes for PushUser
, it also does for PushUsers_Async
.
The purpose of these two services is very different however: PushUsers_Async
is aimed solely at importing large amounts of users into EVA and is not a quick process.
You can add 100 users per service call, and the speed at which those are processed is different each time, since it depends on each environment's current workload.
There are two additional properties which set the service apart.
IgnoreErrors
This property lets you vary between two different ways of pushing your users. It basically comes down to an "all-or-nothing" approach when it comes to valid user entries; it makes for a whole different kind of integration.
- True - this will make the service return an "OK" response regardless as it processes and imports all valid users into EVA
- Invalid entries are initially ignored
- You will have to check with the batch's JobID later on to see if there were any invalid entries and for what Reason (as is the general way of handling EVA's Async services)
You can check the results of each push by means of PushUsers_AsyncResult
, which requires the mentioned JobID.
Result sample
{
"Success": false,
"Metadata": {
"IsAsyncResultAvailable": false
},
"ValidUsers": [
{
"ID": 123,
"Addresses": [
{
"AddressBookID": 123,
"AddressBookBackendID": "string"
}
],
"BackendID": "string"
}
],
"InvalidUsers": [
{
"Reason": "string",
"BackendID": "string"
}
]
}
While the True method is arguably the best way of configuring your integration, it will take a little more time to set up since you have to take into account to check for the invalid entries later on.
- False - this will fail the entire user batch immediately if there is an invalid entry
While easier to setup, it will ultimately take more time since valid user entries are blocked as well.
If you are planning to push millions of users into EVA, it's best to inform your Project Manager or Support about this beforehand so we can take this into account as we monitor each environment's workload.
DisableEventExports
While an added user normally speaking triggers (several) event exports in EVA, we wouldn't want to flood your event exports endpoints when adding a multitude of users.
For that purpose, this service contains the DisableEventExports property, which we recommend you set to true.