PayVelix.Contracts 1.1.0

dotnet add package PayVelix.Contracts --version 1.1.0
                    
NuGet\Install-Package PayVelix.Contracts -Version 1.1.0
                    
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="PayVelix.Contracts" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PayVelix.Contracts" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="PayVelix.Contracts" />
                    
Project file
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 PayVelix.Contracts --version 1.1.0
                    
#r "nuget: PayVelix.Contracts, 1.1.0"
                    
#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 PayVelix.Contracts@1.1.0
                    
#: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=PayVelix.Contracts&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=PayVelix.Contracts&version=1.1.0
                    
Install as a Cake Tool

PayVelix Client

Build PayVelix NuGet PayVelix.Contracts NuGet

PayVelix Client is a .NET 8 SDK for integrating applications with the PayVelix payment API. It provides typed clients for payments and balances, works with IHttpClientFactory, and supports both single-tenant and multi-tenant applications.

Installation

dotnet add package PayVelix --version 1.1.0

The shared contract package is published separately for applications that only need DTOs and exceptions:

dotnet add package PayVelix.Contracts --version 1.1.0

Requirements:

  • .NET SDK 8.0 or later
  • A valid PayVelix merchant API key

Single-Tenant Configuration

Use the standard registration when the application uses one PayVelix merchant account:

using PayVelix.DependencyInjection;

builder.Services.AddPayVelix(options =>
{
    options.ApiKey = builder.Configuration["PayVelix:ApiKey"]
        ?? throw new InvalidOperationException("PayVelix API key is missing.");
    options.BaseUrl = "https://api.payvelix.com";
    options.Timeout = TimeSpan.FromSeconds(30);
});

Inject IPayVelixClient as before:

using PayVelix;
using PayVelix.Contracts.Payments;

public sealed class PaymentService(IPayVelixClient payVelix)
{
    public Task<CreatePaymentResponse> CreateAsync(
        CreatePaymentRequest request,
        CancellationToken cancellationToken)
    {
        return payVelix.Payments.CreateAsync(request, cancellationToken);
    }
}

Multi-Tenant Configuration

AddPayVelix also registers IPayVelixClientFactory. Use it when each merchant has a different API key loaded dynamically from a database, vault, or secret store.

Configure shared defaults once:

builder.Services.AddPayVelix(options =>
{
    options.ApiKey = builder.Configuration["PayVelix:FallbackApiKey"]!;
    options.BaseUrl = "https://api.payvelix.com";
    options.Timeout = TimeSpan.FromSeconds(30);
});

Do not place every merchant API key in appsettings.json. Store merchant keys in your platform database or secret store, retrieve the key for the current merchant, and pass it to the factory.

Creating A Client For A Merchant

using PayVelix;
using PayVelix.Contracts.Payments;

public interface IMerchantSecretStore
{
    Task<string> GetPayVelixApiKeyAsync(string merchantId, CancellationToken cancellationToken);
}

public sealed class MerchantPaymentGateway(
    IPayVelixClientFactory payVelixClientFactory,
    IMerchantSecretStore merchantSecretStore)
{
    public async Task<CreatePaymentResponse> CreatePaymentAsync(
        string merchantId,
        CreatePaymentRequest request,
        CancellationToken cancellationToken)
    {
        var merchantApiKey = await merchantSecretStore.GetPayVelixApiKeyAsync(
            merchantId,
            cancellationToken);

        var payVelix = payVelixClientFactory.CreateClient(merchantApiKey);

        return await payVelix.Payments.CreateAsync(request, cancellationToken);
    }
}

Advanced callers can override base URL or timeout per created client:

var payVelix = payVelixClientFactory.CreateClient(new PayVelixClientConfiguration
{
    ApiKey = merchantApiKey,
    BaseUrl = "https://sandbox-api.example.com",
    Timeout = TimeSpan.FromSeconds(15)
});

The factory validates that API keys are not blank, base URLs are absolute HTTP or HTTPS URLs, and timeout values are greater than zero.

Creating Payments

using PayVelix.Contracts.Payments;

var payment = await payVelix.Payments.CreateAsync(
    new CreatePaymentRequest
    {
        IdempotencyKey = orderId,
        Amount = 25.50m,
        Currency = "USD",
        ReturnUrl = $"https://example.com/payments/return?orderId={orderId}",
        WebhookUrl = "https://example.com/webhooks/payvelix",
        CallbackParams = new Dictionary<string, string>
        {
            ["orderId"] = orderId
        }
    },
    cancellationToken);

Amount must be greater than zero. IdempotencyKey must be supplied either on the request or through the explicit overload:

var payment = await payVelix.Payments.CreateAsync(
    request,
    explicitIdempotencyKey,
    cancellationToken);

The explicit idempotency key overload takes precedence. The SDK sends the idempotency key through the Idempotency-Key HTTP header, not in the JSON body.

CreatePaymentResponse includes:

Property Purpose
PaymentId Permanent PayVelix provider transaction reference. Persist this in your order or transaction table.
PaymentLink Redirect URL for the customer's checkout. Persist it if your application needs to resume an incomplete checkout.
ExpiresAt Indicates how long the payment link remains usable.

The verify endpoint does not reconstruct or return the original payment link unless the PayVelix API itself supports that behavior. Do not assume PaymentLink can always be rebuilt from PaymentId.

Return URL Versus Webhook

ReturnUrl and WebhookUrl serve different roles:

Field Purpose
ReturnUrl Browser redirect URL used after the customer completes or leaves checkout.
WebhookUrl Server-to-server notification endpoint used by PayVelix to notify your application.

Always verify the payment through the PayVelix verify endpoint before marking an order as paid. Browser redirects and webhooks may arrive multiple times or in any order, so webhook processing must be idempotent.

The SDK does not implement webhook signature verification because no PayVelix webhook signature mechanism is defined in the current API surface.

Verifying Payments

using PayVelix.Contracts.Payments;

var payment = await payVelix.Payments.VerifyAsync(paymentId, cancellationToken);

if (payment.Status == VerifyPaymentStatus.Paid)
{
    // Mark the order as paid.
}

Current VerifyPaymentStatus values:

Status General handling
Pending Payment is still pending or processing. Wait and verify again later.
Paid Payment completed successfully.
Mismatch Payment requires manual review because the paid amount or expected amount does not match.
Expired Payment link or payment attempt expired. Treat as terminal unless a new payment is created.
Cancelled Payment was cancelled. Treat as terminal unless a new payment is created.

The SDK returns the typed status and does not collapse non-paid states into a generic failure. Your application should decide whether to wait, retry, reject, cancel, or manually review the transaction.

Idempotency

Payment creation is a financial operation and should be idempotent. Use a stable idempotency key for the same logical payment attempt, such as your order ID or payment attempt ID. Reuse the same key across retries so the PayVelix API can return the same payment instead of creating duplicates.

Error Handling

For non-successful PayVelix API responses, the SDK throws PayVelixApiException:

using PayVelix.Contracts.Common;

try
{
    var payment = await payVelix.Payments.VerifyAsync(paymentId, cancellationToken);
}
catch (PayVelixApiException ex)
{
    logger.LogWarning(
        "PayVelix request failed. StatusCode: {StatusCode}, ErrorCode: {ErrorCode}",
        ex.StatusCode,
        ex.ErrorCode);
}

Useful exception properties:

Property Description
StatusCode HTTP status code returned by the API.
ErrorCode PayVelix error code, when available.
ResponseBody Raw response body for troubleshooting. The SDK redacts the request API key if it appears in the body.

Failure categories:

  • Invalid SDK arguments throw ArgumentException, ArgumentNullException, or ArgumentOutOfRangeException.
  • HTTP and network failures are surfaced by HttpClient exceptions.
  • PayVelix API errors throw PayVelixApiException.
  • Successful HTTP responses with empty, invalid, or malformed payloads throw PayVelixApiException.
  • Cancellation requested through the supplied cancellation token remains OperationCanceledException or TaskCanceledException and is not converted to PayVelixApiException.

Security Considerations

  • Do not log, serialize, or expose merchant API keys.
  • Multi-tenant clients add X-Api-Key directly to each outgoing request instead of shared HttpClient.DefaultRequestHeaders.
  • Factory-created clients are lightweight; IHttpClientFactory manages the underlying handlers.
  • Do not cache clients by raw API key unless your application has a specific need and the cache cannot expose or retain secrets unnecessarily.
  • Store merchant API keys in a database or secret store designed for sensitive values, not in application configuration files.

Get Balance

var balance = await payVelix.Balance.GetAsync(cancellationToken: cancellationToken);

When id is null or empty, the SDK calls /api/Balance. When an id is provided, it calls /api/Balance?id={value} with the value URL-escaped before being sent.

Models

CreatePaymentRequest

Property Type Description
IdempotencyKey string? Required for create-payment calls unless passed to the explicit overload. Sent as the Idempotency-Key header, not in the JSON body.
ReturnUrl string? URL where the customer is redirected after payment.
Amount decimal Payment amount. Must be greater than zero.
Currency string Currency code. Defaults to USDT.
WebhookUrl string? URL that receives PayVelix webhook callbacks.
CallbackParams Dictionary<string, string>? Custom parameters for tracking orders or callback context.

CreatePaymentResponse

Property Type
PaymentId Guid
Amount decimal
PaymentLink string
ExpiresAt DateTimeOffset
AdditionalData Dictionary<string, JsonElement>?

VerifyPaymentResponse

Property Type
PaymentId Guid
Amount decimal
PaidAmount decimal
FeeAmount decimal
ExpectedAmount decimal
MerchantReceivableAmount decimal
Currency string?
Network string?
Status VerifyPaymentStatus
ExpiresAt DateTimeOffset
AdditionalData Dictionary<string, JsonElement>?

BalanceResponse

Property Type
Currencies Dictionary<string, decimal>?
UsdEquivalent decimal
AdditionalData Dictionary<string, JsonElement>?

Build And Test

dotnet restore .\PayVelix.sln
dotnet build .\PayVelix.sln --configuration Release
dotnet test .\PayVelix.sln --configuration Release

Package Release

Package versions are controlled by Git tags. Publishing a GitHub release or pushing a tag named v1.1.0 publishes NuGet packages with version 1.1.0.

The publish workflow restores, builds, tests, packs PayVelix.Contracts before PayVelix, publishes symbols packages, and uses NuGet.org Trusted Publishing through GitHub OIDC.

Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on PayVelix.Contracts:

Package Downloads
PayVelix

.NET SDK for the PayVelix merchant payment API.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 150 7/29/2026
1.0.0 123 7/29/2026

Contracts for the PayVelix .NET SDK 1.1.0 release.