How to use transformations to format data during CSV upload
When mapping CSV columns to Veza attributes, you can apply transformations to format, combine, or convert data during import. This enables data standardization without requiring modifications to source CSV files.
Transformations are useful for:
Combining columns into a single attribute (e.g., display name from first and surname)
Reformatting dates or times to match expected formats
Standardizing case (uppercase, lowercase, title case)
Padding numbers to fixed widths, trimming whitespace or removing characters
To apply a transformation, enter a formatter expression in the Value field when mapping a CSV column.
Formatter expressions use curly braces to reference column names. The pipe character (|) can chain transformation functions.
To combine first_name and last_name columns into a full name:
To generate an email address from the username column:
To ensure an employee ID is always 8 characters with leading zeros:
The following transformation functions are available for CSV imports:
For function documentation including parameters and syntax, see the . While reference examples use Lifecycle Management terminology, syntax is the same for CSV transformations.
: CSV integration guide
: All transformation functions
Padding
LEFT_PAD, RIGHT_PAD, ZERO_PAD
Date/Time
DATE_FORMAT, DATE_ADJUST, DATE_ADJUST_DAY, ASSUME_TIME_ZONE, UTC_TO_TIME_ZONE
Encoding
ASCII, REMOVE_DIACRITICS
Standardization
PHONE_NUMBER_E164, LANGUAGE_RFC5646, COUNTRY_CODE_ISO3166, REMOVE_DOMAIN
Case
LOWER, UPPER, LOWER_SNAKE_CASE, UPPER_SNAKE_CASE, LOWER_CAMEL_CASE, UPPER_CAMEL_CASE
Trimming & Removal
TRIM, TRIM_CHARS, TRIM_CHARS_LEFT, TRIM_CHARS_RIGHT, REMOVE_CHARS, REMOVE_WHITESPACE, REPLACE_ALL
Substring
Column name format: When referencing CSV columns in transformers, use all lowercase with underscores replacing spaces. For example, a column named "User Name" becomes {user_name} in the transformer.

FIRST_N, LAST_N, SUB_STRING, SPLIT
{first_name} {last_name}{username}@example.com{employee_id | ZERO_PAD, 8}Automating updating CSV integration data
In addition to using a simple web interface to update CSV data manually, you can automate a process to push new data using the Veza REST API and refresh the Veza graph. This document includes example utilities using Python and CLI tools.
After creating a CSV upload integration, you can use the REST API operation Push Custom Provider Datasource CSV to upload new CSV data.
Whenever a CSV is submitted, it is processed based on the current configuration of the CSV Upload Integration provider, including any column mapping settings.Authentication: To make API calls, you must include an authorization token in the header of each request. This can be:
A Personal API Key for a Veza administrator
A Team API Key, for a team assigned to manage CSV Upload integrations
See for more details on creating API keys.
Note: The CSV data must be complete for each upload. Veza will remove entities from the Graph for any entities that were present in the previous upload, but not in the current upload.
Using the REST API requires the Integration (Provider) and Data Source IDs. You can retrieve these in Veza on the Integration Details > Data Source tab:
On the Veza Integrations page, click the CSV integration to view details
On the Data Source tab, click the data source name to view details
Copy the values from the Properties table:
The unique data source "Id"
Uploading the CSV data is made with a post call to the /api/v1/providers/custom/{provider_id}/datasources/{data_source_id}:push_csv endpoint.
Note: The CSV contents must be base64-encoded into the JSON body of the request. Raw CSV values are rejected. You can automatically convert the data as part of your implementation, as shown below.
The "Provider Id"
Both values are in UUID format, e.g., 19b0c736-6686-4708-87e2-92171db6afb3.
{
"csv_data": "abc123="
}CSV_PAYLOAD=$(cat my_app_data.csv | base64)
curl --location https://example.vezacloud.com/api/v1/providers/custom/40bdd318-d320-4574-be90-ca556d59889a/datasources/9bc29dc6-8cd0-4926-992e-7d720305ae2f:push_csv \
--request POST \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $VEZA_API_KEY" \
--data "{\"csv_data\": \"${CSV_PAYLOAD}\"}"#!/usr/bin/env python3
import base64
import json
import os
import sys
import oaaclient.utils as oaautils
from oaaclient.client import OAAClient, OAAClientError
veza_url = "https://example.vezacloud.com"
veza_api_key = os.getenv("VEZA_API_KEY")
provider_id = "UUID of Provider"
data_source_id = "UUID of Data Source"
source_csv = "path/to/my_file.csv"
print("Connecting to Veza")
try:
veza_con = OAAClient(veza_url, veza_api_key)
except OAAClientError as e:
print("Error connecting to Veza tenant")
print(e)
sys.exit(1)
print("Loading CSV file")
with open(source_csv, "rb") as f:
encoded_csv = base64.b64encode(f.read())
print("Pushing data to Veza")
try:
push_request = {"id": provider_id, "data_source_id": data_source_id, "csv_data": encoded_csv.decode()}
veza_con.api_post(f"/api/v1/providers/custom/{provider_id}/datasources/{data_source_id}:push_csv", push_request)
print("Push succeeded")
except OAAClientError as e:
log.error(f"{e.error}: {e.message} ({e.status_code})")
if hasattr(e, "details"):
for d in e.details:
log.error(d)
sys.exit(3)
Configure email, Slack, and Microsoft Teams notifications for CSV upload status and refreshed query results
The CSV Upload integration supports notifications to inform subscribers about the status of file uploads and how queries affected by the upload re-evaluate once processing completes.
Notifications are opt-in and configured on the Notifications tab when creating or editing a CSV integration.
Two distinct categories of notification are available:
Upload and extraction status — progress and outcome of receiving and processing an uploaded file.
Query Results Refreshed — a summary of how the risk-scored queries affected by the upload were re-evaluated, and whether their results are reflected in the latest risk scores.
You can configure notifications for the following Veza Action integrations:
Email: No additional configuration required.
Slack App: Requires the to be configured.
Microsoft Teams App: Requires the to be configured.
Subject and body are identical across email, Slack, and Microsoft Teams; only channel-specific formatting differs.
Integration Owners: Notify the users assigned as , not only its creator. Owners can be users or groups; only owners that resolve to a user with an email address are notified. A group listed as an owner is not expanded to its members, so group owners do not receive these notifications.
Additional Recipients: One or more email addresses, separated by commas.
A notification is only sent when at least one delivery option, one trigger, and one recipient are selected.
These notifications report progress as Veza receives and processes an uploaded file.
Veza polls upload status for up to 24 hours after the file is received to detect extraction events.
These messages are not customizable. Veza sends a fixed subject and body for each trigger, substituting the uploaded file name. For failures, the underlying error message is appended to the body.
Example messages for an uploaded file named employees.csv:
Enable this notification with the Query Results Refreshed checkbox in the integration's notification preferences.
After a CSV upload finishes processing, Veza re-evaluates the queries that depend on the uploaded data and refreshes their results, including any risk scores. The Query Results Refreshed notification summarizes the refresh for the latest risk-score cycle.
Query evaluation and risk-score evaluation run on separate, environment-configurable schedules (typically hourly and daily). The notification is sent once, after the first risk-score evaluation following the upload. If that evaluation does not run before Veza's timeout, the notification is sent anyway, with a subject noting that risk scores were not updated.
Only the queries that the upload could actually change are summarized. A query is included when all of the following are true:
It has an assigned . Queries without a risk level are not refreshed.
It is enabled. Disabled and hidden queries are excluded.
Queries that the upload cannot affect are skipped.
The notification groups the included queries into three lists, based on whether each query finished in time to be reflected in the latest risk-score cycle:
The message shows a count of successful queries (for example, "12 of 14"), a combined count of failed or incomplete queries, and the query names in each group. The successful-query list is truncated after 15 entries, ending with a trailing - ....
The subject reflects the combined outcome and names the uploaded file:
The body opens with the outcome line, then a short note, the counts, and the queries in each group:
Notifications can be configured via REST API by setting the notification_preferences field on the custom provider when or updating an integration.
Example notification_preferences block:
subscribed_events: FILE_RECEIVED, EXTRACTION_IN_PROGRESS, EXTRACTION_COMPLETED, EXTRACTION_FAILED, FILE_RECEIVE_FAILED, FAILURE (subscribes to all failure events), or QUERY_RESULTS_REFRESHED.
— create and configure a CSV integration.
— set up Slack and Microsoft Teams delivery.
delivery_methods type: EMAIL (no id required), SLACK_APP (id is the configured Slack app ID), or TEAMS_APP (id is the configured Teams app ID).File Received
File received and queued for processing.
File Extraction in Progress
Data transformation has started.
File Successfully Uploaded
File Received
File Received
We have received the CSV file "employees.csv" and are processing it.
File Extraction in Progress
File Extraction In Progress
Succeeded
The query re-evaluated successfully, and its result is reflected in the latest risk scores.
Failed
The query failed to evaluate, so its result is not reflected in the latest risk scores. Try running it manually; if it still cannot run, contact Veza Support.
Incomplete
Queries refreshed and risk scores updated
Queries refreshed and risk scores updated for "employees.csv".
Risk scores updated, but some queries did not succeed
Risk scores updated, but not all queries succeeded for "employees.csv".
Queries refreshed, but the risk-score update did not run
Queries refreshed and risk scores updated for "employees.csv".
Note: Only queries with assigned risk levels are refreshed. Queries that did
not complete successfully were not factored into the latest risk score update.
Queries succeeded: 12 of 14.
Queries failed or incomplete: 2.
Succeeded queries
- Privileged group membership
- Dormant service accounts
- ...
Failed queries
- Inactive admin accounts
* For failed queries, please rerun them manually. If a query still cannot
rerun, please contact Veza Support.
Incomplete queries
- Cross-account role assumptions
* For incomplete queries, please contact Veza Support.{
"notification_preferences": {
"enabled": true,
"subscribed_events": ["EXTRACTION_COMPLETED", "QUERY_RESULTS_REFRESHED", "FAILURE"],
"notify_integration_owner": true,
"additional_recipients": ["data-ops@example.com"],
"delivery_methods": [
{ "type": "EMAIL" }
]
}
}Data extracted and parsed to the access graph.
File Upload Failure
File could not be received, or extraction failed. A single trigger covers both failure modes.
Extraction of the CSV file "employees.csv" has started.
File Successfully Uploaded
File Successfully Uploaded
The CSV file "employees.csv" has been successfully uploaded.
File Upload Failure (file not received)
File Received — Failed
The CSV file "employees.csv" was not received. Please contact Veza Support for further assistance.
Error: <underlying error>
File Upload Failure (extraction failed)
File Extraction — Failed
The CSV file "employees.csv" could not be extracted. Please contact Veza Support for further assistance.
Error: <underlying error>
The query did not finish in time for the latest risk-score cycle — it is still running, has not been evaluated yet, or has not been completed after the cycle ran (so its result is not yet reflected).
Queries refreshed, but risk score update did not run for "employees.csv".
Risk scores not updated and some queries did not succeed
Risk scores not updated and not all queries succeeded for "employees.csv".
Reference implementation for automating HRIS data uploads to Veza from S3 using AWS Lambda
This page provides a reference implementation for syncing employee data from an S3-hosted Excel file to Veza using AWS Lambda. Download the example deployment package, configure it for your environment, and schedule it with Amazon EventBridge.
The function reads an employee Excel file from S3 and pushes records to Veza using the HRIS template. It uses the oaaclient Python library to push data, and pandas with openpyxl as the Excel engine to read the employee spreadsheet. openpyxl is bundled in the zip; pandas is provided by the Lambda layer added in the next section.
Reads environment variables for your Veza API key, S3 bucket, and HRIS name
Downloads the employee Excel file from S3 to Lambda's /tmp directory
Iterates each row to create an HRISProvider employee record
Creates departments as groups and links employees to them
Pushes the complete HRIS payload to Veza via the OAA API
Optionally enables Lifecycle Management provisioning on the provider
An AWS account with permission to create and configure Lambda functions
An S3 bucket containing the employee Excel file
A Veza API key (see )
Open the and click Create function
Choose Author from scratch
Set the function name (for example, veza-hris-importer)
Set Runtime to
After uploading, verify the handler is set to lambda_function.lambda_handler under Runtime settings.
The function uses pandas to read Excel files, with openpyxl as the engine. openpyxl is bundled in the deployment package; pandas is not included in the standard Lambda Python runtime and must be added as a layer.
Add the layer:
Scroll to Layers and click Add a layer
Choose Specify an ARN
Paste the ARN for your AWS region:
Under Configuration → General configuration, set:
Memory: 512 MB
Timeout: 5 minutes
Under Configuration → Environment variables, add:
Same-account bucket:
Go to Configuration → Permissions and click the execution role name
Choose Add permissions → Attach policies
Attach AmazonS3ReadOnlyAccess
Cross-account bucket:
In addition to the role policy above, ask the bucket owner to add a bucket policy granting access to the Lambda execution role:
Replace YOUR-ACCOUNT, YOUR-LAMBDA-ROLE, and bucket-name with the appropriate values.
Open the Test tab
Create a test event with an empty payload: {}
Click Test
A successful run returns a statusCode
The S3 Excel file must include all of the following columns except Work Email. Column names are case-sensitive, and every required column must be present even where values are blank — update the names in lambda_function.py if your file uses different headers.
To run the function automatically on a schedule:
Go to Configuration → Triggers → Add trigger
Select EventBridge (CloudWatch Events)
Choose Create a new rule, give it a name, and set a schedule expression:
Before deploying to Lambda, you can run the function locally against a real Veza tenant using DATA_SOURCE=local. This is the fastest way to iterate on column mappings or custom properties.
Prerequisites: Python 3.11+. oaaclient and openpyxl are bundled in the zip. Extract it, then install the remaining dependencies:
Set environment variables and run:
A successful run logs Success and creates (or updates) an HRIS provider in Veza. Check Integrations in the Veza UI to confirm the provider and employee records appear.
The load_users function in lambda_function.py maps columns directly by name. To adapt it for a different Excel schema:
Update the column name strings (for example, row['Employee Id']) to match your file headers
Add custom employee properties by calling hris.property_definitions.define_employee_property() before iterating rows
To link employees to an IdP (for example, Okta), add hris.system.add_idp_type() with the appropriate IdPProviderType
— manual and API-based upload options
— data model for employee records
— automate provisioning based on HRIS data
Click Create function
Under Code source, click Upload from → .zip file and upload veza-hris-lambda.zip
The version suffix (:19) may not be the latest. Check the for the current version and full ARN list for all regions.
Click Add
200bodyrate(1 day)Daily at 9 AM UTC: cron(0 9 * * ? *)
Click Add
VEZA_URL
Your Veza tenant URL, for example https://yourcompany.vezacloud.com
VEZA_API_KEY
A Veza API key with permission to push OAA data
DATA_SOURCE
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::YOUR-ACCOUNT:role/YOUR-LAMBDA-ROLE"
},
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::bucket-name/*",
"arn:aws:s3:::bucket-name"
]
}]
}{
"statusCode": 200,
"body": "{\"message\": \"HRIS data processed successfully\", \"result\": { ... }}"
}Employee Id
Unique identifier for the employee
Display Name
Full display name
First Name
unzip veza-hris-lambda.zip -d veza-hris-lambda
cd veza-hris-lambda
pip install pandas boto3export DATA_SOURCE=local
export DATA_SOURCE_LOCAL=/path/to/employees.xlsx
export VEZA_URL=https://yourcompany.vezacloud.com
export VEZA_API_KEY=your-api-key
export HRIS_VENDOR="Acme HR"
export HRIS_VENDOR_URL="https://hr.acme.com"
export ENABLE_LCM=false
python lambda_function.pyus-east-1
arn:aws:lambda:us-east-1:336392948345:layer:AWSSDKPandas-Python311:19
us-west-2
arn:aws:lambda:us-west-2:336392948345:layer:AWSSDKPandas-Python311:19
eu-west-1
arn:aws:lambda:eu-west-1:336392948345:layer:AWSSDKPandas-Python311:19
remote reads the file from S3 (use this for Lambda). local reads from a local path set in DATA_SOURCE_LOCAL (for testing only).
DATA_SOURCE_LOCAL
Local file path to the employee Excel file. Only used when DATA_SOURCE=local. Not needed for Lambda deployments.
S3_BUCKET_NAME
Name of the S3 bucket containing the employee file. Required when DATA_SOURCE=remote.
S3_FILE_NAME
Path to the Excel file within the bucket, for example hr/employees.xlsx. Required when DATA_SOURCE=remote.
HRIS_VENDOR
Display name for your HRIS system
HRIS_VENDOR_URL
URL of your HRIS system
ENABLE_LCM
true turns on provisioning for the provider. Other values skip that step; they do not turn it off again.
Given name
Last Name
Family name
Preferred First Name
Preferred or nickname (can be blank)
Status
Active marks the employee as active. Any other value (for example, Terminated) marks them inactive, and the value is recorded as-is as the employment status.
Employment Type
For example, Full-time, Part-time, Contractor
Most Recent Hire Date
Excel date cell, or a YYYY-MM-DD string
Job Title
Employee job title
Department
Department or team name
Work Email
Work email address. The only optional column: the example reads it defensively, so it can be blank or absent entirely, and either way the employee's email is set to an empty string.
Work Location Name
Office or location name
Common patterns for importing identity and permissions metadata from CSV files
This document provides practical examples for mapping data from CSV files into Veza using the CSV Upload integration.
You can use the CSV integration to flexibly model user, group, and role relationships based on data exported from the source application. This document includes examples from basic user data import to modeling more complex organizational structures, which you can adapt based on your needs.
When importing CSV data into Veza, you are typically establishing one or more of these key components:
Entities: Users, groups, and roles that exist in your application
Attributes: Properties that describe each entity (e.g., name, email, status)
Relationships: Connections between entities (user belongs to group, user has role)
The examples below demonstrate different approaches to mapping these components from CSV data into Veza's Access Graph.
For a simple file containing user records, one user per row with a list or groups and roles. You can map columns directly:
Example CSV:
Your CSV files may have column names that differ from Veza's standard attribute names.
The CSV integration supports two methods for assigning users to groups and roles:
Use a single column containing comma-separated values to assign a user to multiple groups or roles at once.
Column mapping:
Example CSV:
Key points about list columns:
Values must be comma-separated
Enclose lists in quotes if they contain commas
Whitespace around values is automatically trimmed
Empty values are ignored
You can incrementally assign roles or groups using multiple rows with the same user id. This approach is useful when:
You have many groups or roles per user
Your source system exports data in this format
You need to include additional details for roles or groups such as custom properties
Example CSV:
Key points about multiple row assignments:
The first occurrence of an entity id sets all properties for that entity. If the same user or role is listed more than once, the user or role attributes are not updated for rows after the first.
Subsequent rows only process new group and role assignments
The CSV can include a column with a list of permissions for each role. This enables searching and filtering by permission in Veza:
You can assign permissions to roles and then users to roles:
Note: If permissions column is not defined any Roles are automatically assigned the
Memberpermission
This example shows how to represent a complex organizational structure with departments, teams, roles with permissions, and user assignments:
Column mapping for this example:
This example CSV will create:
7 user entities with their properties
Department groups (Engineering, Product, Marketing, Finance, HR, Sales)
Team groups (Backend, Architecture, Frontend, Product Management, UX Research, Content, Social, Accounting, Recruiting, Enterprise Sales)
Multiple role assignments per user
The CSV integration supports various timestamp formats:
Timestamps are considered unset when the value is never, null, none, false, or 0. Invalid timestamps will result in a processing error.
When mapping to boolean attributes like is_active:
TRUE values: true, t, yes, y, 1, active, enabled
FALSE values: Any other value including false
Any column can be mapped to a custom property for any entity type. When mapping to a custom property:
Select Custom Property as the attribute
Enter a name for the custom property
Select the data type (String, Number, Boolean, Timestamp
Designated Entity Owners can up supplied for supported Application entity types as part of the CSV. This allows for automatically assigning the owner from the value in the CSV.
This example indicates the owner of the Role and could be used auto-assign Access Review rows to the owner for each role.
Note that when a is configured, Owner Type is optional. Otherwise, the owner type is used to specify the type of entity in Veza Graph that will be assigned as an owner. This will typically be a User entity in your organization's Identity Provider (such as an Okta, Azure AD User, or Active Directory User), representing a top-level human identity.
For more information about Entity Owners, see:
Permissions: Actions that roles allow users to perform
Veza automatically creates any groups or roles that don't already exist
Additional properties on Groups and Roles is not supported
Role permission assignments for different functional areas
fnon0inactivedisabledString Listemployee_id
local_user
id
Yes
employee_id,display_name,email_address,account_status,join_date,last_access,password_updated,termination_date,groups,roles
EMP001,Alex Johnson,alex.j@example.com,active,2023-04-15,2025-02-15T09:30:45Z,2024-11-10T08:15:30Z,,"Engineering, DevOps","Developer, System Administrator"
EMP002,Taylor Smith,taylor.s@example.com,true,2022-09-20,2025-03-01T11:45:20Z,2024-10-05T14:30:15Z,,"Product, UX Research","Product Manager, UX Designer"
EMP003,Jordan Lee,jordan.l@example.com,inactive,2021-11-05,2024-10-10T16:20:30Z,2024-06-15T09:45:10Z,2025-01-15,"Marketing, Content","Content Creator, Social Media Manager"
EMP004,Casey Morgan,casey.m@example.com,1,2023-08-22,2025-02-28T15:10:25Z,2024-12-20T10:30:45Z,,"Finance, Accounting","Financial Analyst, Auditor"
EMP005,Riley Brown,riley.b@example.com,0,2022-03-10,2024-11-15T08:45:30Z,2024-08-05T11:20:15Z,2024-12-31,"HR, Recruiting","HR Specialist, Talent Acquisition"departments, department_names, teams
local_group
name list
job_titles, positions, roles_assigned
local_role
user_id
local_user
id
groups
local_group
user_id,groups,roles
user1,"Engineering, QA Team, Product Team","Software Engineer, Technical Lead"
user2,Marketing,"Content Writer, Editor"
user3,Finance,"Accountant, Auditor"
user4,HR,HR Specialist
user5,"Support, Training",Customer Support Representativeuser_id,name,email,active,group,role,role_description
user1,Alice Smith,alice@example.com,true,Engineering,Software Engineer,Core development role
user1,Alice Smith,alice@example.com,true,QA Team,Technical Lead,Testing oversight role
user1,Alice Smith,alice@example.com,true,Product Team,Technical Lead,Product development leadership
user2,Bob Johnson,bob@example.com,false,Marketing,Content Writer,Content creation role
user2,Bob Johnson,bob@example.com,false,Marketing,Editor,Content review roleuser_id,name,email,is_active,groups,role,permissions
USR001,Alex Johnson,alex.j@example.com,true,"Dev Team",Developer,"view_code, edit_code"
USR001,Alex Johnson,alex.j@example.com,true,"Backend Group",Code Reviewer,"approve_pull_requests"
USR002,Taylor Smith,taylor.s@example.com,yes,"Ops Team",System Administrator,"manage_infrastructure"
USR002,Taylor Smith,taylor.s@example.com,yes,"Cloud Admin",Release Manager,"deploy_production"
USR003,Jordan Lee,jordan.l@example.com,1,"Product Team",Product Owner,"create_requirements"
USR003,Jordan Lee,jordan.l@example.com,1,"Analytics Users",Data Analyst,"view_analytics"user_id,display_name,email,active,department,team,job_title,role,role_permissions
emp101,John Smith,john.smith@example.com,true,Engineering,Backend,"Senior Developer","Developer Lead","read_all,write_backend,deploy_backend"
emp101,John Smith,john.smith@example.com,true,Engineering,Architecture,"Senior Developer","Architecture Committee","approve_designs,modify_architecture"
emp102,Jane Doe,jane.doe@example.com,true,Engineering,Frontend,"UI Developer","Frontend Developer","read_all,write_frontend,deploy_frontend"
emp103,Robert Johnson,robert.j@example.com,true,Product,"Product Management","Product Owner","Product Manager","read_all,create_requirements,approve_features"
emp103,Robert Johnson,robert.j@example.com,true,Product,"UX Research","Product Owner","User Researcher","conduct_research,analyze_results"
emp104,Maria Garcia,maria.g@example.com,true,Marketing,Content,"Marketing Specialist","Content Creator","read_marketing,write_content"
emp104,Maria Garcia,maria.g@example.com,true,Marketing,Social,"Marketing Specialist","Social Media Manager","post_social,analyze_metrics"
emp105,David Lee,david.l@example.com,true,Finance,Accounting,"Finance Manager","Financial Controller","approve_expenses,manage_budgets,generate_reports"
emp106,Sarah Wilson,sarah.w@example.com,true,HR,Recruiting,"HR Specialist","Recruiter","post_jobs,review_applications,conduct_interviews"
emp107,Michael Brown,michael.b@example.com,true,Sales,"Enterprise Sales","Sales Executive","Account Manager","manage_clients,create_proposals,close_deals"user_id
local_user
id
display_name
local_user
user_id,name,email,active,created_at,last_login_at,password_last_changed_at,deactivated_at
TS001,Timestamp Example 1,ts1@example.com,true,2023-04-12T15:34:56.123456789Z,2006-01-02T15:04:05Z07:00,20060102150405,
TS002,Timestamp Example 2,ts2@example.com,true,2006-01-30 15:04:05Z07:00,2006-01-30 15:04:05,2006-01-30,2006-01-30T
TS003,Timestamp Example 3,ts3@example.com,true,2006-01-30T15:04:05,2006-01-30T15:04:05Z,never,null
TS004,Timestamp Example 4,ts4@example.com,false,2024-03-15,none,false,0
TS005,Timestamp Example 5,ts5@example.com,true,1/2/2006,1/15/2023,11/22/2024,user_id
local_user
Id
user_name
local_user
display_name
local_user
name
No
email_address
local_user
No
account_status
local_user
is_active
No
join_date
local_user
created_at
No
last_access
local_user
last_login_at
No
password_updated
local_user
password_last_changed_at
No
termination_date
local_user
deactivated_at
No
groups
local_group
name list
No
roles
local_role
name list
No
name list
permissions, access_rights
local_role
permissions list
name list
roles
local_role
name list
name
local_user
active
local_user
is_active
department
local_group
name
team
local_group
name
job_title
local_user
custom property (String)
role
local_role
name
role_permissions
local_role
permissions list
Name
role_name
local_role
Name
role_owner
local_role
Owner Id
role_owner_type
local_role
Owner Type
user_id,name,email,active
B001,Boolean Example 1,b1@example.com,true
B002,Boolean Example 2,b2@example.com,t
B003,Boolean Example 3,b3@example.com,yes
B004,Boolean Example 4,b4@example.com,y
B005,Boolean Example 5,b5@example.com,1
B006,Boolean Example 6,b6@example.com,active
B007,Boolean Example 7,b7@example.com,enabled
B008,Boolean Example 8,b8@example.com,false
B009,Boolean Example 9,b9@example.com,f
B010,Boolean Example 10,b10@example.com,no
B011,Boolean Example 11,b11@example.com,n
B012,Boolean Example 12,b12@example.com,0
B013,Boolean Example 13,b13@example.com,inactive
B014,Boolean Example 14,b14@example.com,disableduser_id,name,email,active,department,title,office_location,hire_date,employee_type,salary_band,performance_rating,certification,languages,project_ids,manager_id,emergency_contact
CP001,Custom Property Example 1,cp1@example.com,true,Engineering,Senior Developer,New York,2023-01-15,Full-time,B4,Exceeds Expectations,"AWS Certified, Azure Expert","Java, Python, Go","PROJ-001, PROJ-002",MGR-101,John Smith (555-123-4567)
CP002,Custom Property Example 2,cp2@example.com,true,Marketing,Marketing Manager,San Francisco,2022-05-10,Full-time,C2,Meets Expectations,Google Analytics,"English, Spanish",PROJ-003,MGR-102,Mary Johnson (555-987-6543)
CP003,Custom Property Example 3,cp3@example.com,false,Finance,Financial Analyst,Chicago,2023-08-22,Contract,A3,Needs Improvement,CPA,"English, French","PROJ-004, PROJ-005, PROJ-006",MGR-103,Robert Davis (555-456-7890)user_id,user_name,role_name,role_owner,role_owner_type
10001,bob,admin,owner_1@example.com,,oktauser
10002,sue,admin,owner_1@example.com,oktauser
10003,marry,user,owner_2@example.com,oktauser
10004,jane,user,owner_2@example.com,oktauser
10005,sam,viewer,owner_3@example.com,oktauser
10006,adam,viewer,owner_3@example.com,oktauser
10007,brett,ops,owner_4@example.com,oktauser
10008,robert,ops,owner_4@example.com,oktauser
10009,chris,manager,,
10010,nick,manager,,Solutions for common CSV import issues in Veza
This document helps you identify and resolve common issues when importing CSV files into Veza.
Before troubleshooting, it's important to understand how the CSV import process works:
Maximum file size: 100MB per CSV file
Character encoding: UTF-8 recommended
First row: Must contain column headers
Column delimiters: Commas
Text qualifiers: Double quotes for fields containing commas
Users: Each user must have either an id or name (or both)
Groups: Each group must have either an id or name (or both)
Roles
First-row behavior: For entities appearing in multiple rows, only the first row sets the entity properties
Subsequent rows: Additional rows with the same identifier only process group and role assignments
Role permissions: Permissions for the same role are added across all rows (additive)
All properties: All properties (including custom properties) are set only from the first row where that entity appears
Start with a test file
Begin with a small subset of data to verify your mapping configuration
Test with representative examples of your data structure
Validate CSV format
Be aware of these current limitations in the CSV import functionality:
No application resources support
Resources within applications are not currently supported
No direct user-to-permission mapping
Permissions must be assigned to roles, which are then assigned to users
If you continue to experience issues after reviewing this guide:
Review the for details on supported formats and mapping options
Check the for guidance on structuring your CSV files
Contact Veza Support with:
A sample of your CSV file (with sensitive data removed)
idnameIf only id or name is provided for an entity, that value is used for both fields and must be unique
Minimum mapping: You must map at least one column for each entity type you want to import
Ensure proper comma delimitation
Quote fields containing commas
Use consistent data formats across rows
Pre-plan your mapping
Identify which columns map to which entity types and attributes
Determine how to handle multi-value fields (as lists or multiple rows)
Identify custom properties and their data types
Consider data quality
Standardize identifiers (case consistency, no trailing spaces)
Use consistent naming for groups and roles
Validate data formats before import
Direct user-to-permission mappings (without a role) are not supported
No column transformations
The system cannot combine or transform column values during import
Column transformations or combinations are not supported
Full replacement updates
Each update completely replaces the previous data
Incremental updates are not supported
Custom property types are fixed after creation
Once a custom property type is set and data processed, it cannot be changed
Changing custom property types requires deleting the integration and recreating it
Default permissions
If no column is mapped to role permissions, Veza assigns a default "Uncategorized" permission.
HRIS Type field propagation
Updates to the HRIS Type field require a complete CSV file re-upload to propagate changes to downstream systems like Lifecycle Management (LCM)
Changing the HRIS Type field alone will not update entity names throughout the system
Your mapping configuration
A description of the unexpected behavior
Entity names inconsistent between CSV provider and Lifecycle Management (LCM) after update
Critical: When updating the HRIS Type field for an HR System template integration, you must re-upload the complete CSV file immediately after changing the type. Updating the HRIS Type field without re-uploading data causes system-wide inconsistencies. See the for detailed steps.
CSV file is rejected with validation error
Verify you've mapped the minimum required fields (id or name for all entity types)
Only some properties appear
Check that columns are mapped to the correct entity types and attributes
Users appear without group/role assignments
Imported users are not connected to identity provider users
Confirm the local user's Identities attribute holds a value. Set the Identity field on the application configuration to the correct column names, or map a column to the local user Identities attribute. Mapping a column to Email does not correlate the user. See
Some users connect and others do not
Compare the identity value to the attributes Veza reads from your provider, such as the Okta login or the Entra ID principal name. The comparison ignores case but is otherwise exact, so values differing by a domain, an email alias, or a trailing space do not correlate
Users share an employee ID with the provider but do not connect
Boolean values not interpreted correctly
Use standard values: true, t, yes, y, 1, active, or enabled for TRUE
Timestamp data not processed
Ensure timestamps are in one of the supported formats listed in the
Multiple groups/roles not assigned properly
Manager field not populating on graph
Ensure manager ID values are in lowercase. The system compares employee IDs to the lowercase value of the manager attribute. For example, use manager_id: emp001 instead of EMP001.
Manager relationships not appearing after import
Verify that the manager ID value exactly matches an existing employee's unique identifier (in lowercase format).
Groups/roles in comma-separated lists not assigned
Verify you've selected the list option when mapping the column
Only first value in list is processed
Check for proper quoting around values that contain commas
Only some list values appear
Ensure you've correctly mapped group and role columns
Entities appear multiple times
Ensure that the value you're using for id is unique (Veza automatically cleans whitespace and is case-insensitive)
Import fails with duplicate column error
Column names must be unique (case-insensitive). While mapping allows columns with different cases like "Email" and "email", the import will fail. Ensure all column headers have unique names regardless of case
Veza does not compare employee IDs automatically. Add a property matcher on the identity provider integration with the application as the destination. See
Employees from an HRIS import are not connected
Veza uses the first value present among IDP ID, Email, and Employee Number. Confirm the column you rely on is mapped and that earlier columns in that order are empty or hold the same value
Users correlate to Okta users but have no sso_last_login_at value, or the value is older than the sign-in Okta reports
Okta SSO last login enrichment has its own configuration, separate from identity correlation, and Veza reads Okta activity only while processing a CSV upload. Parsing the stored payload again does not refresh the value. Confirm that the application specifies an Okta App ID, and that the tenant matching property points to the Okta user property that holds the matching value, then upload the CSV again. See
For list columns, ensure values are comma-separated and enclosed in quotes if they contain commas
Special characters causing parsing issues
Save your CSV with UTF-8 encoding and ensure text with commas is properly quoted
Check for inconsistent naming between list items and other references to the same entity
Import identity and authorization data from CSV files into Veza
Use CSV Upload to integrate identity and authorization metadata from sources that don't have built-in Veza connectors, but can export or provide data in tabular format.
You can create a CSV integration in Veza to:
Import user and authorization data from legacy or custom applications
Integrate with SaaS applications that support CSV exports
Model employee access to homegrown or specialized systems
Upload employee metadata from your HRIS as a source of identity for Lifecycle Management workflows
The integration uses the Open Authorization API (OAA) to map CSV data to supported OAA templates:
Application - Models Users, Groups, Roles, and Resources across applications for a wide variety of authorization use cases. An introduction to the Application Template .
Human Resource Information Systems (HRIS) - Models employee information from HR sources for use with Lifecycle Management (LCM).
Application Template - Use Custom Applications to model business applications and access permissions:
Models Users, Groups, Roles, and Resources across applications
For example, you can upload user permissions from a homegrown CRM system, data store, or any other application users can access.
HRIS Template - Use for employee data from HR systems
Models employee information and organizational structure
For example, you can upload employee data for manager-based Access Reviews and automated provisioning with Lifecycle Management.
CSV integration is ideal for systems that export tabular data but lack dedicated Veza connectors:
Legacy applications with user permission exports
Custom business applications built in-house
HR systems for employee lifecycle management
Specialized industry tools without native APIs
CSV import enables modeling identity and permissions metadata for any application not natively supported by Veza, with flexible column mapping, custom properties, and support for multiple data formats.
To create an integration from CSV, you will need:
A CSV file containing relevant data with column headers
Sufficient permissions in Veza (Admin or OAA CSV Manager role)
Understanding of the data model for the source application
A plan for mapping between CSV columns and Veza attributes
For more information about user roles and permissions, see .
CSV (Comma-Separated Values) is a widely used file format that stores tabular data in plain text. Each row represents a record or a relationship between entities (e.g., User to Role), and columns represent attributes.
When importing from CSV:
The first row must contain column headers
Each column can be mapped to a specific Veza attribute or custom attribute
Columns can be ignored after uploading the file
At minimum, you must map columns for unique identifiers (such as user ID or Name) for each entity type you plan to import (e.g., Users, Groups, Roles, or Employees).
To create a new CSV integration:
Go to Integrations > Add Integration
Choose Upload CSV from the options
Upload a logo for the provider (optional) - This will appear throughout the Veza UI, including in Graph search, to identify the integration and entity types.
Enter an integration name
The CSV integration allows you to map columns in your file to specific Veza attributes. After uploading the CSV, Veza automatically detects all columns and presents them for mapping.
For each column, you can:
Select to include or exclude the column
Select the target entity type for mapping (available entities depend on the selected template)
Select the specific entity attribute to map to (only attributes applicable to the selected entity type will be shown)
For custom properties, specify a name and data type
Example: Mapping CSV columns to Application template entities and attributes
For more examples and detailed mapping patterns, see .
Additionally, you can apply to column data for more flexibility and additional formatting. Transformations can be used to:
Combine columns to form a single attribute (e.g., first_name and last_name into a display name)
Reformat data such as dates, times, and case (uppercase, lowercase)
Apply padding, trimming, and character replacement
For all entities, an ID or Name is required. If ID is not provided, Name is automatically used as the unique identifier for the entity. Both are also supported.
The available entity types and attributes depend on the template you select. Each template supports different entity types.
Application Template Entities
User Attributes
Group Attributes
Role Attributes
HR System Template Entities
Employee Attributes
The following values are treated as TRUE (case-insensitive):
true, t
yes, y
1
Any other value is treated as FALSE.
Veza supports multiple timestamp formats:
2023-04-12T15:34:56.123456789Z (RFC3339 with nanoseconds)
2006-01-02T15:04:05Z07:00 (RFC3339)
20060102150405 (Active Directory format)
Timestamps are considered unset when the value is never, null, none, false, 0 or empty. Invalid timestamps will result in a processing error.
For attributes that support lists (like Role Name List, and Group Name List), values should be comma-separated within the cell and the list enclosude by quotes ".
Incremental updates are not supported; you must submit the complete data set for each update.
Find the CSV integration on the Veza Integrations page
Click on the integration name to view details
Under Data Sources, click Upload CSV
Select your updated CSV file and click Upload
Find the CSV integration on the Veza Integrations page
Click on the integration name to view details
Click Edit
In the integration configuration, click Edit above the table of current mappings
CSV integrations can send notifications about file upload and extraction status, and a Query Results Refreshed summary of how the risk-scored queries affected by an upload re-evaluate once it completes. Configure notifications on the Notifications tab when creating or editing a CSV integration.
For the available triggers, delivery options, recipients, message content, and REST API configuration, see .
Veza provides a limited privilege "CSV Manager" role for users that need permission to manage a CSV integration, but should not have access to other functionality in Veza.
Users with this role can:
Create new CSV integrations
Upload new CSV data
Edit existing CSV integrations, including delete
This role can be combined with to further limit a user's scope. When a user with the CSV manager role is added to a non-root team, they can only manage CSV integrations assigned to their team.
Multiple Rows per Entity: If the same entity (user, group, or role) appears in multiple rows, Veza processes them as follows:
Properties are set based on the first row where the entity ID (or Name if it is being used as the unique ID) appears
For subsequent rows with the same identifier, only relationship assignments are processed (for example user to group, or user to role)
Veza correlates the users in your CSV to users in your identity provider by comparing an identity value on each imported user against the attributes it reads from the identity provider. With the Application template, set that value in either of these ways:
Enter the column names in the Identity field of the application configuration, as a comma-separated list such as email or email,username.
Map a column to the local user Identities attribute in the column mapper. Mark the mapping as a list to split multiple values from one column.
If you upload a CSV without mapping columns, Veza uses the email column as the identity value.
The values you supply must equal one of the attributes Veza compares on the identity provider, such as the Okta login or email address, or the Entra ID and Active Directory user principal name. The comparison ignores case but is otherwise exact, so a value that differs by a domain, a formatting difference, or a trailing space does not correlate.
Veza does not compare employee IDs automatically. To correlate on an employee ID, or on any other attribute, add a property matcher on the identity provider integration and select the application as the destination. See .
For the attributes Veza compares for each provider, and for how to diagnose users that do not correlate, see .
With the HRIS template, Veza resolves the identity value from the IDP ID, Email, and Employee Number columns, in that order, and takes the first that has a value. An HRIS CSV integration can also hold its own mapping configuration.
Identity mapping does not govern Okta SSO last login enrichment. That enrichment reads the same identity values, but it compares them against one Okta user property that you configure separately, and it applies only to applications that specify an Okta App ID. Correlating a user to an Okta user is therefore not sufficient to produce a sso_last_login_at value. See .
Use a title that uniquely identifies this integration source
Avoid generic terms like "application" or "CSV"
If you have multiple environments, consider including that in the name
Select a data source template (currently supports Application and HR Systems)
Enter template-specific information (fields will vary based on the selected template):
For Application Template:
Name: A unique identifying name for this specific application instance (e.g., "Marketing CRM - Prod", "HR Portal - Dev").
Type: The general category or system type (e.g., "CRM", "DevOps Tool"). In Veza, the type appears as a prefix on entity names, e.g., CRM User, DevOps Tool Role.
Identity: Optional. The comma-separated names of the columns holding the values that correlate each application user to an identity provider user, such as email or email,username. See .
Okta App ID: Optional, early access. The Okta application ID (0oa…) of the Okta application that provides SSO access to this application. Veza uses it to record the last time each local user signed in through Okta SSO. This field is visible only when the feature is enabled on your tenant. See .
For HR System Template:
Name: A unique identifying name for the HR system (e.g., "Workday - Production", "HR Portal - Dev")
Type: The type of HR system (e.g., "HRIS", "ATS", "Benefits")
URL: The URL of the HR system
Note: Naming is critical for easy search in Veza. For Applications, the Type enables searching for all entities of that category, while the Name differentiates between multiple instances of the same system type.
Upload the CSV file - Veza will read the column headers and show them for mapping
Map your columns to Veza attributes (see Column Mapping section)
Click Create Integration to trigger extraction and parsing
Mark the row value as required. If a column mapping is marked required the CSV upload will be rejected if any row is missing a value in that column.
Created At
Timestamp when the user was created
Last Login At
Timestamp of the user's last login
Deactivated At
Timestamp when the user was deactivated
Password Last Changed At
Timestamp of the last password change
User's email address (display only, not used to correlate the user to an identity provider)
Identities
Value(s) used to correlate the user to an identity provider user (supports list format)
Custom Properties
Map any column to a custom user property (type varies)
Owner ID
Entity Owner ID to assign
Owner Type
User node type for Entity Owner(s)
Custom Properties
Map any column to a custom group property (type varies)
Owner ID
Entity Owner ID to assign
Owner Type
User node type for Entity Owner(s)
Custom Properties
Map any column to a custom role property (type varies)
Owner ID
Entity Owner ID to assign
Owner Type
User node type for Entity Owner(s)
Alternative employee identifier. Used to correlate the employee to an identity provider user when IDP ID and Email are both empty
Company
Employee's company
First Name
Employee's first name
Last Name
Employee's last name
Preferred Name
Employee's preferred name
Display Full Name
Complete display name
Canonical Name
Standardized name format
Username
Employee's username
Primary email address. Used to correlate the employee to an identity provider user when IDP ID is empty
IDP ID
The employee's identifier in the destination identity provider. Checked first when correlating the employee to an identity provider user. See
Personal Email
Personal email address
Home Location
Employee's home location
Work Location
Employee's work location
Cost Center
Cost center assignment
Department
Employee's department
Managers
Employee's manager(s) (supports list format)
Groups
Group memberships (supports list format)
Employment Status
Current employment status
Is Active
Boolean indicating active employment
Start Date
Employment start date
Termination Date
Employment end date
Job Title
Employee's job title
Employment Types
Types of employment (supports list format)
Primary Time Zone
Employee's primary time zone
Custom Properties
Map any column to a custom employee property (type varies)
active
enabled
2006-01-30 15:04:05Z07:00
2006-01-30 15:04:05
2006-01-30
2006-01-30T
2006-01-30T15:04:05
2006-01-30T15:04:05Z
1/2/2006 (MM/DD/YYYY format)
Modify your column mappings as needed
Click Save Configuration to apply the changes
Ignored Columns: Columns that are not mapped (unchecked) are ignored during processing
Additional Columns: CSV files can contain more columns than are mapped - extra columns are ignored
Entity Identifiers: Every entity type (user, group, role) requires an ID or Name (or both). If only one is provided, the same value is used for both fields and must be unique.
ID
Unique identifier for the user
Name
Display name for the user
Is Active
ID
Unique identifier for the group
Name
Name of the group (supports list format)
Created At
ID
Unique identifier for the role
Name
Name of the role (supports list format)
Permissions
ID
Unique identifier for the employee
Name
Employee name (typically full name)
Warning: Mapping Employment Status Properties with HRIS CSV
When manually mapping your HRIS CSV, use only one of the following two fields: is_active or employment_status to avoid misleading data on employment type.
Column Header Case Sensitivity: Column headers must be unique regardless of case. While the mapping interface is case-sensitive and may allow you to map columns with similar names like "Email" and "email", the import process is case-insensitive and will fail if duplicate column names exist with different casing. Ensure all column headers have distinct names.
⚠️ Warning: Mapping Properties with HRIS CSV
When manually mapping your HRIS CSV, use only one of the following two fields: is_active or employment_status to avoid misleading data on employment type.
Manager Field Case Sensitivity
When mapping the Managers or manager_id field in HRIS CSV imports, ensure that manager ID values are in lowercase. The system compares employee unique IDs to the lowercase value of the manager attribute when building manager relationships.
For example, if an employee has employee_number: EMP001, the manager reference for their direct reports should use manager_id: emp001 (lowercase), not EMP001.
⚠️ Warning: Configuration Updates
When updating the configuration fields or mappings for an existing CSV integration, changes are not reflected until after the next CSV Upload is processed. For example when updating the HRIS Type field, changing this field alone and saving the integration will not immediately change the type Veza system. Then new type will not be availble in graph or in other features such as Lifecycle Management (LCM) until after the next upload is processed.
Required Process for changing configurations:
Update the configuration fields in the integration settings
Re-upload the complete CSV file to apply the changes
Allow the Veza platform to complete the extraction and parse process
Verify that entity names are consistent across all Veza components
Early Access Feature: The CSV Manager role is currently in early access and must be enabled by Veza support before it can be assigned to users. Contact your Customer Success Manager or submit a support request to enable this role.
Mapping a column to the local user Email attribute does not correlate the user. Email populates a display attribute only. Populate Identity or Identities as well, even when the value is the same email address.

Boolean indicating if the user is active
Timestamp when the group was created
Permissions assigned to the role (supports list format)
Employee Number