API Reference

Complete API reference for the VECU Custody SDK for .NET (v1.2.0).

SDK-Only Access

To ensure your integration remains stable and supported, always use the official SDKs. The underlying API endpoints are internal implementation details that may change in purpose, functionality, or be removed at any time without notice. Direct API access is not supported. Learn more →

The SDK methods documented here are your supported interface. Versioning is managed through SDK upgrades.

Client Interface

All API methods are accessible through the ICustodyServiceClient interface, which can be injected into your services via dependency injection:

public class VehicleService
{
    private readonly ICustodyServiceClient _custodyClient;

    public VehicleService(ICustodyServiceClient custodyClient)
    {
        _custodyClient = custodyClient;
    }

    public async Task ProcessVehicle(string vin)
    {
        // Use _custodyClient methods
        var result = await _custodyClient.GetReleasabilityAsync(
            vin,
            "1 Auction Blvd, Bordentown, NJ 08505");
    }
}

API Resources

Custody Permits4 methods
Releasability2 methods

Query and update vehicle releasability status - GetReleasabilityAsync()

UpdateReleasabilityAsync()

Release1 method

Record vehicle releases from custody - ReleaseVehicleAsync()

Removed in 3.0.0: Transfers API

The RecordTransferAsync, GetCustodyStatusAsync, and GetCustodyChainAsync methods have been removed from the SDK as of v3.0.0. The underlying server routes (POST /v1/transfers, GET /v1/transfers/status/{vin}, GET /v1/transfers/history/{vin}) were taken offline on 2026-04-14 by the server team pending Broken Object-Level Authorization controls (OWASP API1:2023). These methods will be re-introduced in a future minor release once the server restores the routes with per-object authorization scopes. Track progress at vecu-custody-service#208. See the Changelog for the full migration note.

Audit API Coming Soon

The Audit API (audit trails for custody operations) is planned for a future release.

Common Patterns

Async/Await

All API methods are asynchronous and return Task<T>:

// Always use await with API calls
var auth = await client.CreateAuthorizationAsync(request);

// Don't block on async methods
// ❌ Bad: var auth = client.CreateAuthorizationAsync(request).Result;
// ✅ Good: var auth = await client.CreateAuthorizationAsync(request);

CancellationToken Support

All methods accept an optional CancellationToken for cancellation support:

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

try
{
    var result = await client.GetReleasabilityAsync(vin, origin, cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Request cancelled or timed out");
}

Error Handling

The SDK throws typed exceptions for different error scenarios:

using CoxAuto.Vecu.CustodySdk.Exceptions;

try
{
    var auth = await client.CreateAuthorizationAsync(request);
}
catch (ValidationException ex)
{
    // Invalid request parameters (400, 422)
    Console.WriteLine($"Validation error: {ex.Message}");
}
catch (AuthException ex)
{
    // Authentication failure (401)
    Console.WriteLine($"Auth error: {ex.Message}");
}
catch (DuplicateAuthorizationException ex)
{
    // Authorization already exists (409)
    Console.WriteLine($"Duplicate: {ex.Message}");
}
catch (AuthorizationNotFoundException ex)
{
    // Authorization not found (404)
    Console.WriteLine($"Not found: {ex.Message}");
}
catch (RateLimitException ex)
{
    // Rate limit exceeded (429)
    Console.WriteLine($"Rate limited. Retry after: {ex.RetryAfter}");
}
catch (NetworkException ex)
{
    // Network or server errors (5xx)
    Console.WriteLine($"Network error: {ex.Message}");
}

VIN Format

All methods accepting VINs expect standard 17-character Vehicle Identification Numbers:

  • Length: Exactly 17 alphanumeric characters
  • Excluded Characters: I, O, Q (to avoid confusion with 1, 0)
  • Example: 1HGBH41JXMN109186
// Valid VINs
"1HGBH41JXMN109186"
"9HGBH41JXMN999999"

// Invalid VINs
"1HGBH41JXMN10918"    // Too short (16 characters)
"1HGBH41JXMN1091866"  // Too long (18 characters)
"1HGBH41JXMN10918O"   // Contains 'O' (excluded character)

DateTime Handling

All timestamp fields use DateTimeOffset with ISO 8601 format:

var auth = await client.CreateAuthorizationAsync(request);

// Timestamps are DateTimeOffset
Console.WriteLine($"Created: {auth.CreatedAt:O}");  // ISO 8601 format

// Convert to local time
var localCreated = auth.CreatedAt.ToLocalTime();

Authentication

All environments use the same TokenProvider callback model. You provide a callback that returns a bearer token (e.g., a CIP token), and the SDK exchanges it for a VECU service token internally. The VECU token is cached as a singleton across all requests and refreshed automatically.

services.AddCustodyClient(options =>
{
    options.Environment = CustodyEnvironment.Sandbox;
    options.TokenProvider = async (cancellationToken) =>
    {
        var token = await myAuthClient.GetTokenAsync(cancellationToken);
        return token.AccessToken;
    };
});

The SDK calls your TokenProvider on the first request, when the cached token expires (5-minute buffer), if the token exchange endpoint rejects the client token (401/410), or if the Custody API itself returns 401. In all cases, the SDK handles retry automatically — you do not need to manage token lifecycle.

See Configuration for the full token exchange flow and options.

Dependency Injection

Register the client in your DI container:

// Program.cs or Startup.cs
builder.Services.AddCustodyClient(options =>
{
    options.Environment = CustodyEnvironment.Sandbox;
    options.TokenProvider = async (ct) => await myAuthClient.GetTokenAsync(ct);
});

// Inject into services
public class MyService
{
    private readonly ICustodyServiceClient _client;

    public MyService(ICustodyServiceClient client)
    {
        _client = client;
    }
}

Next Steps