SellApp 0.1.1

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

SellApp .NET SDK

Read your catalog, connect store data to another service, or build your next checkout flow in C#. The SellApp SDK turns async method calls into API requests and responses into objects you can work with.

Let's start with one product's name in your terminal. A small request, a useful answer, and no changes to your store.

Already know your way around? Jump to configuration, usage details, or the method index.

Install

The SDK requires .NET 8 or later. Install SellApp from NuGet. From an existing project directory:

dotnet add package SellApp --version 0.1.1

For a new console application, create the project first:

dotnet new console --name SellAppExample --framework net8.0
cd SellAppExample
dotnet add package SellApp --version 0.1.1

Your first request

Your request needs an API key to identify you and a store slug to select your store. Give the key the listing ability, which grants access to the catalog. For example-store.sell.app, the slug is example-store. The authentication guide helps you get both ready.

Set SELLAPP_API_KEY and SELLAPP_STORE as environment variables: settings passed to your program rather than saved in its source. Keep the key out of Git history. Replace your application's Program.cs with the program below. Then replace the fictitious values and run these commands in a Bash-compatible shell:

export SELLAPP_API_KEY=sk_example_replace_me
export SELLAPP_STORE=example-store
export SELLAPP_API_BASE_URL=https://sell.app/api
dotnet run

You should see a product's ID and title. If the store is empty, the program says so; that still means the request worked. The URL points at your real store, so the example asks you to choose it explicitly. SELLAPP_API_BASE_URL is an example setting, not an SDK environment setting, and an unconfigured run stops before making a request.

Here's the onboarding program. Start with FirstRequestAsync: it waits for the response and reads products from page.Data. The remaining methods handle additional pages and failures, ready for when you need them.

using SellApp;
using Newtonsoft.Json.Linq;

namespace SellAppExamples;

public static class Onboarding
{
    public static async Task FirstRequestAsync(SellAppClient client, TextWriter output, CancellationToken ct)
    {
        var page = await client.Products.ListAsync(new ProductsListOptions { Limit = 1 }, cancellationToken: ct);
        foreach (var product in page.Data)
            await output.WriteLineAsync($"{product.Id}: {product.Title}");
        if (page.Data.Count == 0)
            await output.WriteLineAsync("No products yet. Your connection is ready.");
    }

    public static async Task PaginateAsync(SellAppClient client, TextWriter output, CancellationToken ct)
    {
        // Bound this example to three pages; ask for each page explicitly.
        for (var number = 1; number <= 3; number++)
        {
            var page = await client.Products.ListAsync(
                new ProductsListOptions { Limit = 15, Page = number }, cancellationToken: ct);
            foreach (var product in page.Data)
                await output.WriteLineAsync($"{product.Id}: {product.Title}");
            if (page.Meta?["current_page"]?.Value<int>() >= page.Meta?["last_page"]?.Value<int>())
                break;
        }
    }

    public static async Task<long> CatalogWorkflowAsync(SellAppClient client, CancellationToken ct)
    {
        // Creates and updates real catalog data when used outside the fixture tests.
        var created = await client.Products.CreateAsync(new ProductsCreateOptions {
            Title = "Design kit", Description = "Templates for your next project.", Visibility = new CatalogVisibility("HIDDEN")
        }, cancellationToken: ct);
        var product = await client.Products.GetAsync(created.Data.Id.ToString(), cancellationToken: ct);
        var updated = await client.Products.UpdateAsync(product.Data.Id.ToString(), new ProductsUpdateOptions {
            Title = "Design kit revised"
        }, cancellationToken: ct);
        return updated.Data.Id;
    }

    public static async Task<long> CheckoutAsync(SellAppClient client, string orderId, CancellationToken ct)
    {
        // Starts a real payment-provider checkout. Inspect current order state before retrying.
        var order = await client.Orders.GetAsync(orderId, cancellationToken: ct);
        var checkout = await client.Orders.CreateCheckoutAsync(order.Data.Id.ToString(), new OrdersCreateCheckoutOptions {}, cancellationToken: ct);
        return checkout.Data.Id;
    }

    public static async Task<long> UploadAsync(SellAppClient client, string productId, string variantId, byte[] file, CancellationToken ct)
    {
        var uploaded = await client.VariantDeliverableFiles.UploadAsync(productId, variantId, new VariantDeliverableFilesUploadOptions { File = file }, cancellationToken: ct);
        var saved = await client.VariantDeliverableFiles.GetAsync(productId, variantId, uploaded.Data.Id.ToString(), cancellationToken: ct);
        return saved.Data.Id;
    }

    public static string DescribeError(Exception error) => error switch
    {
        AuthenticationException e => $"Check your API key and store: {e.Message}",
        ApiException e => $"API status {e.Status}: {e.Message} (request {e.RequestId ?? "unavailable"})",
        SellAppTimeoutException e => $"Request timed out: {e.Message}",
        OperationCanceledException => "Request canceled.",
        _ => $"Request failed: {error.Message}",
    };

    public static async Task<int> Main(string[] args)
    {
        try
        {
            string Required(string name) => Environment.GetEnvironmentVariable(name) is { Length: > 0 } value
                ? value : throw new InvalidOperationException($"Set {name} before running this example.");
            using var client = new SellAppClient(new SellAppOptions
            {
                ApiKey = Required("SELLAPP_API_KEY"),
                Store = Required("SELLAPP_STORE"),
                BaseUrl = Required("SELLAPP_API_BASE_URL"),
                MaxRetries = 0,
            });
            using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
            if (args.Contains("pagination"))
                await PaginateAsync(client, Console.Out, cancellation.Token);
            else
                await FirstRequestAsync(client, Console.Out, cancellation.Token);
            return 0;
        }
        catch (Exception exception)
        {
            Console.Error.WriteLine(DescribeError(exception));
            return 1;
        }
    }
}

Account access and first-store setup

Create a user-owned key in API keys, even before you have a store. Enable account:read for identity, store discovery and permission inspection, and stores:create separately for store creation. Identity, discovery, store detail by ID and creation omit X-STORE; permission inspection and business requests select a store explicitly.

An unrestricted key covers current and future accessible stores. A selected-store key covers only its fixed list; an empty list covers none. Membership and role changes still apply. Selected-store keys cannot create stores. Existing keys do not gain abilities automatically; * satisfies the new abilities while retaining membership, role and restriction checks.

The account guide shows first-store creation, required idempotency keys, and bounded reads across several stores with partial failures. Creation returns an ID and slug; use the slug for subsequent product requests. Find your language's methods in the resource reference. CLI and MCP connections retain browser OAuth.

If the request fails

Result Next step
Empty product list The read succeeded. Create a product when you are ready.
401 Check the selected credential and whether it has expired or been revoked.
403 Check the key's listing ability, selected-store restrictions and the account's current store permissions. Official CLI OAuth also requires its active grant.
400 with a missing-store message Set SELLAPP_STORE to an authorized store slug.
429 Follow Retry-After and the SDK's documented retry behavior.

Keep the request ID when reporting an API failure. Never include credentials.

Three useful next actions

  1. Create and edit a product: exact signatures and complete examples.
  2. Read orders or create a checkout: inspect permissions and effects before changing a purchase.
  3. Read more than one page: pagination, request controls, errors, and retry behavior.

Reference and examples

Support and releases

Find available packages and installation instructions in the SDK guide. Report an SDK issue. Include the SDK version, runtime version, and a redacted reproduction. Licensed under MIT; see third-party notices.

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.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.1 102 9/19/2026