Official SDKs and extensions
Install an official SellApp SDK, read your first product, and find community integrations.
An SDK is a library that handles API requests and responses for your application. You can also use the cURL quickstart or your language's HTTP client.
Official SDKs
Use an official SDK to work with products, orders, customers, and subscriptions from your server. The SDKs include typed requests and responses, pagination, and structured errors. They use API keys to connect to your store.
| Language | Package | Source and reference | Get started |
|---|---|---|---|
| Node.js / TypeScript | @sell.app/sdk on npm | GitHub · Method reference | Install · First request |
| Python | sellapp-sdk on PyPI | GitHub · Method reference | Install · First request |
| C# / .NET | SellApp on NuGet | GitHub · Method reference | Install · First request |
| PHP | sellapp/sellapp on Packagist | GitHub · Method reference | Install · First request |
| Go | github.com/sellapp/sellapp-go on Go package reference | GitHub · Method reference | Install · First request |
| Kotlin / JVM | app.sell:sellapp on Maven Central | GitHub · Method reference | Install · First request |
| Ruby | sellapp on RubyGems | GitHub · Method reference | Install · First request |
| Rust | sellapp-sdk on crates.io | GitHub · Method reference | Install · First request |
| Elixir | sellapp on Hex | GitHub · HexDocs · Method reference | Install · First request |
Node.js and TypeScript
Install
Use Node.js 20 or newer, preferably a currently supported release. In your server-side application's directory, run:
npm install @sell.app/sdkThe package supports ES modules and CommonJS, with TypeScript declarations for
both. For CommonJS, import it with const { SellApp } = require('@sell.app/sdk').
Read your first product
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to your target store. Keep the key out of browser code and source control. See
authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. Save the following as
first-request.mjs, then run node first-request.mjs in your application:
import { SellApp } from '@sell.app/sdk';// Explicit endpoint selection keeps examples from accidentally calling a live store.const baseUrl = process.env.SELLAPP_API_BASE_URL;if (!baseUrl) throw new Error('Set SELLAPP_API_BASE_URL before running this example');const client = new SellApp({ baseUrl }); // Reads SELLAPP_API_KEY and SELLAPP_STORE.const page = await client.products.list({ limit: 1 });for (const product of page.data) { console.log(product.id, product.title);}if (page.data.length === 0) console.log('No products yet. The request worked!');The program prints the product's ID and title. If your store has no products,
No products yet. The request worked! confirms the request succeeded.
The SDK reads your key and store from the environment; this example passes
SELLAPP_API_BASE_URL explicitly to choose the API address.
If the request fails, check your key for 401, the key's listing ability and
store permissions for 403, or the store slug and resource ID for 404.
Follow the response's retry guidance for 429. Keep the request ID when asking
for help, and never share your API key. See errors and the
SDK's error example.
Next, use the method reference to find an operation, or read the pagination and configuration guide. Prefer terminal commands? Use the official CLI, which connects with browser login.
Python
Use synchronous or asynchronous clients in your server-side Python application. Keep your API key on your server and out of source control.
Install Python
Use Python 3.10 or newer, preferably a currently supported release. In your application's directory, create a virtual environment to keep its packages separate:
python -m venv .venvActivate it with . .venv/bin/activate on macOS or Linux, or
.venv\Scripts\Activate.ps1 in Windows PowerShell. Then install the SDK:
python -m pip install sellapp-sdkThe package name is sellapp-sdk; Python code imports it as sellapp_sdk.
Read your first product with Python
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to your target store. See authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set these
with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
Save the following as first_request.py, then run python first_request.py
with your virtual environment active:
import osfrom sellapp_sdk import SellAppClientbase_url = os.environ["SELLAPP_API_BASE_URL"]if not base_url.strip(): raise ValueError("Set a nonempty SELLAPP_API_BASE_URL before running this example")with SellAppClient(base_url=base_url) as client: page = client.products.list(limit=1) for product in page.data: print(product.id, product.title) if not page.data: print("No products yet. Your connection is ready.")The program prints the product's ID and title. If your store has no products,
No products yet. Your connection is ready. confirms the request succeeded.
The products are in page.data, and the with block closes the HTTP client
after use. The SDK reads your key and store from the environment; this example
passes SELLAPP_API_BASE_URL explicitly to choose the API address.
If the request fails, check your key for 401, the key's listing ability and
store permissions for 403, or the store slug and resource ID for 404.
Follow the response's retry guidance for 429. If the error includes a request
ID, keep it when asking for help, and never share your API key. See
errors and the
SDK's error example.
Next, use the method reference to find an operation, read the pagination and configuration guide, or try the asynchronous first request.
C# and .NET
Use asynchronous methods and typed responses in your server-side .NET application. Keep your API key on your server and out of source control.
Install .NET
Use the .NET 8 SDK or later. In an existing application, run:
dotnet add package SellApp --version 0.1.1For 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.1Read your first product with C#
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to your target store. See authentication for setup and permissions.
In PowerShell, replace the key and store slug:
$env:SELLAPP_API_KEY = 'replace-with-your-key'
$env:SELLAPP_STORE = 'launch-lab'
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api'In a Bash-compatible terminal, use export SELLAPP_API_KEY='replace-with-your-key',
export SELLAPP_STORE='launch-lab', and
export SELLAPP_API_BASE_URL='https://sell.app/api' instead.
For launch-lab.sell.app, the store slug is launch-lab.
Replace your application's Program.cs with the following program, then run
dotnet run from the application directory:
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; } }}The program prints the product's ID and title. If your store has no products,
No products yet. Your connection is ready. confirms the request succeeded.
Products are in page.Data. The using statement closes the client after use,
and the cancellation token limits the request to 30 seconds. The example requires
all three environment variables before sending a request.
If the request fails, check your key for 401, its listing ability and your
store permissions for 403, or the store slug and resource ID for 404.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors.
Next, use the method reference to find an operation, or read the pagination and configuration guide.
PHP
Use typed requests and responses in your server-side PHP application. Keep your API key on your server and out of source control.
Install PHP
Use PHP 8.2 or newer within PHP 8 and Composer 2. From your application's directory, install the SDK:
composer require 'sellapp/sellapp:^0.1.1'Composer installs Guzzle, the HTTP client used by the SDK, and checks the required PHP extensions.
Read your first product with PHP
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to your target store. See authentication for setup and permissions.
Create an examples/ directory beside your application's vendor/ directory.
Save this complete program as examples/first-request.php:
<?phpdeclare(strict_types=1);require __DIR__ . '/../vendor/autoload.php';use SellApp\Client;$baseUrl = getenv('SELLAPP_API_BASE_URL');if (!$baseUrl) { throw new RuntimeException('Set SELLAPP_API_BASE_URL before running this example');}$client = new Client(baseUrl: $baseUrl); // Reads SELLAPP_API_KEY and SELLAPP_STORE.$page = $client->products()->list(limit: 1);foreach ($page->data as $product) { echo $product->id . ' ' . $product->title . PHP_EOL;}if ($page->data === []) { echo 'No products yet. The request worked!' . PHP_EOL;}In a Bash-compatible terminal, replace the key and store slug, then run the program from your application's root directory:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'
php examples/first-request.phpFor launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set
the environment variables with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
The program prints the product's ID and title. If your store has no products,
No products yet. The request worked! confirms the request succeeded.
Products are in $page->data. The SDK reads your key and store from the
environment; the example passes SELLAPP_API_BASE_URL explicitly to choose
the API address.
If the request fails, check your key for 401, its listing ability and your
store permissions for 403, or the store slug and resource ID for 404.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors and the
SDK's error example.
Next, use the method reference to find an operation, or read the pagination and configuration guide.
Go
Use typed responses and cancellable requests in your server-side Go application.
Install Go
Use Go 1.23 or newer. In an existing Go module, install this SDK version:
go get github.com/sellapp/sellapp-go@v0.1.1For a new application, create the directory and module first:
mkdir sellapp-example
cd sellapp-example
go mod init example.com/sellapp-example
go get github.com/sellapp/sellapp-go@v0.1.1Go records the module and its checksum in go.mod and go.sum.
Read your first product with Go
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to the store you want to read.
Keep the key on your server and out of source control. See
authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set
these with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
Save this complete program as main.go in your application directory, then run
go run .:
package mainimport ( "context" "errors" "fmt" "io" "os" "time" "github.com/sellapp/sellapp-go")func firstRequest(ctx context.Context, client *sellapp.Client, out io.Writer) error { limit := 1 products := client.Products().List(ctx, &sellapp.ProductsListParams{Limit: &limit}) if products.Next() { product := products.Current() fmt.Fprintf(out, "%d: %s\n", product.ID, product.Title) } else if products.Err() == nil { fmt.Fprintln(out, "No products yet. Your connection is ready.") } return products.Err()}func paginate(ctx context.Context, client *sellapp.Client, out io.Writer) error { limit := 15 products := client.Products().List(ctx, &sellapp.ProductsListParams{Limit: &limit}) // Keep this example bounded: inspect at most 30 products. for count := 0; count < 30 && products.Next(); count++ { fmt.Fprintf(out, "%d: %s\n", products.Current().ID, products.Current().Title) } return products.Err()}func reportError(err error, out io.Writer) { var authentication *sellapp.AuthenticationError var rateLimit *sellapp.RateLimitExceededError var timeout *sellapp.TimeoutError switch { case errors.As(err, &authentication): fmt.Fprintf(out, "Check the API key and store: %s (request %s)\n", authentication.Message, authentication.RequestID) case errors.As(err, &rateLimit): fmt.Fprintf(out, "Rate limited: %s (request %s)\n", rateLimit.Message, rateLimit.RequestID) case errors.As(err, &timeout): fmt.Fprintln(out, "Request timed out:", timeout) default: fmt.Fprintln(out, "Request failed:", err) }}func run(out io.Writer) error { // An explicit URL keeps accidental example runs from reaching production. baseURL := os.Getenv("SELLAPP_API_BASE_URL") if baseURL == "" || os.Getenv("SELLAPP_API_KEY") == "" || os.Getenv("SELLAPP_STORE") == "" { return fmt.Errorf("set SELLAPP_API_BASE_URL, SELLAPP_API_KEY, and SELLAPP_STORE") } client := sellapp.NewClient("", "", sellapp.WithBaseURL(baseURL), sellapp.WithMaxRetries(0)) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if os.Getenv("SELLAPP_EXAMPLE_MODE") == "pagination" { return paginate(ctx, client, out) } return firstRequest(ctx, client, out)}func main() { if err := run(os.Stdout); err != nil { reportError(err, os.Stderr) os.Exit(1) }}The program prints a product's ID and title. If your store has no products,
No products yet. Your connection is ready. confirms the request succeeded.
The client reads your API key and store from the environment. The example passes
SELLAPP_API_BASE_URL explicitly and limits the operation to 30 seconds.
products.Next() advances the iterator, products.Current() returns the
product, and products.Err() distinguishes an empty result from a failed request.
The program's default mode reads one product; its separate pagination mode
reads at most 30.
If the request fails, check your key for 401. For 403, check its
listing ability, allowed stores, and your current store permissions.
For 404, check the store slug.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors.
Next, browse the Go package reference or the method reference. See the pagination and configuration guide for retries and bounded iteration.
Kotlin and JVM
Use blocking methods or Kotlin coroutines in your server-side JVM application.
Install Kotlin
Install JDK 17 and Gradle 8.9 for the example below. The Gradle project selects and downloads Kotlin 2.1.20; a separate Kotlin compiler installation is not required. In an existing Gradle project, add Maven Central and the SDK dependency:
repositories { mavenCentral() }
dependencies {
implementation("app.sell:sellapp:0.1.1")
}For a complete runnable example, create an empty project directory. Save this
as settings.gradle.kts:
rootProject.name = "sellapp-example"Save this as build.gradle.kts. The additional dependencies are used directly
by the example's HTTP client and coroutine mode:
plugins {
kotlin("jvm") version "2.1.20"
application
}
repositories { mavenCentral() }
dependencies {
implementation("app.sell:sellapp:0.1.1")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1")
}
kotlin { jvmToolchain(17) }
application { mainClass.set("sellapp.examples.OnboardingKt") }Read your first product with Kotlin
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to the store you want to read.
Keep the key on your server and out of source control. See
authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set
these with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
Create src/main/kotlin/ in the example project. Save this complete program as
src/main/kotlin/Onboarding.kt, then run gradle run from the project directory:
package sellapp.examplesimport app.sell.sellapp.SellAppimport app.sell.sellapp.common.exceptions.SellAppApiExceptionimport app.sell.sellapp.common.exceptions.SellAppSerializationExceptionimport app.sell.sellapp.common.exceptions.SellAppTimeoutExceptionimport kotlinx.coroutines.runBlockingimport okhttp3.OkHttpClientimport app.sell.sellapp.types.CatalogVisibilityimport app.sell.sellapp.common.http.PatchFieldfun firstRequest(client: SellApp): String { val product = client.products.list(limit = 1).data.firstOrNull() ?: return "No products yet. Your connection is ready." return "${product.id}: ${product.title}"}suspend fun firstRequestSuspend(client: SellApp): String { val product = client.products.listSuspend(limit = 1).data.firstOrNull() ?: return "No products yet. Your connection is ready." return "${product.id}: ${product.title}"}fun inspectProducts(client: SellApp): String { return try { client.products.list(limit = 1).take(30).joinToString("\n") { "${it.id}: ${it.title}" }.ifEmpty { "No products yet." } } catch (error: SellAppSerializationException) { "Product pages could not be decoded safely: ${error.message}." }}fun catalogWorkflow(client: SellApp): Long { // This changes real catalog data outside the local fixture test. val created = client.products.create(title = "Design kit", description = "Templates for your next project.", visibility = CatalogVisibility.Hidden) val product = client.products.get(created.data.id.toString()) return client.products.update(product.data.id.toString(), title = PatchField.Present("Design kit revised")).data.id}suspend fun catalogWorkflowSuspend(client: SellApp): Long { val created = client.products.createSuspend(title = "Design kit", description = "Templates for your next project.", visibility = CatalogVisibility.Hidden) val product = client.products.getSuspend(created.data.id.toString()) return client.products.updateSuspend(product.data.id.toString(), title = PatchField.Present("Design kit revised")).data.id}fun checkout(client: SellApp, orderId: String): Long { // Creates a provider checkout; inspect the order before retrying a lost response. val order = client.orders.get(orderId) return client.orders.createCheckout(order.data.id.toString()).data.id}fun upload(client: SellApp, productId: String, variantId: String, file: ByteArray): Long { val uploaded = client.variantDeliverableFiles.upload(productId, variantId, file) return client.variantDeliverableFiles.get(productId, variantId, uploaded.data.id.toString()).data.id}suspend fun checkoutSuspend(client: SellApp, orderId: String): Long { val order = client.orders.getSuspend(orderId) return client.orders.createCheckoutSuspend(order.data.id.toString()).data.id}suspend fun uploadSuspend(client: SellApp, productId: String, variantId: String, file: ByteArray): Long { val uploaded = client.variantDeliverableFiles.uploadSuspend(productId, variantId, file) return client.variantDeliverableFiles.getSuspend(productId, variantId, uploaded.data.id.toString()).data.id}fun describeError(error: Exception): String = when (error) { is SellAppApiException -> "API status ${error.status}: ${error.message} (request ${error.requestId ?: "unavailable"})" is SellAppTimeoutException -> "Request timed out: ${error.message}" else -> "Request failed: ${error.message}"}fun main(args: Array<String>) { fun required(name: String): String = System.getenv(name)?.takeIf { it.isNotBlank() } ?: error("Set $name before running this example.") val http = OkHttpClient() try { val client = SellApp( apiKey = required("SELLAPP_API_KEY"), store = required("SELLAPP_STORE"), baseUrl = required("SELLAPP_API_BASE_URL"), maxRetries = 0, httpClient = http, ) val result = when (args.firstOrNull()) { "suspend" -> runBlocking { firstRequestSuspend(client) } "pagination" -> inspectProducts(client) else -> firstRequest(client) } println(result) } catch (error: Exception) { System.err.println(describeError(error)) throw error } finally { http.dispatcher.executorService.shutdown() http.connectionPool.evictAll() http.cache?.close() }}Running the program without arguments reads one product and prints its ID and
title. No products yet. Your connection is ready. means an empty store was
read successfully. Products are in page.data. The program requires all three
environment variables and closes its HTTP client after use.
The complete example also contains catalog, checkout, and upload helper functions.
Those helpers can change real data if you call them; gradle run does not call
them. Use gradle run --args=suspend to perform the same read with a coroutine.
If the request fails, check your key for 401. For 403, check its
listing ability, allowed stores, and your current store permissions.
For 404, check the store slug.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors.
Next, use the method reference to find an operation, or read the pagination and configuration guide. The example project also includes a Gradle launcher.
Ruby
Use Ruby objects, pagination, and typed errors in your server-side application.
Install Ruby
Use Ruby 3.1.7 or newer and Bundler. Add these lines to your application's
Gemfile:
source "https://rubygems.org"
gem "sellapp", "~> 0.1.1"Run bundle install from the application directory. For a new application,
create an empty directory and save the two lines above as Gemfile first.
Bundler records the selected versions in Gemfile.lock.
Read your first product with Ruby
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to the store you want to read.
Keep the key on your server and out of source control. See
authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set
these with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
Save this complete program as first-request.rb in your application directory,
then run bundle exec ruby first-request.rb:
# frozen_string_literal: truerequire "sellapp"base_url = ENV.fetch("SELLAPP_API_BASE_URL")raise "Set SELLAPP_API_BASE_URL before running this example" if base_url.empty?client = SellApp::Client.new(base_url: base_url) # Reads SELLAPP_API_KEY and SELLAPP_STORE.page = client.products.list(limit: 1)page.data.each { |product| puts "#{product.id} #{product.title}" }puts "No products yet. The request worked!" if page.data.empty?The program prints the product's ID and title. If your store has no products,
No products yet. The request worked! confirms the request succeeded.
Products are in page.data. The client reads your API key and store from the
environment; this example passes SELLAPP_API_BASE_URL explicitly.
The first program stops if the request fails. The error example shows how to catch API, timeout, and transport errors.
If the request fails, check your key for 401. For 403, check its
listing ability, allowed stores, and your current store permissions.
For 404, check the store slug.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors.
Next, use the method reference to find an operation, or read the pagination and configuration guide.
Rust
Use asynchronous requests and typed responses in your server-side Rust application.
Install Rust
Use a current stable Rust toolchain. The SDK uses Rust edition 2024; a minimum supported Rust version for the complete dependency graph has not been established.
On Linux, the SDK's HTTPS dependency also needs OpenSSL development headers and
pkg-config. On Debian or Ubuntu, install them before building:
sudo apt-get install pkg-config libssl-devFor other Linux distributions, see the OpenSSL build requirements.
Create a new application, then add the SDK and Tokio, the runtime that executes the asynchronous example:
cargo new sellapp-example
cd sellapp-example
cargo add sellapp-sdk@0.1.1 --rename sellapp
cargo add tokio@1 --features macros,rt-multi-threadThe published crate is sellapp-sdk. The dependency is named sellapp in
your application, matching the code's imports. Your Cargo.toml dependencies
will include:
[dependencies]
sellapp = { package = "sellapp-sdk", version = "0.1.1" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }Read your first product with Rust
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to the store you want to read.
Keep the key on your server and out of source control. See
authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set
these with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
Replace src/main.rs with this complete program, then run cargo run from
your application directory:
use sellapp::{Client, Error};use sellapp::resources::products::ListParams;pub async fn first_request(client: &Client) -> Result<Vec<(i64, String)>, Error> { let page = client.products().list(ListParams { limit: Some(1), ..Default::default() }).await?; let products: Vec<_> = page.data.into_iter().map(|p| (p.id, p.title)).collect(); for (id, title) in &products { println!("{id}: {title}"); } if products.is_empty() { println!("No products yet. Your connection is ready."); } Ok(products)}#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { // Require a deliberate destination for this runnable example. let base_url = std::env::var("SELLAPP_API_BASE_URL")?; let client = Client::from_env()?.with_base_url(base_url).with_max_retries(0); first_request(&client).await?; Ok(())}The program prints the product's ID and title. If your store has no products,
No products yet. Your connection is ready. confirms the request succeeded.
Products are in page.data. Client::from_env() reads your API key and store;
the example passes SELLAPP_API_BASE_URL explicitly and disables retries.
.await waits for the response, and ? returns a failure to the caller.
The error example
shows how to inspect typed failures and request IDs.
If the request fails, check your key for 401. For 403, check its
listing ability, allowed stores, and your current store permissions.
For 404, check the store slug.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors.
Next, use the method reference to find an operation, or read the pagination and configuration guide.
Elixir
Use Elixir structs and explicit success or error results in your server-side application.
Install Elixir
These instructions use Elixir 1.20.4 with Erlang/OTP 28.4 and Mix, Elixir's build tool.
In an existing Mix application, add the SDK to the deps/0 list in mix.exs:
defp deps do
[
{:sellapp, "~> 0.1.1"}
]
endKeep your application's existing dependencies in that list. Run mix deps.get
to download the SDK from Hex.
For a new application, run these commands first, then add the dependency above:
mix new sellapp_example
cd sellapp_exampleRead your first product with Elixir
This request reads at most one product. It does not create data or charge anyone.
Create a server-side key in API keys.
Enable its listing ability and allow access to the store you want to read.
Keep the key on your server and out of source control. See
authentication for setup and permissions.
In a Bash-compatible terminal, replace the key and store slug:
export SELLAPP_API_KEY='replace-with-your-key'
export SELLAPP_STORE='launch-lab'
export SELLAPP_API_BASE_URL='https://sell.app/api'For launch-lab.sell.app, the store slug is launch-lab. In PowerShell, set
these with $env:SELLAPP_API_KEY = 'replace-with-your-key',
$env:SELLAPP_STORE = 'launch-lab', and
$env:SELLAPP_API_BASE_URL = 'https://sell.app/api' instead.
Save this complete program as first-request.exs in your application directory,
then run mix run first-request.exs:
base_url = System.fetch_env!("SELLAPP_API_BASE_URL")if base_url == "", do: raise("Set SELLAPP_API_BASE_URL before running this example")client = SellApp.client(base_url: base_url)# Credentials come from SELLAPP_API_KEY and SELLAPP_STORE.{:ok, page} = SellApp.Products.list(client, %{limit: 1})Enum.each(page.data, fn product -> IO.puts("#{product.id} #{product.title}") end)if page.data == [], do: IO.puts("No products yet. The request worked!")The program prints the product's ID and title. If your store has no products,
No products yet. The request worked! confirms the request succeeded.
SellApp.client/1 reads your API key and store from the environment;
the example passes SELLAPP_API_BASE_URL explicitly.
The {:ok, page} match unwraps a successful response, and page.data is
the list of product structs. This first program stops if the request fails.
The error example
uses case to handle {:error, error} results.
If the request fails, check your key for 401. For 403, check its
listing ability, allowed stores, and your current store permissions.
For 404, check the store slug.
Follow the response's retry guidance for 429. Keep any request ID when asking
for help, and never share your API key. See errors.
Next, use the HexDocs reference or the method reference to find an operation, or read the pagination and configuration guide.
Community SDKs & extensions
Before choosing a community package, check which API versions and endpoints it
supports, how it sends X-STORE, and how it handles errors and retries. Compare
its requests with this reference; a convenient wrapper may not cover every endpoint.
Note
These community packages are not officially endorsed. Review their maintenance status and compatibility before adding one to your project. Never expose a secret API key in a browser-based integration.
Node.js by t6c
A community-maintained Node.js wrapper for the SellApp API.
Python by qoft
A community-maintained Python package for interacting with SellApp.
.NET by biitez
A community-maintained .NET integration for SellApp.
React by 6ichem
A community-maintained React integration for SellApp storefront flows.
Embedding SellApp products
SellApp offers an official embed solution that lets you place product purchase flows directly on your own website. Once embedded, customers can complete purchases without being redirected to your storefront.
For setup instructions, see the Embedding products guide in the main help documentation.