Veracity.Core.Api.V4
1.0.20251203.3
Prefix Reserved
dotnet add package Veracity.Core.Api.V4 --version 1.0.20251203.3
NuGet\Install-Package Veracity.Core.Api.V4 -Version 1.0.20251203.3
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Veracity.Core.Api.V4" Version="1.0.20251203.3" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Veracity.Core.Api.V4" Version="1.0.20251203.3" />
<PackageReference Include="Veracity.Core.Api.V4" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Veracity.Core.Api.V4 --version 1.0.20251203.3
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Veracity.Core.Api.V4, 1.0.20251203.3"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Veracity.Core.Api.V4@1.0.20251203.3
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Veracity.Core.Api.V4&version=1.0.20251203.3
#tool nuget:?package=Veracity.Core.Api.V4&version=1.0.20251203.3
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Veracity.Core.Api.V4 - Comprehensive Documentation
Table of Contents
- Overview
- Installation and Setup
- Quick Start Guide
- Core Concepts
- API Reference
- Advanced Features
- Authentication
- Error Handling
- Best Practices
- Examples
Overview
The Veracity.Core.Api.V4 package is the official .NET SDK for the Veracity Platform Graph API. It provides comprehensive access to Veracity's identity and resource management system.
Key Features
- Tenant Management - Organizational units for data isolation
- User & Group Management - Identity and access control
- Application Licensing - Service instance and license management
- Element Management - Application-specific resource hierarchies
- Fine-Grained Permissions - Element-level access control
- Extension Properties - Custom metadata on all entities
- Type-Safe Responses - Strongly-typed wrapper support
- Built-in Authorization - ASP.NET Core attribute-based protection
Supported Frameworks
- .NET 6
- .NET 7
- .NET 8
- .NET 9
Installation and Setup
1. Install Package
dotnet add package Veracity.Core.Api.V4
2. Configuration (appsettings.json)
{
"Veracity": {
"veracityGraphBaseUrl": "https://api.veracity.com/veracity/graph/v4",
"applicationPrefix": "myapp",
"serviceId": "your-application-id-from-developer",
"clientId": "your-client-id",
"clientSecret": "your-client-secret",
"subscriptionKey": "your-subscription-key",
"instance": "https://login.microsoftonline.com/tfp/",
"domain": "dnvglb2cprod.onmicrosoft.com",
"policy": "B2C_1A_SignInWithADFSIdp",
"callbackPath": "/signin-oidc",
"scope": "https://dnvglb2cprod.onmicrosoft.com/83054ebf-1d7b-43f5-82ad-b2bde84d7b75/user_impersonation"
}
}
3. ASP.NET Core Setup (Startup.cs)
public void ConfigureServices(IServiceCollection services)
{
// Load configuration
services.AddVeracity(Configuration);
// Add Veracity Graph API with logging
services.AddVeracityGraphApi<DotNetLogger>();
// Configure authentication
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddVeracityAuthentication(Configuration)
.AddCookie();
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseVeracity();
app.UseAuthorization();
// Optional: Profile picture middleware
app.UseVeracityProfilePicture();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
4. Console Application Setup
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var services = new ServiceCollection()
.AddVeracity(configuration)
.AddVeracityClientCredentialsAuthentication(clientId,clientSecret)
.AddVeracityGraphApi()
.BuildServiceProvider();
using var scope = services.CreateScope();
var client = scope.ServiceProvider.GetRequiredService<IVeracityGraphClient>();
Quick Start Guide
Basic Usage
public class MyController : Controller
{
private readonly IVeracityGraphClient _client;
public MyController(IVeracityGraphClient client)
{
_client = client;
}
// Get tenant
public async Task<IActionResult> GetTenant(string tenantId)
{
var tenant = await _client.Tenants.GetTenant(tenantId);
return Ok(tenant);
}
// List users
public async Task<IActionResult> ListUsers(string tenantId)
{
var users = await _client.Users.FindUsers(tenantId, top: 25);
return Ok(users);
}
// Add license
public async Task<IActionResult> AddLicense(string tenantId, Guid userId)
{
var license = await _client.ThisApplication.AddLicense(
tenantId,
new LicenseRequest
{
EntityId = userId,
LicenseType = EntityTypes.profile,
AccessLevel = "reader"
});
return Ok(license);
}
}
Core Concepts
Tenants
Tenants provide isolation boundaries for organizations.
// Get tenant
var tenant = await _client.Tenants.GetTenant(tenantId);
// List tenants for your application
var tenants = await _client.Tenants.GetTenants(applicationId);
// Update tenant properties
var patch = tenant.MakeJsonPatch()
.AddOrUpdateProperty("customField", "value");
await patch.ExecutePatchTenantAsync();
Users
// Find user by email
var user = await _client.Users.GetUserByEmail(tenantId, "user@example.com");
// List users with OData
var users = await _client.Users.ListUsers(tenantId, new OdataRequest
{
Filter = "name eq 'John Doe'",
Top = 25,
Skip = 0
});
// Get user's groups
var groups = await _client.Users.GetGroupsForUser(tenantId, userId);
// Get user's applications
var apps = await _client.Users.GetApplicationsForUser(tenantId, userId);
Groups
// List groups
var groups = await _client.Groups.FindGroups(tenantId, top: 25);
// Get direct members
var members = await _client.Groups.GetGroupMembers(
tenantId,
groupId,
EntityTypes.profile);
// Get all members (including nested)
var allMembers = await _client.Groups.GetMembersWithInheritedMemberships(
tenantId,
groupId,
new Dictionary<string, string>());
// Check membership
var isMember = await _client.Groups.IsUserMemberOfGroup(
tenantId,
groupId,
userId);
Applications
// Get application
var app = await _client.ThisApplication.GetApplication(tenantId);
// Verify user license
var license = await _client.ThisApplication.VerifyUserLicense(tenantId, userId);
// Get all users with licenses
var users = await _client.ThisApplication.GetUsersWithInheritedAccess(tenantId);
// Add license
var newLicense = await _client.ThisApplication.AddLicense(
tenantId,
new LicenseRequest
{
EntityId = userId,
LicenseType = EntityTypes.profile
});
Elements
// Create element
var element = await _client.ThisApplicationElements.CreateElement(
tenantId,
new ElementRequest
{
Name = "My Workspace",
ElementExternalId = "ws-001",
ElementType = "Workspace",
Description = "Project workspace"
});
// Create child element
var child = await element.AddChildElement(new ElementRequest
{
Name = "Sub-workspace",
ElementExternalId = "ws-001-sub"
});
// Add rights
await element.AddRights(new ElementRightRequest
{
EntityId = userId,
LicenseType = EntityTypes.profile,
AccessLevel = "editor"
});
// Get user's elements
var userElements = await _client.ThisApplicationElements
.GetUserElements(tenantId, userId);
API Reference
IVeracityGraphClient
Main entry point for all operations.
Properties:
Tenants- ITenants ApiUsers- IUsersApiGroups- IGroupsApiApplications- IApplicationsApiElements- IElementsApiMe- IMeThisApplication- IThisApplicationThisApplicationElements- IThisApplicationElementsApplicationId- Guid?Prefix- stringLogger- LogAdapter
Methods:
string MakePropertyName(string name);
ExtensionProperty MakeExtensionProperty(string name, string value);
PropertyPatchDocument<T> MakeJsonPatch<T>(T obj, string name, string value);
ITenantsApi
Task<TenantResponse> GetTenant(string tenantId);
Task<ListEx<TenantResponse>> GetTenants(string applicationId);
Task<TenantResponse> PatchTenant(string tenantId, JsonPatchDocument<TenantResponse> body);
Task<UserRoles> GetAdmin(string tenantId, Guid userId);
Task<ListEx<UserRoles>> GetAdmins(string tenantId);
IUsersApi
Task<UserDetailsResponse> GetUserByEmail(string tenantId, string email);
Task<GlobalUserDetailsResponse> GetUser(Guid userId);
Task<PagedList<UserResponse>> ListUsers(string tenantId, Dictionary<string, string> odata);
Task<UserDetailsResponse> GetUserInTenant(string tenantId, Guid userId);
Task<GroupResponse[]> GetGroupsForUser(string tenantId, Guid userId);
Task<ListEx<ApplicationLicenseResponse>> GetApplicationsForUser(string tenantId, Guid userId);
Task<UserDetailsResponse> PatchUser(string tenantId, Guid userId, JsonPatchDocument<UserDetailsResponse> patchOps);
IGroupsApi
Task<PagedList<GroupResponse>> GetGroups(string tenantId, Dictionary<string, string> odata);
Task<GroupResponse> GetGroup(string tenantId, Guid groupId);
Task<ListEx<MemberResponse>> GetGroupMembers(string tenantId, Guid groupId, EntityTypes? memberType);
Task<ListEx<UserResponse>> GetMembersWithInheritedMemberships(string tenantId, Guid groupId, Dictionary<string, string> odata);
Task<IsMemberResponse> IsUserMemberOfGroup(string tenantId, Guid groupId, Guid userId);
Task<GroupResponse> PatchGroup(string tenantId, Guid groupId, JsonPatchDocument<GroupResponse> patchOps);
IApplicationsApi
Task<ApplicationResponse> GetApplication(string tenantId, Guid applicationId);
Task<ListEx<LicenseResponse>> GetLicenses(string tenantId, Guid applicationId, EntityTypes? licenseType);
Task<LicenseResponse> VerifyUserLicense(string tenantId, Guid applicationId, Guid userId);
Task<ListEx<UserLicenseResponse>> GetUsersWithInheritedAccess(string tenantId, Guid applicationId);
Task<LicenseResponse> AddLicense(string tenantId, Guid applicationId, LicenseRequest subscription);
Task<LicenseResponse> SetAccessLevel(string tenantId, Guid applicationId, Guid entityId, EntityTypes? licenseType, string accessLevel);
Task DeleteLicense(string tenantId, Guid applicationId, Guid entityId, EntityTypes? licenseType);
Task<ApplicationResponse> PatchApplication(string tenantId, Guid applicationId, JsonPatchDocument<ApplicationResponse> patchOps);
IElementsApi
Task<PagedList<ElementResponse>> ListElements(string tenantId, Guid applicationId);
Task<ElementResponse> GetElement(string tenantId, Guid applicationId, string elementId);
Task<ElementResponse> CreateElement(string tenantId, Guid applicationId, ElementRequest body);
Task<ElementResponse> CreateChildElement(string tenantId, Guid applicationId, string elementId, ElementRequest body);
Task<ElementResponse> PatchElement(string tenantId, Guid applicationId, string elementId, JsonPatchDocument<ElementResponse> patchDoc);
Task DeleteElement(string tenantId, Guid applicationId, string elementId);
Task<List<ElementRightResponse>> GetElementRights(string tenantId, Guid applicationId, string elementId);
Task<ElementRightResponse> AddElementRights(string tenantId, Guid applicationId, string elementId, ElementRightRequest body);
Task<List<ElementRightTreeResponse>> GetUserElements(string tenantId, Guid applicationId, Guid userId);
Advanced Features
Custom Typed Responses
Create strongly-typed models:
public class MyTenant : TypedTenantBase
{
public List<string> VesselList
{
get => GetValue<List<string>>();
set => SetValue(value);
}
public string Department
{
get => GetValue<string>();
set => SetValue(value);
}
}
// Usage
var typedTenant = await _client.Tenants
.GetTenant(tenantId)
.ToTyped<MyTenant>();
Console.WriteLine(typedTenant.Department);
OData Queries
var query = new OdataRequest
{
Filter = "name eq 'John Doe'",
Search = "engineer",
OrderBy = new[]
{
new OrderingElement { Field = "name", Type = OrderTypes.Ascending }
},
Top = 25,
Skip = 0
};
var users = await _client.Users.ListUsers(tenantId, query);
// Pagination
if (users.NextPageUrl != null)
{
var nextPage = await users.GetNextPage();
}
Extension Properties
// Add/update
var patch = user.MakeJsonPatch()
.AddOrUpdateProperty("customField", "value")
.AddOrUpdateProperty("listField", new List<string> { "a", "b" });
await patch.ExecutePatchUserAsync();
// Remove
var patch = user.MakeJsonPatch()
.RemoveProperty("customField");
await patch.ExecutePatchUserAsync();
// Read
var value = user.GetPropertyValue<string>("customField");
Authorization Attribute
// Basic
[VeracityAuthorization]
public async Task<IActionResult> MyAction(string tenant_id)
{
// User has valid license
}
// With access levels
[VeracityAuthorization("admin", "editor")]
public async Task<IActionResult> AdminAction(string tenant_id)
{
// User has admin OR editor access
}
// Custom configuration
[VeracityAuthorization(
TenantIdIn = IdCarrierTypes.Path,
TenantIdKey = "tenant_id",
CacheWindowSizeInMinutes = 5)]
[HttpGet("api/tenants/{tenant_id}/data")]
public async Task<IActionResult> GetData(string tenant_id)
{
// Protected endpoint
}
Profile Picture Middleware
// Configure
app.UseVeracityProfilePicture(
generateInitialsAvatar: true,
background: Color.DarkBlue,
text: Color.White);
// Use in views
<img src="@user.ProfilePictureUrl" alt="Profile" />
// Programmatic
var imageBytes = await user.GetProfileImage();
Authentication
Authorization Code Flow (Web Apps)
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddVeracityAuthentication(Configuration)
.AddCookie();
Client Credentials Flow (Daemons)
var clientSecret = new SecureString();
foreach (var c in Environment.GetEnvironmentVariable("CLIENT_SECRET"))
{
clientSecret.AppendChar(c);
}
services.AddVeracityClientCredentialsAuthentication(
"your-client-id",
clientSecret);
// Update scope to:
// "https://dnvglb2cprod.onmicrosoft.com/83054ebf-1d7b-43f5-82ad-b2bde84d7b75/.default"
Error Handling
try
{
var user = await _client.Users.GetUserByEmail(tenantId, email);
}
catch (ServerException ex)
{
var error = ex.GetErrorData<ErrorDetail>();
_logger.LogError(ex,
"API error. Correlation ID: {CorrelationId}",
error.CorrelationId);
return StatusCode((int)ex.Status, new
{
message = error.Message,
correlationId = error.CorrelationId
});
}
Best Practices
1. Caching
services.AddDistributedMemoryCache();
// or
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration["Redis:Connection"];
});
2. Logging
public class MyLogger : LogAdapter
{
private readonly ILogger<MyLogger> _logger;
public MyLogger(ILogger<MyLogger> logger)
{
_logger = logger;
}
protected override void LogMessageInternal(string message, string memberName, int? lineNumber, string filePath)
{
_logger.LogInformation("{MemberName} - {Message}", memberName, message);
}
public override void LogError(Exception exception)
{
_logger.LogError(exception, "Veracity API error");
}
}
services.AddVeracityGraphApi<MyLogger>();
3. Pagination
var allUsers = new List<UserResponse>();
var query = new OdataRequest { Top = 100 };
PagedList<UserResponse> page;
do
{
page = await _client.Users.ListUsers(tenantId, query);
allUsers.AddRange(page.Items);
if (page.NextPageUrl != null)
page = await page.GetNextPage();
else
break;
} while (page != null);
4. Bulk Operations
// Good: Batch
var users = await _client.Users.ResolveUsers(tenantId, userIds);
// Bad: Loop
foreach (var userId in userIds)
{
var user = await _client.Users.GetUserInTenant(tenantId, userId);
}
Examples
Complete CRUD Example
public class TenantController : Controller
{
private readonly IVeracityGraphClient _client;
public TenantController(IVeracityGraphClient client)
{
_client = client;
}
[VeracityAuthorization]
[HttpGet("api/tenants/{tenantId}")]
public async Task<IActionResult> Get(string tenantId)
{
try
{
var tenant = await _client.Tenants.GetTenant(tenantId);
return Ok(tenant);
}
catch (ServerException ex) when (ex.Status == HttpStatusCode.NotFound)
{
return NotFound();
}
}
[VeracityAuthorization("admin")]
[HttpPatch("api/tenants/{tenantId}")]
public async Task<IActionResult> Update(string tenantId, [FromBody] Dictionary<string, string> properties)
{
var tenant = await _client.Tenants.GetTenant(tenantId);
var patch = tenant.MakeJsonPatch();
foreach (var prop in properties)
{
patch.AddOrUpdateProperty(prop.Key, prop.Value);
}
var updated = await patch.ExecutePatchTenantAsync();
return Ok(updated);
}
[VeracityAuthorization]
[HttpGet("api/tenants/{tenantId}/users")]
public async Task<IActionResult> ListUsers(
string tenantId,
[FromQuery] string search,
[FromQuery] int top = 25,
[FromQuery] int skip = 0)
{
var users = await _client.Users.FindUsers(
tenantId,
search: search,
top: top,
skip: skip);
return Ok(users);
}
[VeracityAuthorization("admin")]
[HttpPost("api/tenants/{tenantId}/licenses")]
public async Task<IActionResult> AddLicense(
string tenantId,
[FromBody] LicenseRequest request)
{
var license = await _client.ThisApplication.AddLicense(tenantId, request);
return Created($"/api/licenses/{license.Id}", license);
}
}
Additional Resources
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net6.0
- Microsoft.AspNetCore.JsonPatch (>= 6.0.33)
- Stardust.Interstellar.Rest (>= 5.6.1)
- Stardust.Interstellar.Rest.Annotations (>= 5.6.1)
- Swashbuckle.AspNetCore.Annotations (>= 6.7.3)
- System.Drawing.Common (>= 6.0.0)
- Veracity.Common.Authentication.Abstractions (>= 3.6.1)
- Veracity.Common.Authentication.AspNetCore (>= 3.6.5.2)
-
net7.0
- Microsoft.AspNetCore.JsonPatch (>= 7.0.20)
- Stardust.Interstellar.Rest (>= 5.6.1)
- Stardust.Interstellar.Rest.Annotations (>= 5.6.1)
- Swashbuckle.AspNetCore.Annotations (>= 6.7.3)
- System.Drawing.Common (>= 7.0.0)
- Veracity.Common.Authentication.Abstractions (>= 3.6.1)
- Veracity.Common.Authentication.AspNetCore (>= 3.6.5.2)
-
net8.0
- Microsoft.AspNetCore.JsonPatch (>= 8.0.8)
- Stardust.Interstellar.Rest (>= 5.6.1)
- Stardust.Interstellar.Rest.Annotations (>= 5.6.1)
- Swashbuckle.AspNetCore.Annotations (>= 6.7.3)
- System.Drawing.Common (>= 8.0.8)
- Veracity.Common.Authentication.Abstractions (>= 3.6.1)
- Veracity.Common.Authentication.AspNetCore (>= 3.6.5.2)
-
net9.0
- Microsoft.AspNetCore.JsonPatch (>= 9.0.0)
- Stardust.Interstellar.Rest (>= 5.6.1)
- Stardust.Interstellar.Rest.Annotations (>= 5.6.1)
- Swashbuckle.AspNetCore.Annotations (>= 6.7.3)
- System.Drawing.Common (>= 9.0.0)
- Veracity.Common.Authentication.Abstractions (>= 3.6.1)
- Veracity.Common.Authentication.AspNetCore (>= 3.6.5.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Veracity.Core.Api.V4:
| Package | Downloads |
|---|---|
|
Veracity.Core.Api.V4.Privileged
SDK for accessing Veracity Tenant Management Privileged API. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.20251203.3 | 696 | 12/3/2025 |
| 1.0.20251202.10 | 681 | 12/2/2025 |
| 1.0.20251202.9 | 689 | 12/2/2025 |
| 1.0.20241120.7 | 237 | 11/20/2024 |