Veracity.Core.Api.V4
1.0.20260320.8
Prefix Reserved
dotnet add package Veracity.Core.Api.V4 --version 1.0.20260320.8
NuGet\Install-Package Veracity.Core.Api.V4 -Version 1.0.20260320.8
<PackageReference Include="Veracity.Core.Api.V4" Version="1.0.20260320.8" />
<PackageVersion Include="Veracity.Core.Api.V4" Version="1.0.20260320.8" />
<PackageReference Include="Veracity.Core.Api.V4" />
paket add Veracity.Core.Api.V4 --version 1.0.20260320.8
#r "nuget: Veracity.Core.Api.V4, 1.0.20260320.8"
#:package Veracity.Core.Api.V4@1.0.20260320.8
#addin nuget:?package=Veracity.Core.Api.V4&version=1.0.20260320.8
#tool nuget:?package=Veracity.Core.Api.V4&version=1.0.20260320.8
Veracity.Core.Api.V4 Documentation
Welcome to the Veracity Platform Graph API SDK for .NET! This comprehensive package enables seamless integration with Veracity's identity and resource management system.
Quick Links
- Comprehensive Guide - Full documentation with examples
- Developer Portal - Register your application
- Veracity Platform - Learn about Veracity
- GitHub Repository - Base authentication library
What's New in V4
- ? Tenant-centric architecture - All operations organized by tenant
- ?? Fine-grained permissions - Element-level access control
- ?? Element management - Hierarchical resource structures
- ?? Type-safe responses - Strongly-typed extension properties
- ?? Enhanced authorization - Built-in attribute-based protection
- ?? Multi-framework - .NET 6, 7, 8, and 9 support
Installation
dotnet add package Veracity.Core.Api.V4
Quick Setup
1. Configure appsettings.json
{
"Veracity": {
"veracityGraphBaseUrl": "https://api.veracity.com/apiv4/v1",
"applicationPrefix": "myapp",
"serviceId": "your-application-id-from-developer",
"clientId": "your-client-id",
"clientSecret": "your-client-secret",
"subscriptionKey": "your-subscription-key",
"azureAdB2C": {
"instance": "https://login.microsoftonline.com/tfp/",
"domain": "dnvglb2cprod.onmicrosoft.com",
"policy": "B2C_1A_SignInWithADFSIdp",
"clientId": "your-client-id",
"callbackPath": "/signin-oidc",
"scopes": "https://dnvglb2cprod.onmicrosoft.com/83054ebf-1d7b-43f5-82ad-b2bde84d7b75/user_impersonation"
}
}
}
2. Configure Services (Startup.cs)
public void ConfigureServices(IServiceCollection services)
{
// Add Veracity authentication
services.AddVeracity(Configuration);
// Add Veracity Graph API
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: Add profile picture middleware
app.UseVeracityProfilePicture();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
3. Use in Your Code
public class MyController : Controller
{
private readonly IVeracityGraphClient _veracityClient;
public MyController(IVeracityGraphClient veracityClient)
{
_veracityClient = veracityClient;
}
[VeracityAuthorization]
[HttpGet("api/tenants/{tenant_id}/users")]
public async Task<IActionResult> ListUsers(string tenant_id)
{
var users = await _veracityClient.Users.FindUsers(
tenant_id,
top: 25,
skip: 0);
return Ok(users);
}
[VeracityAuthorization("admin", "editor")]
[HttpPost("api/tenants/{tenant_id}/licenses")]
public async Task<IActionResult> AddLicense(
string tenant_id,
[FromBody] Guid userId)
{
var license = await _veracityClient.ThisApplication.AddLicense(
tenant_id,
new LicenseRequest
{
EntityId = userId,
LicenseType = EntityTypes.profile,
AccessLevel = "editor"
});
return Ok(license);
}
}
Key Features
Tenant Management
// Get tenant information
var tenant = await _veracityClient.Tenants.GetTenant(tenantId);
// List all tenants for your application
var tenants = await _veracityClient.Tenants.GetTenants(applicationId);
// Update tenant properties
var patch = tenant.MakeJsonPatch()
.AddOrUpdateProperty("customField", "value");
await patch.ExecutePatchTenantAsync();
User Management
// Find user by email
var user = await _veracityClient.Users.GetUserByEmail(tenantId, "user@example.com");
// List users with fluent query builder (recommended)
var users = await _veracityClient.Users.Query(tenantId)
.Filter(u => u.Name == "John Doe")
.Or(u => u.Name == "Jane Doe")
.And(u => u.IsLocked == false)
.Search("engineer")
.Top(25)
.ExecuteAsync();
// Get user's groups and applications
var groups = await _veracityClient.Users.GetGroupsForUser(tenantId, userId);
var apps = await _veracityClient.Users.GetApplicationsForUser(tenantId, userId);
Group Management
// List groups with query builder
var groups = await _veracityClient.Groups.Query(tenantId)
.Filter(g => g.Name == "Administrators")
.Or(g => g.Name == "Editors")
.Top(25)
.ExecuteAsync();
// Get group members (including nested)
var allMembers = await _veracityClient.Groups.GetMembersWithInheritedMemberships(
tenantId,
groupId,
new Dictionary<string, string>());
// Check if user is member
var isMember = await _veracityClient.Groups.IsUserMemberOfGroup(
tenantId,
groupId,
userId);
Application & License Management
// Get application details
var app = await _veracityClient.ThisApplication.GetApplication(tenantId);
// Verify user has license
var license = await _veracityClient.ThisApplication.VerifyUserLicense(
tenantId,
userId);
// Get all users with licenses (including inherited from groups)
var users = await _veracityClient.ThisApplication.GetUsersWithInheritedAccess(
tenantId);
// Add license to user
var newLicense = await _veracityClient.ThisApplication.AddLicense(
tenantId,
new LicenseRequest
{
EntityId = userId,
LicenseType = EntityTypes.profile,
AccessLevel = "reader"
});
Element Management (Application-Specific Resources)
// Create a root element (e.g., workspace, vessel, project)
var element = await _veracityClient.ThisApplicationElements.CreateElement(
tenantId,
new ElementRequest
{
Name = "My Workspace",
ElementExternalId = "ws-001",
ElementType = "Workspace",
Description = "Main project workspace",
ElementTypeIconUrl = new Uri("https://cdn.example.com/icon.png")
});
// Create child element
var child = await element.AddChildElement(new ElementRequest
{
Name = "Sub-workspace",
ElementExternalId = "ws-001-sub",
ElementType = "Workspace"
});
// Grant user access to element
await element.AddRights(new ElementRightRequest
{
EntityId = userId,
LicenseType = EntityTypes.profile,
AccessLevel = "editor"
});
// Get all elements user has access to
var userElements = await _veracityClient.ThisApplicationElements
.GetUserElements(tenantId, userId);
Custom Typed Responses
Create strongly-typed models for your extension properties:
// Define your typed model
public class MyTenant : TypedTenantBase
{
public List<string> VesselList
{
get => GetValue<List<string>>();
set => SetValue(value);
}
public string Department
{
get => GetValue<string>();
set => SetValue(value);
}
// Access properties from other applications
public List<string> ManagementCompanies =>
GetExternalValue<List<string>>("vtmd2");
}
// Convert response to typed version
var typedTenant = await _veracityClient.Tenants
.GetTenant(tenantId)
.ToTyped<MyTenant>();
Console.WriteLine($"Department: {typedTenant.Department}");
Console.WriteLine($"Vessels: {string.Join(", ", typedTenant.VesselList)}");
Supported Base Types:
TypedTenantBaseTypedUserBaseTypedGroupBaseTypedApplicationBaseTypedLicenseBaseTypedMemberBaseTypedElementBase
Authorization Attribute
Protect your endpoints with built-in license verification:
// Basic authorization - verify user has valid license
[VeracityAuthorization]
public async Task<IActionResult> MyAction(string tenant_id)
{
// User has a valid license
}
// Require specific access levels
[VeracityAuthorization("admin", "editor")]
public async Task<IActionResult> AdminAction(string tenant_id)
{
// User has admin OR editor access level
}
// Configure tenant ID location
[VeracityAuthorization(
TenantIdIn = IdCarrierTypes.Path,
TenantIdKey = "tenant_id",
CacheWindowSizeInMinutes = 5)]
[HttpGet("api/tenants/{tenant_id}/data")]
public async Task<IActionResult> GetData(string tenant_id)
{
// Tenant ID extracted from path parameter
}
// Element-level authorization
[VeracityAuthorization(
ElementIdIn = IdCarrierTypes.Path,
ElementIdKey = "elementId",
AccessLevels = new[] { "editor", "owner" })]
[HttpPost("api/elements/{elementId}/data")]
public async Task<IActionResult> UpdateElement(string elementId)
{
// User has editor or owner rights on the element
}
Profile Picture Middleware
Display user profile pictures in your web application:
// Configure in Startup.cs
app.UseVeracityProfilePicture(
generateInitialsAvatar: true,
background: Color.DarkBlue,
text: Color.White);
// Use in Razor views
<img src="@user.ProfilePictureUrl" alt="@user.Name" />
// Or get programmatically
var imageBytes = await user.GetProfileImage();
If a user doesn't have a profile picture, the middleware automatically generates an initials-based avatar.
OData Queries
Fluent Query Builder (Recommended)
Use the fluent query builder for type-safe, readable queries:
// Simple filter
var users = await _veracityClient.Users.Query(tenantId)
.Filter(u => u.Name == "John Doe")
.Top(25)
.ExecuteAsync();
// Complex filter with OR and AND combinations
var users = await _veracityClient.Users.Query(tenantId)
.Filter("tenantId eq 'abc'") // Initiates filter
.And(u => u.Name == "John") // Commits previous, starts new AND group
.Or(u => u.Name == "Jane") // Adds OR to current group
.Or(u => u.Name == "Bob") // Adds OR to current group
.And(u => u.IsLocked == false) // Commits OR group, adds new AND clause
.Top(50)
.OrderBy(u => u.Name)
.ExecuteAsync();
// Produces: tenantId eq 'abc' and (name eq 'John' or name eq 'Jane' or name eq 'Bob') and isLocked eq false
// Search with filters
var users = await _veracityClient.Users.Query(tenantId)
.Search("engineer")
.Filter(u => u.IsLocked == false)
.Top(25)
.Skip(0)
.OrderByDescending(u => u.Name)
.Select(u => u.Name)
.Select(u => u.Email)
.ExecuteAsync();
// Pagination support
if (users.NextPageUrl != null)
{
var nextPage = await users.GetNextPage();
}
Query Builder Pattern:
Filter()- Initiates the filter (only use once at the start)And()- Commits current group and starts a new AND clauseOr()- Adds an OR condition to the current groupTop(),Skip()- PaginationOrderBy(),OrderByDescending()- SortingSearch()- Free-text searchSelect()- Field projection
Raw OData Queries
For advanced scenarios, you can use raw OData queries:
var query = new OdataRequest
{
Filter = "name eq 'John Doe' and email ne 'test@example.com'",
Search = "engineer",
OrderBy = new[]
{
new OrderingElement { Field = "name", Type = OrderTypes.Ascending }
},
Top = 25,
Skip = 0,
Select = new[] { "name", "email", "userId" }
};
var users = await _veracityClient.Users.ListUsers(tenantId, query);
Supported OData Operators:
- Comparison:
eq,ne,gt,lt,ge,le - Logical:
and,or,not - String: ("search.ismatch('hn', 'name'),("search.ismatch('hn', 'name'), ("search.ismatch('hn', 'name'), ("search.ismatch('hn', 'name')
Extension Properties
Manage custom metadata on any entity:
// Add or update properties
var patch = user.MakeJsonPatch()
.AddOrUpdateProperty("customField", "value")
.AddOrUpdateProperty("tags", new List<string> { "tag1", "tag2" });
await patch.ExecutePatchUserAsync();
// Remove property
var patch = user.MakeJsonPatch()
.RemoveProperty("customField");
await patch.ExecutePatchUserAsync();
// Read property
var value = user.GetPropertyValue<string>("customField");
// Read property from another application
var externalValue = user.GetPropertyValue<string>("otherapp", "propertyName");
Properties are automatically prefixed with your application prefix (configured in appsettings.json).
Authentication Modes
Authorization Code Flow (Web Applications)
Default mode for interactive user applications:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddVeracityAuthentication(Configuration)
.AddCookie();
Client Credentials Flow (Daemon Applications)
For service-to-service communication:
services.AddVeracityClientCredentialsAuthentication(
clientId: "your-client-id",
clientSecret: secureClientSecret);
Note: Update the scope in configuration to:
{
"Veracity": {
"azureAdB2C": {
"scopes": "https://dnvglb2cprod.onmicrosoft.com/83054ebf-1d7b-43f5-82ad-b2bde84d7b75/.default"
}
}
}
Error Handling
All API operations throw ServerException with detailed error information:
try
{
var user = await _veracityClient.Users.GetUserByEmail(tenantId, email);
}
catch (ServerException ex)
{
var error = ex.GetErrorData<ErrorDetail>();
Console.WriteLine($"Error: {error.Message}");
Console.WriteLine($"Correlation ID: {error.CorrelationId}");
Console.WriteLine($"Support Code: {error.SupportCode}");
Console.WriteLine($"HTTP Status: {ex.Status}");
// Log for support
_logger.LogError(ex,
"API error - Correlation ID: {CorrelationId}",
error.CorrelationId);
}
Common Status Codes:
200 OK- Success400 Bad Request- Invalid parameters401 Unauthorized- Authentication failure403 Forbidden- Insufficient permissions404 Not Found- Resource doesn't exist409 Conflict- Resource conflict500 Internal Server Error- Server error
API Interfaces
Main Interfaces
IVeracityGraphClient- Main entry pointTenants- Tenant operationsUsers- User operationsGroups- Group operationsApplications- Application and license operationsElements- Element operationsMe- Current user operationsThisApplication- Quick access to your configured applicationThisApplicationElements- Quick access to your application's elements
Key Operations by Interface
ITenantsApi
- GetTenant, GetTenants, PatchTenant
- GetAdmin, GetAdmins
- GetUsersAndGroups
IUsersApi
- GetUserByEmail, GetUser, GetUserInTenant
- ListUsers, ResolveUsers
- GetGroupsForUser, GetApplicationsForUser, GetTenantsForUser
- PatchUser
IGroupsApi
- GetGroups, GetGroup
- GetGroupMembers, GetMembersWithInheritedMemberships
- IsUserMemberOfGroup, GetMemberOf
- GetApplications, PatchGroup, PatchMember
IApplicationsApi
- GetApplications, GetApplication
- GetLicenses, VerifyUserLicense, GetUsersWithInheritedAccess
- AddLicense, SetAccessLevel, UpdateLicense, DeleteLicense
- GetAdministrators, PatchApplication
IElementsApi
- ListElements, ListChildElements, GetElementTree
- GetElement, CreateElement, CreateChildElement
- PatchElement, DeleteElement
- GetElementRights, AddElementRights, UpdateElementRights, DeleteElementRights
- GetUserElements, GetUserElement
IMe
- GetMyInfo, GetMyApplications, GetMyTenantApplications
- GetMyGroups, GetMyTenants, GetMyTenantsWithApplication
- VerifyUserPolicy
Migration from V3 API
If you're migrating from the V3 API:
Configuration Changes
V3:
services.AddVeracityServices(myApiV3Url);
V4:
services.AddVeracityGraphApi(veracityGraphBaseUrl);
API Changes
V4 uses a tenant-centric approach. All operations now require a tenant context:
V3:
var services = await _my.Services(new UserAndServiceQuery { userId });
V4:
var apps = await _veracityClient.Users.GetApplicationsForUser(tenantId, userId);
Profile Picture
V3: Manual implementation required
V4: Built-in middleware
app.UseVeracityProfilePicture();
Console Application Example
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Veracity.Core.Api.V4;
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var clientSecret = new SecureString();
foreach (var c in Environment.GetEnvironmentVariable("CLIENT_SECRET"))
{
clientSecret.AppendChar(c);
}
var services = new ServiceCollection()
.AddVeracity(configuration)
.AddVeracityClientCredentialsAuthentication(
"your-client-id",
clientSecret)
.AddVeracityGraphApi()
.BuildServiceProvider();
using var scope = services.CreateScope();
var client = scope.ServiceProvider.GetRequiredService<IVeracityGraphClient>();
// Use the client
var users = await client.Users.ListUsers(
"tenant-id",
new Dictionary<string, string>());
Console.WriteLine($"Found {users.Items.Length} users");
Best Practices
- Use Distributed Caching - Configure Redis or memory cache for better performance
- Implement Custom Logging - Extend
LogAdapterfor your logging infrastructure - Handle Pagination - Use
GetNextPage()for large result sets - Use Batch Operations - Prefer
ResolveUsers()over loops - Proper Extension Property Naming - Use
MakePropertyName()for consistency - Error Handling - Always catch
ServerExceptionand log correlation IDs - Access Level Validation - Check if application supports access levels before setting them
- Don't Dispose Manually - Let IoC container manage
IVeracityGraphClientlifetime
Support and Resources
Documentation
- Developer Portal - Application registration and management
- API Reference - Complete API documentation
Getting Help
- Technical Issues: Contact Veracity Support with the Correlation ID from error responses
- Integration Questions: Consult the developer portal
- Feature Requests: Contact your Veracity representative
Sample Code
- Review the
WebApplicationNet7project for ASP.NET Core examples - Check
CCTestAppfor console application patterns - See
WebApplicationNet7/Controllers/TestApi.csfor API usage examples
Version History
v4.2.0 (Current)
- Client credentials flow support
- Multi-framework targeting (.NET 6, 7, 8, 9)
- Enhanced element hierarchy management
- Improved error handling and logging
v4.1.0
- Custom typed response support
- Enhanced OData query support
- Profile picture middleware
- Improved caching strategies
v4.0.0
- Initial V4 release
- Tenant-centric architecture
- Element management
- Enhanced access control
- Server-sent events
License
This SDK is provided by DNV and is subject to the terms and conditions of your Veracity Platform agreement.
Ready to get started? Check out the Comprehensive Guide for detailed documentation and examples!
| 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 is compatible. 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. |
-
net10.0
- Microsoft.AspNetCore.JsonPatch (>= 10.0.1)
- Stardust.Interstellar.Rest (>= 5.7.2)
- Stardust.Interstellar.Rest.Annotations (>= 5.7.1)
- Swashbuckle.AspNetCore.Annotations (>= 6.7.3)
- System.Drawing.Common (>= 10.0.0)
- Veracity.Common.Authentication.Abstractions (>= 3.6.1)
- Veracity.Common.Authentication.AspNetCore (>= 3.6.5.2)
-
net6.0
- Microsoft.AspNetCore.JsonPatch (>= 6.0.33)
- Stardust.Interstellar.Rest (>= 5.7.2)
- Stardust.Interstellar.Rest.Annotations (>= 5.7.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.7.2)
- Stardust.Interstellar.Rest.Annotations (>= 5.7.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.7.2)
- Stardust.Interstellar.Rest.Annotations (>= 5.7.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.7.2)
- Stardust.Interstellar.Rest.Annotations (>= 5.7.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.20260320.8 | 104 | 3/20/2026 |
| 1.0.20251203.3 | 728 | 12/3/2025 |
| 1.0.20251202.10 | 700 | 12/2/2025 |
| 1.0.20251202.9 | 709 | 12/2/2025 |
| 1.0.20241120.7 | 265 | 11/20/2024 |